summaryrefslogtreecommitdiff
path: root/nonprism/pidgin-nonprism/nonprism.patch
diff options
context:
space:
mode:
Diffstat (limited to 'nonprism/pidgin-nonprism/nonprism.patch')
-rw-r--r--nonprism/pidgin-nonprism/nonprism.patch166577
1 files changed, 0 insertions, 166577 deletions
diff --git a/nonprism/pidgin-nonprism/nonprism.patch b/nonprism/pidgin-nonprism/nonprism.patch
index 448558a5f..485bef3c8 100644
--- a/nonprism/pidgin-nonprism/nonprism.patch
+++ b/nonprism/pidgin-nonprism/nonprism.patch
@@ -1157,27 +1157,6 @@ diff -Nur pidgin-2.10.7/doc/funniest_home_convos.txt pidgin-2.10.7-nonprism/doc/
18:34:43 <NoName> Whenever you transfer files between users, no receiving
confirmation is requested, the file gets transfered
automatically
-diff -Nur pidgin-2.10.7/doc/Makefile.in pidgin-2.10.7-nonprism/doc/Makefile.in
---- pidgin-2.10.7/doc/Makefile.in 2013-02-11 07:17:17.000000000 -0200
-+++ pidgin-2.10.7-nonprism/doc/Makefile.in 2013-08-17 00:02:41.026999785 -0300
-@@ -155,8 +155,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -218,8 +216,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
diff -Nur pidgin-2.10.7/doc/pidgin.1.in pidgin-2.10.7-nonprism/doc/pidgin.1.in
--- pidgin-2.10.7/doc/pidgin.1.in 2013-02-11 07:16:51.000000000 -0200
+++ pidgin-2.10.7-nonprism/doc/pidgin.1.in 2013-08-16 21:00:30.964181946 -0300
@@ -1194,90 +1173,6 @@ diff -Nur pidgin-2.10.7/doc/pidgin.1.in pidgin-2.10.7-nonprism/doc/pidgin.1.in
.PP
Pidgin can be extended by plugins written in multiple programming languages and
controlled through DBus or \fBpurple-remote\fR.
-diff -Nur pidgin-2.10.7/finch/libgnt/Makefile.in pidgin-2.10.7-nonprism/finch/libgnt/Makefile.in
---- pidgin-2.10.7/finch/libgnt/Makefile.in 2013-02-11 07:17:18.000000000 -0200
-+++ pidgin-2.10.7-nonprism/finch/libgnt/Makefile.in 2013-08-16 23:49:33.762819097 -0300
-@@ -233,8 +233,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -296,8 +294,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/finch/libgnt/wms/Makefile.in pidgin-2.10.7-nonprism/finch/libgnt/wms/Makefile.in
---- pidgin-2.10.7/finch/libgnt/wms/Makefile.in 2013-02-11 07:17:18.000000000 -0200
-+++ pidgin-2.10.7-nonprism/finch/libgnt/wms/Makefile.in 2013-08-16 23:49:49.779979208 -0300
-@@ -191,8 +191,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -254,8 +252,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/finch/Makefile.in pidgin-2.10.7-nonprism/finch/Makefile.in
---- pidgin-2.10.7/finch/Makefile.in 2013-02-11 07:17:18.000000000 -0200
-+++ pidgin-2.10.7-nonprism/finch/Makefile.in 2013-08-16 23:49:15.322251029 -0300
-@@ -233,8 +233,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -296,8 +294,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/finch/plugins/Makefile.in pidgin-2.10.7-nonprism/finch/plugins/Makefile.in
---- pidgin-2.10.7/finch/plugins/Makefile.in 2013-02-11 07:17:18.000000000 -0200
-+++ pidgin-2.10.7-nonprism/finch/plugins/Makefile.in 2013-08-16 23:50:13.010694932 -0300
-@@ -237,8 +237,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -300,8 +298,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
diff -Nur pidgin-2.10.7/libpurple/account.c pidgin-2.10.7-nonprism/libpurple/account.c
--- pidgin-2.10.7/libpurple/account.c 2013-02-11 07:16:51.000000000 -0200
+++ pidgin-2.10.7-nonprism/libpurple/account.c 2013-08-16 23:31:48.026518940 -0300
@@ -1371,17 +1266,6 @@ diff -Nur pidgin-2.10.7/libpurple/blist.c pidgin-2.10.7-nonprism/libpurple/blist
if (!acct_name || (!proto && !protocol))
return;
-@@ -967,10 +965,6 @@
- purple_blist_update_node_icon((PurpleBlistNode *)buddy);
- }
-
--/*
-- * TODO: Maybe remove the call to this from server.c and call it
-- * from oscar.c and toc.c instead?
-- */
- void purple_blist_rename_buddy(PurpleBuddy *buddy, const char *name)
- {
- PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
diff -Nur pidgin-2.10.7/libpurple/buddyicon.c pidgin-2.10.7-nonprism/libpurple/buddyicon.c
--- pidgin-2.10.7/libpurple/buddyicon.c 2013-02-11 07:16:51.000000000 -0200
+++ pidgin-2.10.7-nonprism/libpurple/buddyicon.c 2013-08-16 23:28:49.244233493 -0300
@@ -1404,60 +1288,6 @@ diff -Nur pidgin-2.10.7/libpurple/buddyicon.c pidgin-2.10.7-nonprism/libpurple/b
}
}
}
-diff -Nur pidgin-2.10.7/libpurple/certificate.c pidgin-2.10.7-nonprism/libpurple/certificate.c
---- pidgin-2.10.7/libpurple/certificate.c 2013-02-11 07:16:51.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/certificate.c 2013-08-17 00:24:11.603381489 -0300
-@@ -108,7 +108,7 @@
- "and time are accurate.");
- break;
- case PURPLE_CERTIFICATE_NAME_MISMATCH:
-- /* Translators: "domain" refers to a DNS domain (e.g. talk.google.com) */
-+ /* Translators: "domain" refers to a DNS domain */
- return _("The certificate presented is not issued to this domain.");
- break;
- case PURPLE_CERTIFICATE_NO_CA_POOL:
-diff -Nur pidgin-2.10.7/libpurple/ciphers/Makefile.in pidgin-2.10.7-nonprism/libpurple/ciphers/Makefile.in
---- pidgin-2.10.7/libpurple/ciphers/Makefile.in 2013-02-11 07:17:18.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/ciphers/Makefile.in 2013-08-16 23:52:56.489066605 -0300
-@@ -152,8 +152,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -215,8 +213,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/libpurple/example/Makefile.in pidgin-2.10.7-nonprism/libpurple/example/Makefile.in
---- pidgin-2.10.7/libpurple/example/Makefile.in 2013-02-11 07:17:18.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/example/Makefile.in 2013-08-16 23:52:31.591632423 -0300
-@@ -155,8 +155,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -218,8 +216,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
diff -Nur pidgin-2.10.7/libpurple/ft.h pidgin-2.10.7-nonprism/libpurple/ft.h
--- pidgin-2.10.7/libpurple/ft.h 2013-02-11 07:16:51.000000000 -0200
+++ pidgin-2.10.7-nonprism/libpurple/ft.h 2013-08-16 22:51:20.590085226 -0300
@@ -1490,27 +1320,6 @@ diff -Nur pidgin-2.10.7/libpurple/gaim-compat.h pidgin-2.10.7-nonprism/libpurple
-#define gaim_init_icq_plugin purple_init_icq_plugin
#endif /* _GAIM_COMPAT_H_ */
-diff -Nur pidgin-2.10.7/libpurple/gconf/Makefile.in pidgin-2.10.7-nonprism/libpurple/gconf/Makefile.in
---- pidgin-2.10.7/libpurple/gconf/Makefile.in 2013-02-11 07:17:18.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/gconf/Makefile.in 2013-08-16 23:53:07.209397103 -0300
-@@ -151,8 +151,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -214,8 +212,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
diff -Nur pidgin-2.10.7/libpurple/internal.h pidgin-2.10.7-nonprism/libpurple/internal.h
--- pidgin-2.10.7/libpurple/internal.h 2013-02-11 07:16:51.000000000 -0200
+++ pidgin-2.10.7-nonprism/libpurple/internal.h 2013-08-17 00:24:37.244172407 -0300
@@ -1523,200 +1332,6 @@ diff -Nur pidgin-2.10.7/libpurple/internal.h pidgin-2.10.7-nonprism/libpurple/in
*/
#ifdef ENABLE_NLS
# include <locale.h>
-diff -Nur pidgin-2.10.7/libpurple/Makefile.in pidgin-2.10.7-nonprism/libpurple/Makefile.in
---- pidgin-2.10.7/libpurple/Makefile.in 2013-02-11 07:17:18.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/Makefile.in 2013-08-16 23:52:14.487771867 -0300
-@@ -302,8 +302,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -365,8 +363,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/libpurple/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/Makefile.mingw
---- pidgin-2.10.7/libpurple/Makefile.mingw 2013-02-11 07:16:51.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,169 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of libpurple
--#
--
--PIDGIN_TREE_TOP := ..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = libpurple
--NEEDED_DLLS = $(LIBXML2_TOP)/bin/libxml2-2.dll
--
--ifeq ($(CYRUS_SASL), 1)
--NEEDED_DLLS += $(CYRUS_SASL_TOP)/bin/libsasl.dll
--
--CYRUS_SASL_PLUGINS = \
-- $(CYRUS_SASL_TOP)/bin/sasl2/saslANONYMOUS.dll \
-- $(CYRUS_SASL_TOP)/bin/sasl2/saslCRAMMD5.dll \
-- $(CYRUS_SASL_TOP)/bin/sasl2/saslDIGESTMD5.dll \
-- $(CYRUS_SASL_TOP)/bin/sasl2/saslGSSAPI.dll \
-- $(CYRUS_SASL_TOP)/bin/sasl2/saslLOGIN.dll \
-- $(CYRUS_SASL_TOP)/bin/sasl2/saslPLAIN.dll
--
--endif
--
--##
--## INCLUDE PATHS
--##
--INCLUDE_PATHS += \
-- -I$(PURPLE_TOP) \
-- -I$(PURPLE_TOP)/win32 \
-- -I$(PIDGIN_TREE_TOP) \
-- -I$(GTK_TOP)/include \
-- -I$(GTK_TOP)/include/glib-2.0 \
-- -I$(GTK_TOP)/lib/glib-2.0/include \
-- -I$(LIBXML2_TOP)/include/libxml2
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(LIBXML2_TOP)/lib
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = \
-- account.c \
-- accountopt.c \
-- blist.c \
-- buddyicon.c \
-- certificate.c \
-- cipher.c \
-- ciphers/des.c \
-- ciphers/gchecksum.c \
-- ciphers/hmac.c \
-- ciphers/md4.c \
-- ciphers/md5.c \
-- ciphers/rc4.c \
-- ciphers/sha1.c \
-- ciphers/sha256.c \
-- circbuffer.c \
-- cmds.c \
-- connection.c \
-- conversation.c \
-- core.c \
-- debug.c \
-- dnsquery.c \
-- dnssrv.c \
-- eventloop.c \
-- ft.c \
-- idle.c \
-- imgstore.c \
-- log.c \
-- mediamanager.c \
-- media.c \
-- mime.c \
-- nat-pmp.c \
-- network.c \
-- notify.c \
-- ntlm.c \
-- plugin.c \
-- pluginpref.c \
-- pounce.c \
-- prefs.c \
-- privacy.c \
-- proxy.c \
-- prpl.c \
-- request.c \
-- roomlist.c \
-- savedstatuses.c \
-- server.c \
-- signals.c \
-- smiley.c \
-- sound-theme-loader.c \
-- sound-theme.c \
-- sound.c \
-- sslconn.c \
-- status.c \
-- stringref.c \
-- stun.c \
-- theme-loader.c \
-- theme-manager.c \
-- theme.c \
-- upnp.c \
-- util.c \
-- value.c \
-- version.c \
-- whiteboard.c \
-- xmlnode.c \
-- win32/giowin32.c \
-- win32/libc_interface.c \
-- win32/win32dep.c
--
--RC_SRC = win32/libpurplerc.rc
--
--OBJECTS = $(C_SRC:%.c=%.o) $(RC_SRC:%.rc=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lgthread-2.0 \
-- -lgobject-2.0 \
-- -lgmodule-2.0 \
-- -lintl \
-- -lws2_32 \
-- -lxml2
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install install_shallow clean
--
--all: $(TARGET).dll
-- $(MAKE) -C $(PURPLE_PROTOS_TOP) -f $(MINGW_MAKEFILE)
-- $(MAKE) -C $(PURPLE_PLUGINS_TOP) -f $(MINGW_MAKEFILE)
--
--install_shallow: $(PURPLE_INSTALL_DIR) $(TARGET).dll
-- cp $(TARGET).dll $(PURPLE_INSTALL_DIR)
-- cp $(NEEDED_DLLS) $(PURPLE_INSTALL_DIR)
--ifeq ($(CYRUS_SASL), 1)
-- mkdir -p $(PURPLE_INSTALL_DIR)/sasl2
-- cp $(CYRUS_SASL_PLUGINS) $(PURPLE_INSTALL_DIR)/sasl2
--endif
--
--install: install_shallow all
-- $(MAKE) -C $(PURPLE_PROTOS_TOP) -f $(MINGW_MAKEFILE) install
-- $(MAKE) -C $(PURPLE_PLUGINS_TOP) -f $(MINGW_MAKEFILE) install
--
--./win32/libpurplerc.rc: ./win32/libpurplerc.rc.in $(PIDGIN_TREE_TOP)/VERSION
-- sed -e 's/@PURPLE_VERSION@/$(PURPLE_VERSION)/g' \
-- $@.in > $@
--
--$(OBJECTS): $(PURPLE_CONFIG_H) $(PURPLE_VERSION_H) $(PURPLE_PURPLE_H)
--
--$(TARGET).dll $(TARGET).dll.a: $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--output-def,$(TARGET).def,--out-implib,$(TARGET).dll.a -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -f $(OBJECTS) $(RC_SRC) $(PURPLE_VERSION_H) $(PURPLE_PURPLE_H)
-- rm -f $(TARGET).dll $(TARGET).dll.a $(TARGET).def
-- $(MAKE) -C $(PURPLE_PROTOS_TOP) -f $(MINGW_MAKEFILE) clean
-- $(MAKE) -C $(PURPLE_PLUGINS_TOP) -f $(MINGW_MAKEFILE) clean
--
--include $(PIDGIN_COMMON_TARGETS)
diff -Nur pidgin-2.10.7/libpurple/media/backend-fs2.c pidgin-2.10.7-nonprism/libpurple/media/backend-fs2.c
--- pidgin-2.10.7/libpurple/media/backend-fs2.c 2013-02-11 07:16:51.000000000 -0200
+++ pidgin-2.10.7-nonprism/libpurple/media/backend-fs2.c 2013-08-17 00:23:19.488440821 -0300
@@ -1739,413 +1354,6 @@ diff -Nur pidgin-2.10.7/libpurple/media/backend-fs2.c pidgin-2.10.7-nonprism/lib
session->id = g_strdup(sess_id);
session->backend = self;
session->type = type;
-diff -Nur pidgin-2.10.7/libpurple/plugins/Makefile.in pidgin-2.10.7-nonprism/libpurple/plugins/Makefile.in
---- pidgin-2.10.7/libpurple/plugins/Makefile.in 2013-02-11 07:17:19.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/plugins/Makefile.in 2013-08-16 23:53:13.792933405 -0300
-@@ -406,8 +406,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -469,8 +467,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/libpurple/plugins/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/plugins/Makefile.mingw
---- pidgin-2.10.7/libpurple/plugins/Makefile.mingw 2013-02-11 07:16:51.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/plugins/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,82 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of libpurple Plugins
--#
--
--PIDGIN_TREE_TOP := ../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--PERL_PLUGIN := ./perl
--TCL_PLUGIN := ./tcl
--SSL_PLUGIN := ./ssl
--
--.SUFFIXES:
--.SUFFIXES: .c .dll
--
--##
--## INCLUDE PATHS
--##
--INCLUDE_PATHS += \
-- -I$(GTK_TOP)/include \
-- -I$(GTK_TOP)/include/glib-2.0 \
-- -I$(GTK_TOP)/lib/glib-2.0/include \
-- -I$(PIDGIN_TREE_TOP) \
-- -I$(PURPLE_TOP) \
-- -I$(PURPLE_TOP)/win32
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lgobject-2.0 \
-- -lgmodule-2.0 \
-- -lintl \
-- -lws2_32 \
-- -lpurple
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all clean plugins install
--
--all: $(PURPLE_DLL).a plugins
-- $(MAKE) -C $(PERL_PLUGIN) -f $(MINGW_MAKEFILE)
-- $(MAKE) -C $(TCL_PLUGIN) -f $(MINGW_MAKEFILE)
-- $(MAKE) -C $(SSL_PLUGIN) -f $(MINGW_MAKEFILE)
--
--install: all $(PURPLE_INSTALL_PLUGINS_DIR)
-- $(MAKE) -C $(PERL_PLUGIN) -f $(MINGW_MAKEFILE) install
-- $(MAKE) -C $(TCL_PLUGIN) -f $(MINGW_MAKEFILE) install
-- $(MAKE) -C $(SSL_PLUGIN) -f $(MINGW_MAKEFILE) install
-- cp *.dll $(PURPLE_INSTALL_PLUGINS_DIR)
--
--%.dll: %.c $(PURPLE_CONFIG_H) $(PURPLE_VERSION_H)
-- $(CC) $(CFLAGS) $(DEFINES) $(INCLUDE_PATHS) -o $@.o -c $<
-- $(CC) -shared $@.o $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $@
--
--plugins: \
-- autoaccept.dll \
-- buddynote.dll \
-- idle.dll \
-- joinpart.dll \
-- log_reader.dll \
-- newline.dll \
-- offlinemsg.dll \
-- psychic.dll \
-- statenotify.dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -f *.o *.dll
-- $(MAKE) -C $(PERL_PLUGIN) -f $(MINGW_MAKEFILE) clean
-- $(MAKE) -C $(TCL_PLUGIN) -f $(MINGW_MAKEFILE) clean
-- $(MAKE) -C $(SSL_PLUGIN) -f $(MINGW_MAKEFILE) clean
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/plugins/mono/api/Makefile.in pidgin-2.10.7-nonprism/libpurple/plugins/mono/api/Makefile.in
---- pidgin-2.10.7/libpurple/plugins/mono/api/Makefile.in 2013-02-11 07:17:19.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/plugins/mono/api/Makefile.in 2013-08-17 00:05:58.593066418 -0300
-@@ -151,8 +151,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -214,8 +212,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/libpurple/plugins/mono/loader/Makefile.in pidgin-2.10.7-nonprism/libpurple/plugins/mono/loader/Makefile.in
---- pidgin-2.10.7/libpurple/plugins/mono/loader/Makefile.in 2013-02-11 07:17:19.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/plugins/mono/loader/Makefile.in 2013-08-17 00:06:17.736987877 -0300
-@@ -184,8 +184,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -247,8 +245,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/libpurple/plugins/mono/Makefile.in pidgin-2.10.7-nonprism/libpurple/plugins/mono/Makefile.in
---- pidgin-2.10.7/libpurple/plugins/mono/Makefile.in 2013-02-11 07:17:19.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/plugins/mono/Makefile.in 2013-08-16 23:53:49.027353090 -0300
-@@ -191,8 +191,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -254,8 +252,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/libpurple/plugins/perl/common/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/plugins/perl/common/Makefile.mingw
---- pidgin-2.10.7/libpurple/plugins/perl/common/Makefile.mingw 2013-02-11 07:16:51.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/plugins/perl/common/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,124 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for Purple perl module.
--#
--
--PIDGIN_TREE_TOP := ../../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--GCCWARNINGS += -Wno-comment -Wno-unused -Wno-nested-externs
--
--DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES))
--
--TARGET = Purple
--AUTOSPLIT = lib/auto/Purple/autosplit.ix
--PERL_PLUGIN_TOP := ..
--
--##
--## INCLUDE PATHS
--##
--INCLUDE_PATHS += -I. \
-- -I$(PIDGIN_TREE_TOP) \
-- -I$(PURPLE_TOP) \
-- -I$(PURPLE_TOP)/win32 \
-- -I$(GTK_TOP)/include \
-- -I$(GTK_TOP)/include/glib-2.0 \
-- -I$(GTK_TOP)/lib/glib-2.0/include \
-- -I$(PERL_LIB_TOP)/CORE
--
--LIB_PATHS += -L$(PERL_LIB_TOP) \
-- -L$(PERL_PLUGIN_TOP) \
-- -L$(PURPLE_TOP) \
-- -L$(GTK_TOP)/lib
--
--##
--## SOURCES, OBJECTS
--##
--XS_FILES = Account.xs \
-- AccountOpts.xs \
-- BuddyIcon.xs \
-- BuddyList.xs \
-- Cipher.xs \
-- Cmds.xs \
-- Certificate.xs \
-- Connection.xs \
-- Conversation.xs \
-- Core.xs \
-- Debug.xs \
-- FT.xs \
-- Idle.xs \
-- Purple.xs \
-- ImgStore.xs \
-- Log.xs \
-- Network.xs \
-- Notify.xs \
-- Plugin.xs \
-- PluginPref.xs \
-- Pounce.xs \
-- Prefs.xs \
-- Privacy.xs \
-- Proxy.xs \
-- Prpl.xs \
-- Request.xs \
-- Roomlist.xs \
-- SSLConn.xs \
-- SavedStatuses.xs \
-- Server.xs \
-- Signal.xs \
-- Smiley.xs \
-- Sound.xs \
-- Status.xs \
-- Stringref.xs \
-- Util.xs \
-- Whiteboard.xs \
-- XMLNode.xs
--
--#FALLBACKS = const-c.inc const-xs.inc
--C_FILES = $(XS_FILES:%.xs=%.c)
--OBJECTS = $(C_FILES:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = -lperl510 \
-- -lperl \
-- -lpurple \
-- -lglib-2.0
--
--include $(PIDGIN_COMMON_RULES)
--
--%.inc:
-- cp fallback/$@ ./
--
--##
--## TARGETS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll $(AUTOSPLIT)
--
--install: all
-- rm -rf $(PURPLE_INSTALL_PERL_DIR)
-- mkdir -p $(PURPLE_INSTALL_PERL_DIR)
-- cp -R lib/* $(PURPLE_INSTALL_PERL_DIR)
-- cp $(TARGET).dll $(PURPLE_INSTALL_PERL_DIR)/auto/Purple
--
--$(C_FILES): $(PURPLE_CONFIG_H)
--
--$(AUTOSPLIT):
-- mkdir -p ./lib/auto
-- cp Purple.pm ./lib
-- $(PERL) -MAutoSplit -e 'autosplit("lib/Purple.pm")'
--
--$(TARGET).dll: $(PURPLE_DLL).a $(PURPLE_PERL_DLL).a $(FALLBACKS) $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
--
--##
--## CLEAN
--##
--clean:
-- rm -rf $(TARGET).dll $(FALLBACKS) lib
-- rm -f *.o $(C_FILES)
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/plugins/perl/Makefile.in pidgin-2.10.7-nonprism/libpurple/plugins/perl/Makefile.in
---- pidgin-2.10.7/libpurple/plugins/perl/Makefile.in 2013-02-11 07:17:19.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/plugins/perl/Makefile.in 2013-08-16 23:53:53.240816341 -0300
-@@ -182,8 +182,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -245,8 +243,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/libpurple/plugins/perl/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/plugins/perl/Makefile.mingw
---- pidgin-2.10.7/libpurple/plugins/perl/Makefile.mingw 2013-02-11 07:16:51.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/plugins/perl/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,84 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for perl plugin loader plugin.
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES))
--
--TARGET = perl
--
--# Perl headers with /* /* */ type comments.. Turn off warnings.
--GCCWARNINGS += -Wno-comment
--
--##
--## INCLUDE PATHS
--##
--INCLUDE_PATHS += -I. \
-- -I$(PIDGIN_TREE_TOP) \
-- -I$(PURPLE_TOP) \
-- -I$(PURPLE_TOP)/win32 \
-- -I$(GTK_TOP)/include \
-- -I$(GTK_TOP)/include/glib-2.0 \
-- -I$(GTK_TOP)/lib/glib-2.0/include \
-- -I$(PERL_LIB_TOP)/CORE
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP) \
-- -L$(PERL_LIB_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = perl.c \
-- perl-common.c \
-- perl-handlers.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lgmodule-2.0 \
-- -lgobject-2.0 \
-- -lws2_32 \
-- -lintl \
-- -lpurple \
-- -lperl510
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll
-- $(MAKE) -C ./common -f $(MINGW_MAKEFILE)
--
--install: all $(PURPLE_INSTALL_PLUGINS_DIR)
-- cp $(TARGET).dll $(PURPLE_INSTALL_PLUGINS_DIR)
-- $(MAKE) -C ./common -f $(MINGW_MAKEFILE) install
--
--$(OBJECTS): $(PURPLE_CONFIG_H)
--
--##
--## BUILD DLL
--##
--$(TARGET).dll $(TARGET).dll.a: $(PURPLE_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--export-all-symbols -Wl,--out-implib,$(TARGET).dll.a -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -rf $(OBJECTS)
-- rm -rf $(TARGET).dll $(TARGET).dll.a
-- $(MAKE) -C ./common -f $(MINGW_MAKEFILE) clean
--
--include $(PIDGIN_COMMON_TARGETS)
diff -Nur pidgin-2.10.7/libpurple/plugins/psychic.c pidgin-2.10.7-nonprism/libpurple/plugins/psychic.c
--- pidgin-2.10.7/libpurple/plugins/psychic.c 2013-02-11 07:16:51.000000000 -0200
+++ pidgin-2.10.7-nonprism/libpurple/plugins/psychic.c 2013-08-27 21:18:22.251908751 -0300
@@ -2159,229 +1367,6 @@ diff -Nur pidgin-2.10.7/libpurple/plugins/psychic.c pidgin-2.10.7-nonprism/libpu
#define PLUGIN_AUTHOR "Christopher O'Brien <siege@preoccupied.net>"
-diff -Nur pidgin-2.10.7/libpurple/plugins/ssl/Makefile.in pidgin-2.10.7-nonprism/libpurple/plugins/ssl/Makefile.in
---- pidgin-2.10.7/libpurple/plugins/ssl/Makefile.in 2013-02-11 07:17:19.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/plugins/ssl/Makefile.in 2013-08-16 23:53:57.577616732 -0300
-@@ -225,8 +225,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -288,8 +286,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/libpurple/plugins/ssl/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/plugins/ssl/Makefile.mingw
---- pidgin-2.10.7/libpurple/plugins/ssl/Makefile.mingw 2013-02-11 07:16:51.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/plugins/ssl/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,96 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for ssl plugin.
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--##
--## VARIABLE DEFINITIONS
--##
--TARGET = ssl
--TARGET_NSS = ssl-nss
--
--NEEDED_DLLS = \
-- $(NSS_TOP)/lib/freebl3.dll \
-- $(NSS_TOP)/lib/libnspr4.dll \
-- $(NSS_TOP)/lib/libplc4.dll \
-- $(NSS_TOP)/lib/libplds4.dll \
-- $(NSS_TOP)/lib/nss3.dll \
-- $(NSS_TOP)/lib/nssutil3.dll \
-- $(NSS_TOP)/lib/smime3.dll \
-- $(NSS_TOP)/lib/softokn3.dll \
-- $(NSS_TOP)/lib/sqlite3.dll \
-- $(NSS_TOP)/lib/ssl3.dll
--
--##
--## 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$(NSS_TOP)/include
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP) \
-- -L$(NSS_TOP)/lib
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = ssl.c
--C_SRC_NSS = ssl-nss.c
--OBJECTS = $(C_SRC:%.c=%.o)
--OBJECTS_NSS = $(C_SRC_NSS:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lws2_32 \
-- -lintl \
-- -lpurple \
-- -lnss3 \
-- -lnspr4 \
-- -lssl3 \
-- -lsmime3
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll $(TARGET_NSS).dll
--
--install: all $(PURPLE_INSTALL_PLUGINS_DIR) $(PURPLE_INSTALL_DIR)
-- cp $(TARGET).dll $(PURPLE_INSTALL_PLUGINS_DIR)
-- cp $(TARGET_NSS).dll $(PURPLE_INSTALL_PLUGINS_DIR)
-- cp $(NEEDED_DLLS) $(PURPLE_INSTALL_DIR)
--
--$(OBJECTS) $(OBJECTS_NSS): $(PURPLE_CONFIG_H)
--
--##
--## BUILD DLL
--##
--$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
--
--$(TARGET_NSS).dll: $(PURPLE_DLL) $(OBJECTS_NSS)
-- $(CC) -shared $(OBJECTS_NSS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET_NSS).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -f $(OBJECTS) $(OBJECTS_NSS) $(TARGET).dll $(TARGET_NSS).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/plugins/tcl/Makefile.in pidgin-2.10.7-nonprism/libpurple/plugins/tcl/Makefile.in
---- pidgin-2.10.7/libpurple/plugins/tcl/Makefile.in 2013-02-11 07:17:19.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/plugins/tcl/Makefile.in 2013-08-16 23:54:01.251063337 -0300
-@@ -185,8 +185,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -248,8 +246,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/libpurple/plugins/tcl/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/plugins/tcl/Makefile.mingw
---- pidgin-2.10.7/libpurple/plugins/tcl/Makefile.mingw 2013-02-11 07:16:51.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/plugins/tcl/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,77 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for tcl plugin loader plugin.
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = tcl
--TCL_INC_DIR := $(TCL_LIB_TOP)/include
--DEFINES += -DHAVE_TK -DUSE_TCL_STUBS -DUSE_TK_STUBS
--
--##
--## INCLUDE PATHS
--##
--INCLUDE_PATHS += -I. \
-- -I$(PIDGIN_TREE_TOP) \
-- -I$(PURPLE_TOP) \
-- -I$(PURPLE_TOP)/win32 \
-- -I$(GTK_TOP)/include \
-- -I$(GTK_TOP)/include/glib-2.0 \
-- -I$(GTK_TOP)/lib/glib-2.0/include \
-- -I$(TCL_INC_DIR)
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP) \
-- -L$(TCL_LIB_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = tcl.c \
-- tcl_cmd.c \
-- tcl_cmds.c \
-- tcl_glib.c \
-- tcl_ref.c \
-- tcl_signals.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lws2_32 \
-- -lintl \
-- -lpurple \
-- -ltclstub84 \
-- -ltkstub84
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll
--
--install: all $(PURPLE_INSTALL_PLUGINS_DIR)
-- cp $(TARGET).dll $(PURPLE_INSTALL_PLUGINS_DIR)
--
--$(OBJECTS): $(PURPLE_CONFIG_H)
--
--$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -rf $(OBJECTS)
-- rm -rf $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
diff -Nur pidgin-2.10.7/libpurple/pounce.c pidgin-2.10.7-nonprism/libpurple/pounce.c
--- pidgin-2.10.7/libpurple/pounce.c 2013-02-11 07:16:51.000000000 -0200
+++ pidgin-2.10.7-nonprism/libpurple/pounce.c 2013-08-16 23:02:20.671021669 -0300
@@ -2393,26286 +1378,6 @@ diff -Nur pidgin-2.10.7/libpurple/pounce.c pidgin-2.10.7-nonprism/libpurple/poun
g_free(tmp);
}
else if (purple_strequal(element_name, "pouncee")) {
-diff -Nur pidgin-2.10.7/libpurple/protocols/bonjour/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/bonjour/Makefile.in
---- pidgin-2.10.7/libpurple/protocols/bonjour/Makefile.in 2013-02-11 07:17:19.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/bonjour/Makefile.in 2013-08-16 23:51:12.255853844 -0300
-@@ -199,8 +199,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -262,8 +260,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/libpurple/protocols/bonjour/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/bonjour/Makefile.mingw
---- pidgin-2.10.7/libpurple/protocols/bonjour/Makefile.mingw 2013-02-11 07:16:51.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/bonjour/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,98 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of libbonjour
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = libbonjour
--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
--
--CFLAGS += -DUSE_BONJOUR_APPLE
--
--##
--## 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$(BONJOUR_TOP)/Include \
-- -I$(LIBXML2_TOP)/include/libxml2 \
-- -I$(PURPLE_TOP) \
-- -I$(PURPLE_TOP)/win32 \
-- -I$(PIDGIN_TREE_TOP)
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(LIBXML2_TOP)/lib \
-- -L$(PURPLE_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = bonjour.c \
-- bonjour_ft.c \
-- buddy.c \
-- dns_sd_proxy.c \
-- jabber.c \
-- mdns_common.c \
-- mdns_win32.c \
-- parser.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lws2_32 \
-- -lintl \
-- -lnetapi32 \
-- -lxml2 \
-- -lpurple
--
--ifeq ($(LINK_DNS_SD_DIRECTLY), 1)
-- CFLAGS += -DLINK_DNS_SD_DIRECTLY
-- LIB_PATHS += -L$(BONJOUR_TOP)/lib/win32 -L$(BONJOUR_TOP)/lib
-- LIBS += -ldnssd
--endif
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll
--
--install: all $(DLL_INSTALL_DIR)
-- cp $(TARGET).dll $(DLL_INSTALL_DIR)
--
--$(OBJECTS): $(PURPLE_CONFIG_H)
--
--$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--
--clean:
-- rm -f $(OBJECTS)
-- rm -f $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/buddylist.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/buddylist.c
---- pidgin-2.10.7/libpurple/protocols/gg/buddylist.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/buddylist.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,188 +0,0 @@
--/**
-- * @file buddylist.c
-- *
-- * purple
-- *
-- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--
--#include <libgadu.h>
--
--#include "gg.h"
--#include "gg-utils.h"
--#include "buddylist.h"
--
--#define F_FIRSTNAME 0
--#define F_LASTNAME 1
--/* #define F_ 2 */
--#define F_NICKNAME 3
--#define F_PHONE 4
--#define F_GROUP 5
--#define F_UIN 6
--
--/* void ggp_buddylist_send(PurpleConnection *gc) {{{ */
--void ggp_buddylist_send(PurpleConnection *gc)
--{
-- GGPInfo *info = gc->proto_data;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- GSList *buddies;
-- uin_t *userlist;
-- gchar *types;
-- int i = 0, ret = 0;
-- int size;
--
-- buddies = purple_find_buddies(account, NULL);
--
-- size = g_slist_length(buddies);
-- userlist = g_new(uin_t, size);
-- types = g_new(gchar, size);
--
-- for (buddies = purple_find_buddies(account, NULL); buddies;
-- buddies = g_slist_delete_link(buddies, buddies), ++i)
-- {
-- PurpleBuddy *buddy = buddies->data;
-- const gchar *name = purple_buddy_get_name(buddy);
--
-- userlist[i] = ggp_str_to_uin(name);
-- types[i] = GG_USER_NORMAL;
-- purple_debug_info("gg", "ggp_buddylist_send: adding %d\n",
-- userlist[i]);
-- }
--
-- ret = gg_notify_ex(info->session, userlist, types, size);
-- purple_debug_info("gg", "send: ret=%d; size=%d\n", ret, size);
--
-- if (userlist) {
-- g_free(userlist);
-- g_free(types);
-- }
--}
--/* }}} */
--
--/* void ggp_buddylist_load(PurpleConnection *gc, char *buddylist) {{{ */
--void ggp_buddylist_load(PurpleConnection *gc, char *buddylist)
--{
-- PurpleBuddy *buddy;
-- PurpleGroup *group;
-- gchar **users_tbl;
-- int i;
-- char *utf8buddylist = charset_convert(buddylist, "CP1250", "UTF-8");
--
-- /* Don't limit the number of records in a buddylist. */
-- users_tbl = g_strsplit(utf8buddylist, "\r\n", -1);
--
-- for (i = 0; users_tbl[i] != NULL; i++) {
-- gchar **data_tbl;
-- gchar *name, *show, *g;
--
-- if (strlen(users_tbl[i]) == 0)
-- continue;
--
-- data_tbl = g_strsplit(users_tbl[i], ";", 8);
-- if (ggp_array_size(data_tbl) < 8) {
-- purple_debug_warning("gg",
-- "Something is wrong on line %d of the buddylist. Skipping.\n",
-- i + 1);
-- continue;
-- }
--
-- show = data_tbl[F_NICKNAME];
-- name = data_tbl[F_UIN];
-- if ('\0' == *name || !atol(name)) {
-- purple_debug_warning("gg",
-- "Identifier on line %d of the buddylist is not a number. Skipping.\n",
-- i + 1);
-- continue;
-- }
--
-- if ('\0' == *show) {
-- show = name;
-- }
--
-- purple_debug_info("gg", "got buddy: name=%s; show=%s\n", name, show);
--
-- if (purple_find_buddy(purple_connection_get_account(gc), name)) {
-- g_strfreev(data_tbl);
-- continue;
-- }
--
-- g = g_strdup("Gadu-Gadu");
--
-- if ('\0' != data_tbl[F_GROUP]) {
-- /* XXX: Probably buddy should be added to all the groups. */
-- /* Hard limit to at most 50 groups */
-- gchar **group_tbl = g_strsplit(data_tbl[F_GROUP], ",", 50);
-- if (ggp_array_size(group_tbl) > 0) {
-- g_free(g);
-- g = g_strdup(group_tbl[0]);
-- }
-- g_strfreev(group_tbl);
-- }
--
-- buddy = purple_buddy_new(purple_connection_get_account(gc), name,
-- strlen(show) ? show : NULL);
--
-- if (!(group = purple_find_group(g))) {
-- group = purple_group_new(g);
-- purple_blist_add_group(group, NULL);
-- }
--
-- purple_blist_add_buddy(buddy, NULL, group, NULL);
-- g_free(g);
--
-- g_strfreev(data_tbl);
-- }
-- g_strfreev(users_tbl);
-- g_free(utf8buddylist);
--
-- ggp_buddylist_send(gc);
--}
--/* }}} */
--
--/* char *ggp_buddylist_dump(PurpleAccount *account) {{{ */
--char *ggp_buddylist_dump(PurpleAccount *account)
--{
-- GSList *buddies;
-- GString *buddylist = g_string_sized_new(1024);
-- char *ptr;
--
-- for (buddies = purple_find_buddies(account, NULL); buddies;
-- buddies = g_slist_delete_link(buddies, buddies)) {
-- PurpleBuddy *buddy = buddies->data;
-- PurpleGroup *group = purple_buddy_get_group(buddy);
-- const char *bname = purple_buddy_get_name(buddy);
-- const char *gname = purple_group_get_name(group);
-- const char *alias = purple_buddy_get_alias(buddy);
--
-- if (alias == NULL)
-- alias = bname;
--
-- g_string_append_printf(buddylist,
-- "%s;%s;%s;%s;%s;%s;%s;%s%s\r\n",
-- alias, alias, alias, alias,
-- "", gname, bname, "", "");
-- }
--
-- ptr = charset_convert(buddylist->str, "UTF-8", "CP1250");
-- g_string_free(buddylist, TRUE);
-- return ptr;
--}
--/* }}} */
--
--
--/* vim: set ts=8 sts=0 sw=8 noet: */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/buddylist.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/buddylist.h
---- pidgin-2.10.7/libpurple/protocols/gg/buddylist.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/buddylist.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,57 +0,0 @@
--/**
-- * @file buddylist.h
-- *
-- * purple
-- *
-- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--
--#ifndef _PURPLE_GG_BUDDYLIST_H
--#define _PURPLE_GG_BUDDYLIST_H
--
--#include "connection.h"
--#include "account.h"
--
--void
--ggp_buddylist_send(PurpleConnection *gc);
--
--/**
-- * Load buddylist from server into the roster.
-- *
-- * @param gc PurpleConnection
-- * @param buddylist Pointer to the buddylist that will be loaded.
-- */
--/* void ggp_buddylist_load(PurpleConnection *gc, char *buddylist) {{{ */
--void
--ggp_buddylist_load(PurpleConnection *gc, char *buddylist);
--
--/**
-- * Get all the buddies in the current account.
-- *
-- * @param account Current account.
-- *
-- * @return List of buddies.
-- */
--char *
--ggp_buddylist_dump(PurpleAccount *account);
--
--
--#endif /* _PURPLE_GG_BUDDYLIST_H */
--
--
--/* vim: set ts=8 sts=0 sw=8 noet: */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/confer.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/confer.c
---- pidgin-2.10.7/libpurple/protocols/gg/confer.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/confer.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,170 +0,0 @@
--/**
-- * @file confer.c
-- *
-- * purple
-- *
-- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--
--#include <libgadu.h>
--#include "gg.h"
--#include "gg-utils.h"
--#include "confer.h"
--
--/* PurpleConversation *ggp_confer_find_by_name(PurpleConnection *gc, const gchar *name) {{{ */
--PurpleConversation *ggp_confer_find_by_name(PurpleConnection *gc, const gchar *name)
--{
-- g_return_val_if_fail(gc != NULL, NULL);
-- g_return_val_if_fail(name != NULL, NULL);
--
-- return purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, name,
-- purple_connection_get_account(gc));
--}
--/* }}} */
--
--/* void ggp_confer_participants_add_uin(PurpleConnection *gc, const gchar *chat_name, const uin_t uin) {{{ */
--void ggp_confer_participants_add_uin(PurpleConnection *gc, const gchar *chat_name,
-- const uin_t uin)
--{
-- PurpleConversation *conv;
-- GGPInfo *info = gc->proto_data;
-- GGPChat *chat;
-- GList *l;
-- gchar *str_uin;
--
-- for (l = info->chats; l != NULL; l = l->next) {
-- chat = l->data;
--
-- if (g_utf8_collate(chat->name, chat_name) != 0)
-- continue;
--
-- if (g_list_find(chat->participants, GINT_TO_POINTER(uin)) == NULL) {
-- chat->participants = g_list_append(
-- chat->participants, GINT_TO_POINTER(uin));
--
-- str_uin = g_strdup_printf("%lu", (unsigned long int)uin);
-- conv = ggp_confer_find_by_name(gc, chat_name);
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(conv), str_uin, NULL,
-- PURPLE_CBFLAGS_NONE, TRUE);
--
-- g_free(str_uin);
-- }
-- break;
-- }
--}
--/* }}} */
--
--/* void ggp_confer_participants_add(PurpleConnection *gc, const gchar *chat_name, const uin_t *recipients, int count) {{{ */
--void ggp_confer_participants_add(PurpleConnection *gc, const gchar *chat_name,
-- const uin_t *recipients, int count)
--{
-- GGPInfo *info = gc->proto_data;
-- GList *l;
-- gchar *str_uin;
--
-- for (l = info->chats; l != NULL; l = l->next) {
-- GGPChat *chat = l->data;
-- int i;
--
-- if (g_utf8_collate(chat->name, chat_name) != 0)
-- continue;
--
-- for (i = 0; i < count; i++) {
-- PurpleConversation *conv;
--
-- if (g_list_find(chat->participants,
-- GINT_TO_POINTER(recipients[i])) != NULL) {
-- continue;
-- }
--
-- chat->participants = g_list_append(chat->participants,
-- GINT_TO_POINTER(recipients[i]));
--
-- str_uin = g_strdup_printf("%lu", (unsigned long int)recipients[i]);
-- conv = ggp_confer_find_by_name(gc, chat_name);
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(conv),
-- str_uin, NULL,
-- PURPLE_CBFLAGS_NONE, TRUE);
-- g_free(str_uin);
-- }
-- break;
-- }
--}
--/* }}} */
--
--/* const char *ggp_confer_find_by_participants(PurpleConnection *gc, const uin_t *recipients, int count) {{{ */
--const char *ggp_confer_find_by_participants(PurpleConnection *gc,
-- const uin_t *recipients, int count)
--{
-- GGPInfo *info = gc->proto_data;
-- GGPChat *chat = NULL;
-- GList *l;
-- int matches;
--
-- g_return_val_if_fail(info->chats != NULL, NULL);
--
-- for (l = info->chats; l != NULL; l = l->next) {
-- GList *m;
--
-- chat = l->data;
-- matches = 0;
--
-- for (m = chat->participants; m != NULL; m = m->next) {
-- uin_t uin = GPOINTER_TO_INT(m->data);
-- int i;
--
-- for (i = 0; i < count; i++)
-- if (uin == recipients[i])
-- matches++;
-- }
--
-- if (matches == count)
-- break;
--
-- chat = NULL;
-- }
--
-- if (chat == NULL)
-- return NULL;
-- else
-- return chat->name;
--}
--/* }}} */
--
--/* const char *ggp_confer_add_new(PurpleConnection *gc, const char *name) {{{ */
--const char *ggp_confer_add_new(PurpleConnection *gc, const char *name)
--{
-- GGPInfo *info = gc->proto_data;
-- GGPChat *chat;
--
-- chat = g_new0(GGPChat, 1);
--
-- if (name == NULL)
-- chat->name = g_strdup_printf("conf#%d", info->chats_count++);
-- else
-- chat->name = g_strdup(name);
--
-- chat->participants = NULL;
--
-- info->chats = g_list_append(info->chats, chat);
--
-- return chat->name;
--}
--/* }}} */
--
--/* vim: set ts=8 sts=0 sw=8 noet: */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/confer.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/confer.h
---- pidgin-2.10.7/libpurple/protocols/gg/confer.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/confer.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,93 +0,0 @@
--/**
-- * @file confer.h
-- *
-- * purple
-- *
-- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--
--#ifndef _PURPLE_GG_CONFER_H
--#define _PURPLE_GG_CONFER_H
--
--#include "gg.h"
--
--/**
-- * Finds a CHAT conversation for the current account with the specified name.
-- *
-- * @param gc PurpleConnection instance.
-- * @param name Name of the conversation.
-- *
-- * @return PurpleConversation or NULL if not found.
-- */
--PurpleConversation *
--ggp_confer_find_by_name(PurpleConnection *gc, const gchar *name);
--
--/**
-- * Adds the specified UIN to the specified conversation.
-- *
-- * @param gc PurpleConnection.
-- * @param chat_name Name of the conversation.
-- */
--void
--ggp_confer_participants_add_uin(PurpleConnection *gc, const gchar *chat_name,
-- const uin_t uin);
--
--/**
-- * Add the specified UINs to the specified conversation.
-- *
-- * @param gc PurpleConnection.
-- * @param chat_name Name of the conversation.
-- * @param recipients List of the UINs.
-- * @param count Number of the UINs.
-- */
--void
--ggp_confer_participants_add(PurpleConnection *gc, const gchar *chat_name,
-- const uin_t *recipients, int count);
--
--/**
-- * Finds a conversation in which all the specified recipients participate.
-- *
-- * TODO: This function should be rewritten to better handle situations when
-- * somebody adds more people to the converation.
-- *
-- * @param gc PurpleConnection.
-- * @param recipients List of the people in the conversation.
-- * @param count Number of people.
-- *
-- * @return Name of the conversation.
-- */
--const char*
--ggp_confer_find_by_participants(PurpleConnection *gc, const uin_t *recipients,
-- int count);
--
--/**
-- * Adds a new conversation to the internal list of conversations.
-- * If name is NULL then it will be automagically generated.
-- *
-- * @param gc PurpleConnection.
-- * @param name Name of the conversation.
-- *
-- * @return Name of the conversation.
-- */
--const char*
--ggp_confer_add_new(PurpleConnection *gc, const char *name);
--
--
--#endif /* _PURPLE_GG_CONFER_H */
--
--/* vim: set ts=8 sts=0 sw=8 noet: */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/gg.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/gg.c
---- pidgin-2.10.7/libpurple/protocols/gg/gg.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/gg.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,2837 +0,0 @@
--/**
-- * @file gg.c Gadu-Gadu protocol plugin
-- *
-- * purple
-- *
-- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
-- *
-- * Some parts of the code are adapted or taken from the previous implementation
-- * of this plugin written by Arkadiusz Miskiewicz <misiek@pld.org.pl>
-- * Some parts Copyright (C) 2009 Krzysztof Klinikowski <grommasher@gmail.com>
-- *
-- * Thanks to Google's Summer of Code Program.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--
--#include "plugin.h"
--#include "version.h"
--#include "notify.h"
--#include "status.h"
--#include "blist.h"
--#include "accountopt.h"
--#include "debug.h"
--#include "util.h"
--#include "request.h"
--#include "xmlnode.h"
--
--#include <libgadu.h>
--
--#include "gg.h"
--#include "confer.h"
--#include "search.h"
--#include "buddylist.h"
--#include "gg-utils.h"
--
--#define DISABLE_AVATARS 1
--
--static PurplePlugin *my_protocol = NULL;
--
--/* Prototypes */
--static void ggp_set_status(PurpleAccount *account, PurpleStatus *status);
--static int ggp_to_gg_status(PurpleStatus *status, char **msg);
--
--/* ---------------------------------------------------------------------- */
--/* ----- EXTERNAL CALLBACKS --------------------------------------------- */
--/* ---------------------------------------------------------------------- */
--
--
--/* ----- HELPERS -------------------------------------------------------- */
--
--/**
-- * Set up libgadu's proxy.
-- *
-- * @param account Account for which to set up the proxy.
-- *
-- * @return Zero if proxy setup is valid, otherwise -1.
-- */
--static int ggp_setup_proxy(PurpleAccount *account)
--{
-- PurpleProxyInfo *gpi;
--
-- gpi = purple_proxy_get_setup(account);
--
-- if ((purple_proxy_info_get_type(gpi) != PURPLE_PROXY_NONE) &&
-- (purple_proxy_info_get_host(gpi) == NULL ||
-- purple_proxy_info_get_port(gpi) <= 0)) {
--
-- gg_proxy_enabled = 0;
-- purple_notify_error(NULL, NULL, _("Invalid proxy settings"),
-- _("Either the host name or port number specified for your given proxy type is invalid."));
-- return -1;
-- } else if (purple_proxy_info_get_type(gpi) != PURPLE_PROXY_NONE) {
-- gg_proxy_enabled = 1;
-- gg_proxy_host = g_strdup(purple_proxy_info_get_host(gpi));
-- gg_proxy_port = purple_proxy_info_get_port(gpi);
-- gg_proxy_username = g_strdup(purple_proxy_info_get_username(gpi));
-- gg_proxy_password = g_strdup(purple_proxy_info_get_password(gpi));
-- } else {
-- gg_proxy_enabled = 0;
-- }
--
-- return 0;
--}
--
--static void ggp_async_token_handler(gpointer _gc, gint fd, PurpleInputCondition cond)
--{
-- PurpleConnection *gc = _gc;
-- GGPInfo *info = gc->proto_data;
-- GGPToken *token = info->token;
-- GGPTokenCallback cb;
--
-- struct gg_token *t = NULL;
--
-- purple_debug_info("gg", "token_handler: token->req: check = %d; state = %d;\n",
-- token->req->check, token->req->state);
--
-- if (gg_token_watch_fd(token->req) == -1 || token->req->state == GG_STATE_ERROR) {
-- purple_debug_error("gg", "token error (1): %d\n", token->req->error);
-- purple_input_remove(token->inpa);
-- gg_token_free(token->req);
-- token->req = NULL;
--
-- purple_notify_error(purple_connection_get_account(gc),
-- _("Token Error"),
-- _("Unable to fetch the token.\n"), NULL);
-- return;
-- }
--
-- if (token->req->state != GG_STATE_DONE) {
-- purple_input_remove(token->inpa);
-- token->inpa = purple_input_add(token->req->fd,
-- (token->req->check == 1)
-- ? PURPLE_INPUT_WRITE
-- : PURPLE_INPUT_READ,
-- ggp_async_token_handler, gc);
-- return;
-- }
--
-- if (!(t = token->req->data) || !token->req->body) {
-- purple_debug_error("gg", "token error (2): %d\n", token->req->error);
-- purple_input_remove(token->inpa);
-- gg_token_free(token->req);
-- token->req = NULL;
--
-- purple_notify_error(purple_connection_get_account(gc),
-- _("Token Error"),
-- _("Unable to fetch the token.\n"), NULL);
-- return;
-- }
--
-- purple_input_remove(token->inpa);
--
-- token->id = g_strdup(t->tokenid);
-- token->size = token->req->body_size;
-- token->data = g_new0(char, token->size);
-- memcpy(token->data, token->req->body, token->size);
--
-- purple_debug_info("gg", "TOKEN! tokenid = %s; size = %d\n",
-- token->id, token->size);
--
-- gg_token_free(token->req);
-- token->req = NULL;
-- token->inpa = 0;
--
-- cb = token->cb;
-- token->cb = NULL;
-- cb(gc);
--}
--
--static void ggp_token_request(PurpleConnection *gc, GGPTokenCallback cb)
--{
-- PurpleAccount *account;
-- struct gg_http *req;
-- GGPInfo *info;
--
-- account = purple_connection_get_account(gc);
--
-- if (ggp_setup_proxy(account) == -1)
-- return;
--
-- info = gc->proto_data;
--
-- if ((req = gg_token(1)) == NULL) {
-- purple_notify_error(account,
-- _("Token Error"),
-- _("Unable to fetch the token.\n"), NULL);
-- return;
-- }
--
-- info->token = g_new(GGPToken, 1);
-- info->token->cb = cb;
--
-- info->token->req = req;
-- info->token->inpa = purple_input_add(req->fd, PURPLE_INPUT_READ,
-- ggp_async_token_handler, gc);
--}
--/* }}} */
--
--/* ---------------------------------------------------------------------- */
--
--/**
-- * Request buddylist from the server.
-- * Buddylist is received in the ggp_callback_recv().
-- *
-- * @param Current action handler.
-- */
--static void ggp_action_buddylist_get(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *)action->context;
-- GGPInfo *info = gc->proto_data;
--
-- purple_debug_info("gg", "Downloading...\n");
--
-- gg_userlist_request(info->session, GG_USERLIST_GET, NULL);
--}
--
--/**
-- * Upload the buddylist to the server.
-- *
-- * @param action Current action handler.
-- */
--static void ggp_action_buddylist_put(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *)action->context;
-- GGPInfo *info = gc->proto_data;
--
-- char *buddylist = ggp_buddylist_dump(purple_connection_get_account(gc));
--
-- purple_debug_info("gg", "Uploading...\n");
--
-- if (buddylist == NULL)
-- return;
--
-- gg_userlist_request(info->session, GG_USERLIST_PUT, buddylist);
-- g_free(buddylist);
--}
--
--/**
-- * Delete buddylist from the server.
-- *
-- * @param action Current action handler.
-- */
--static void ggp_action_buddylist_delete(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *)action->context;
-- GGPInfo *info = gc->proto_data;
--
-- purple_debug_info("gg", "Deleting...\n");
--
-- gg_userlist_request(info->session, GG_USERLIST_PUT, NULL);
--}
--
--static void ggp_callback_buddylist_save_ok(PurpleConnection *gc, const char *filename)
--{
-- PurpleAccount *account = purple_connection_get_account(gc);
--
-- char *buddylist = ggp_buddylist_dump(account);
--
-- purple_debug_info("gg", "Saving...\n");
-- purple_debug_info("gg", "file = %s\n", filename);
--
-- if (buddylist == NULL) {
-- purple_notify_info(account, _("Save Buddylist..."),
-- _("Your buddylist is empty, nothing was written to the file."),
-- NULL);
-- return;
-- }
--
-- if(purple_util_write_data_to_file_absolute(filename, buddylist, -1)) {
-- purple_notify_info(account, _("Save Buddylist..."),
-- _("Buddylist saved successfully!"), NULL);
-- } else {
-- gchar *primary = g_strdup_printf(
-- _("Couldn't write buddy list for %s to %s"),
-- purple_account_get_username(account), filename);
-- purple_notify_error(account, _("Save Buddylist..."),
-- primary, NULL);
-- g_free(primary);
-- }
--
-- g_free(buddylist);
--}
--
--static void ggp_callback_buddylist_load_ok(PurpleConnection *gc, gchar *file)
--{
-- PurpleAccount *account = purple_connection_get_account(gc);
-- GError *error = NULL;
-- char *buddylist = NULL;
-- gsize length;
--
-- purple_debug_info("gg", "file_name = %s\n", file);
--
-- if (!g_file_get_contents(file, &buddylist, &length, &error)) {
-- purple_notify_error(account,
-- _("Couldn't load buddylist"),
-- _("Couldn't load buddylist"),
-- error->message);
--
-- purple_debug_error("gg",
-- "Couldn't load buddylist. file = %s; error = %s\n",
-- file, error->message);
--
-- g_error_free(error);
--
-- return;
-- }
--
-- ggp_buddylist_load(gc, buddylist);
-- g_free(buddylist);
--
-- purple_notify_info(account,
-- _("Load Buddylist..."),
-- _("Buddylist loaded successfully!"), NULL);
--}
--/* }}} */
--
--/*
-- */
--/* static void ggp_action_buddylist_save(PurplePluginAction *action) {{{ */
--static void ggp_action_buddylist_save(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *)action->context;
--
-- purple_request_file(action, _("Save buddylist..."), NULL, TRUE,
-- G_CALLBACK(ggp_callback_buddylist_save_ok), NULL,
-- purple_connection_get_account(gc), NULL, NULL,
-- gc);
--}
--
--static void ggp_action_buddylist_load(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *)action->context;
--
-- purple_request_file(action, _("Load buddylist from file..."), NULL,
-- FALSE,
-- G_CALLBACK(ggp_callback_buddylist_load_ok), NULL,
-- purple_connection_get_account(gc), NULL, NULL,
-- gc);
--}
--
--static void ggp_callback_register_account_ok(PurpleConnection *gc,
-- PurpleRequestFields *fields)
--{
-- PurpleAccount *account;
-- GGPInfo *info = gc->proto_data;
-- struct gg_http *h = NULL;
-- struct gg_pubdir *s;
-- uin_t uin;
-- gchar *email, *p1, *p2, *t;
-- GGPToken *token = info->token;
--
-- email = charset_convert(purple_request_fields_get_string(fields, "email"),
-- "UTF-8", "CP1250");
-- p1 = charset_convert(purple_request_fields_get_string(fields, "password1"),
-- "UTF-8", "CP1250");
-- p2 = charset_convert(purple_request_fields_get_string(fields, "password2"),
-- "UTF-8", "CP1250");
-- t = charset_convert(purple_request_fields_get_string(fields, "token"),
-- "UTF-8", "CP1250");
--
-- account = purple_connection_get_account(gc);
--
-- if (email == NULL || p1 == NULL || p2 == NULL || t == NULL ||
-- *email == '\0' || *p1 == '\0' || *p2 == '\0' || *t == '\0') {
-- purple_connection_error_reason (gc,
-- PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-- _("You must fill in all registration fields"));
-- goto exit_err;
-- }
--
-- if (g_utf8_collate(p1, p2) != 0) {
-- purple_connection_error_reason (gc,
-- PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
-- _("Passwords do not match"));
-- goto exit_err;
-- }
--
-- purple_debug_info("gg", "register_account_ok: token_id = %s; t = %s\n",
-- token->id, t);
-- h = gg_register3(email, p1, token->id, t, 0);
-- if (h == NULL || !(s = h->data) || !s->success) {
-- purple_connection_error_reason (gc,
-- PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-- _("Unable to register new account. An unknown error occurred."));
-- goto exit_err;
-- }
--
-- uin = s->uin;
-- purple_debug_info("gg", "registered uin: %d\n", uin);
--
-- g_free(t);
-- t = g_strdup_printf("%u", uin);
-- purple_account_set_username(account, t);
-- /* Save the password if remembering passwords for the account */
-- purple_account_set_password(account, p1);
--
-- purple_notify_info(NULL, _("New Gadu-Gadu Account Registered"),
-- _("Registration completed successfully!"), NULL);
--
-- if(account->registration_cb)
-- (account->registration_cb)(account, TRUE, account->registration_cb_user_data);
-- /* TODO: the currently open Accounts Window will not be updated withthe
-- * new username and etc, we need to somehow have it refresh at this
-- * point
-- */
--
-- /* Need to disconnect or actually log in. For now, we disconnect. */
-- purple_account_disconnect(account);
--
--exit_err:
-- if(account->registration_cb)
-- (account->registration_cb)(account, FALSE, account->registration_cb_user_data);
--
-- gg_register_free(h);
-- g_free(email);
-- g_free(p1);
-- g_free(p2);
-- g_free(t);
-- g_free(token->id);
-- g_free(token);
--}
--
--static void ggp_callback_register_account_cancel(PurpleConnection *gc,
-- PurpleRequestFields *fields)
--{
-- GGPInfo *info = gc->proto_data;
-- GGPToken *token = info->token;
--
-- purple_account_disconnect(gc->account);
--
-- g_free(token->id);
-- g_free(token->data);
-- g_free(token);
--
--}
--
--static void ggp_register_user_dialog(PurpleConnection *gc)
--{
-- PurpleAccount *account;
-- PurpleRequestFields *fields;
-- PurpleRequestFieldGroup *group;
-- PurpleRequestField *field;
--
-- GGPInfo *info = gc->proto_data;
-- GGPToken *token = info->token;
--
--
-- account = purple_connection_get_account(gc);
--
-- fields = purple_request_fields_new();
-- group = purple_request_field_group_new(NULL);
-- purple_request_fields_add_group(fields, group);
--
-- field = purple_request_field_string_new("email",
-- _("Email"), "", FALSE);
-- purple_request_field_string_set_masked(field, FALSE);
-- purple_request_field_group_add_field(group, field);
--
-- field = purple_request_field_string_new("password1",
-- _("Password"), "", FALSE);
-- purple_request_field_string_set_masked(field, TRUE);
-- purple_request_field_group_add_field(group, field);
--
-- field = purple_request_field_string_new("password2",
-- _("Password (again)"), "", FALSE);
-- purple_request_field_string_set_masked(field, TRUE);
-- purple_request_field_group_add_field(group, field);
--
-- field = purple_request_field_string_new("token",
-- _("Enter captcha text"), "", FALSE);
-- purple_request_field_string_set_masked(field, FALSE);
-- purple_request_field_group_add_field(group, field);
--
-- /* original size: 60x24 */
-- field = purple_request_field_image_new("token_img",
-- _("Captcha"), token->data, token->size);
-- purple_request_field_group_add_field(group, field);
--
-- purple_request_fields(account,
-- _("Register New Gadu-Gadu Account"),
-- _("Register New Gadu-Gadu Account"),
-- _("Please, fill in the following fields"),
-- fields,
-- _("OK"), G_CALLBACK(ggp_callback_register_account_ok),
-- _("Cancel"), G_CALLBACK(ggp_callback_register_account_cancel),
-- purple_connection_get_account(gc), NULL, NULL,
-- gc);
--}
--
--/* ----- PUBLIC DIRECTORY SEARCH ---------------------------------------- */
--
--static void ggp_callback_show_next(PurpleConnection *gc, GList *row, gpointer user_data)
--{
-- GGPInfo *info = gc->proto_data;
-- GGPSearchForm *form = user_data;
-- guint32 seq;
--
-- form->page_number++;
--
-- ggp_search_remove(info->searches, form->seq);
-- purple_debug_info("gg", "ggp_callback_show_next(): Removed seq %u\n",
-- form->seq);
--
-- seq = ggp_search_start(gc, form);
-- ggp_search_add(info->searches, seq, form);
-- purple_debug_info("gg", "ggp_callback_show_next(): Added seq %u\n",
-- seq);
--}
--
--static void ggp_callback_add_buddy(PurpleConnection *gc, GList *row, gpointer user_data)
--{
-- purple_blist_request_add_buddy(purple_connection_get_account(gc),
-- g_list_nth_data(row, 0), NULL, NULL);
--}
--
--static void ggp_callback_im(PurpleConnection *gc, GList *row, gpointer user_data)
--{
-- PurpleAccount *account;
-- PurpleConversation *conv;
-- char *name;
--
-- account = purple_connection_get_account(gc);
--
-- name = g_list_nth_data(row, 0);
-- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, name);
-- purple_conversation_present(conv);
--}
--
--static void ggp_callback_find_buddies(PurpleConnection *gc, PurpleRequestFields *fields)
--{
-- GGPInfo *info = gc->proto_data;
-- GGPSearchForm *form;
-- guint32 seq;
--
-- form = ggp_search_form_new(GGP_SEARCH_TYPE_FULL);
--
-- form->user_data = info;
-- form->lastname = g_strdup(
-- purple_request_fields_get_string(fields, "lastname"));
-- form->firstname = g_strdup(
-- purple_request_fields_get_string(fields, "firstname"));
-- form->nickname = g_strdup(
-- purple_request_fields_get_string(fields, "nickname"));
-- form->city = g_strdup(
-- purple_request_fields_get_string(fields, "city"));
-- form->birthyear = g_strdup(
-- purple_request_fields_get_string(fields, "year"));
--
-- switch (purple_request_fields_get_choice(fields, "gender")) {
-- case 1:
-- form->gender = g_strdup(GG_PUBDIR50_GENDER_MALE);
-- break;
-- case 2:
-- form->gender = g_strdup(GG_PUBDIR50_GENDER_FEMALE);
-- break;
-- default:
-- form->gender = NULL;
-- break;
-- }
--
-- form->active = purple_request_fields_get_bool(fields, "active")
-- ? g_strdup(GG_PUBDIR50_ACTIVE_TRUE) : NULL;
--
-- seq = ggp_search_start(gc, form);
-- ggp_search_add(info->searches, seq, form);
-- purple_debug_info("gg", "ggp_callback_find_buddies(): Added seq %u\n",
-- seq);
--}
--
--static void ggp_find_buddies(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *)action->context;
--
-- PurpleRequestFields *fields;
-- PurpleRequestFieldGroup *group;
-- PurpleRequestField *field;
--
-- fields = purple_request_fields_new();
-- group = purple_request_field_group_new(NULL);
-- purple_request_fields_add_group(fields, group);
--
-- field = purple_request_field_string_new("lastname",
-- _("Last name"), NULL, FALSE);
-- purple_request_field_string_set_masked(field, FALSE);
-- purple_request_field_group_add_field(group, field);
--
-- field = purple_request_field_string_new("firstname",
-- _("First name"), NULL, FALSE);
-- purple_request_field_string_set_masked(field, FALSE);
-- purple_request_field_group_add_field(group, field);
--
-- field = purple_request_field_string_new("nickname",
-- _("Nickname"), NULL, FALSE);
-- purple_request_field_string_set_masked(field, FALSE);
-- purple_request_field_group_add_field(group, field);
--
-- field = purple_request_field_string_new("city",
-- _("City"), NULL, FALSE);
-- purple_request_field_string_set_masked(field, FALSE);
-- purple_request_field_group_add_field(group, field);
--
-- field = purple_request_field_string_new("year",
-- _("Year of birth"), NULL, FALSE);
-- purple_request_field_group_add_field(group, field);
--
-- field = purple_request_field_choice_new("gender", _("Gender"), 0);
-- purple_request_field_choice_add(field, _("Male or female"));
-- purple_request_field_choice_add(field, _("Male"));
-- purple_request_field_choice_add(field, _("Female"));
-- purple_request_field_group_add_field(group, field);
--
-- field = purple_request_field_bool_new("active",
-- _("Only online"), FALSE);
-- purple_request_field_group_add_field(group, field);
--
-- purple_request_fields(gc,
-- _("Find buddies"),
-- _("Find buddies"),
-- _("Please, enter your search criteria below"),
-- fields,
-- _("OK"), G_CALLBACK(ggp_callback_find_buddies),
-- _("Cancel"), NULL,
-- purple_connection_get_account(gc), NULL, NULL,
-- gc);
--}
--
--/* ----- CHANGE PASSWORD ------------------------------------------------ */
--
--static void ggp_callback_change_passwd_ok(PurpleConnection *gc, PurpleRequestFields *fields)
--{
-- PurpleAccount *account;
-- GGPInfo *info = gc->proto_data;
-- struct gg_http *h;
-- gchar *cur, *p1, *p2, *t;
--
-- cur = charset_convert(
-- purple_request_fields_get_string(fields, "password_cur"),
-- "UTF-8", "CP1250");
-- p1 = charset_convert(
-- purple_request_fields_get_string(fields, "password1"),
-- "UTF-8", "CP1250");
-- p2 = charset_convert(
-- purple_request_fields_get_string(fields, "password2"),
-- "UTF-8", "CP1250");
-- t = charset_convert(
-- purple_request_fields_get_string(fields, "token"),
-- "UTF-8", "CP1250");
--
-- account = purple_connection_get_account(gc);
--
-- if (cur == NULL || p1 == NULL || p2 == NULL || t == NULL ||
-- *cur == '\0' || *p1 == '\0' || *p2 == '\0' || *t == '\0') {
-- purple_notify_error(account, NULL, _("Fill in the fields."), NULL);
-- goto exit_err;
-- }
--
-- if (g_utf8_collate(p1, p2) != 0) {
-- purple_notify_error(account, NULL,
-- _("New passwords do not match."), NULL);
-- goto exit_err;
-- }
--
-- if (g_utf8_collate(cur, purple_account_get_password(account)) != 0) {
-- purple_notify_error(account, NULL,
-- _("Your current password is different from the one that you specified."),
-- NULL);
-- goto exit_err;
-- }
--
-- purple_debug_info("gg", "Changing password\n");
--
-- /* XXX: this email should be a pref... */
-- h = gg_change_passwd4(ggp_get_uin(account),
-- "user@example.net", purple_account_get_password(account),
-- p1, info->token->id, t, 0);
--
-- if (h == NULL) {
-- purple_notify_error(account, NULL,
-- _("Unable to change password. Error occurred.\n"),
-- NULL);
-- goto exit_err;
-- }
--
-- purple_account_set_password(account, p1);
--
-- gg_change_passwd_free(h);
--
-- purple_notify_info(account, _("Change password for the Gadu-Gadu account"),
-- _("Password was changed successfully!"), NULL);
--
--exit_err:
-- g_free(cur);
-- g_free(p1);
-- g_free(p2);
-- g_free(t);
-- g_free(info->token->id);
-- g_free(info->token->data);
-- g_free(info->token);
--}
--
--static void ggp_change_passwd_dialog(PurpleConnection *gc)
--{
-- PurpleRequestFields *fields;
-- PurpleRequestFieldGroup *group;
-- PurpleRequestField *field;
--
-- GGPInfo *info = gc->proto_data;
-- GGPToken *token = info->token;
--
-- char *msg;
--
--
-- fields = purple_request_fields_new();
-- group = purple_request_field_group_new(NULL);
-- purple_request_fields_add_group(fields, group);
--
-- field = purple_request_field_string_new("password_cur",
-- _("Current password"), "", FALSE);
-- purple_request_field_string_set_masked(field, TRUE);
-- purple_request_field_group_add_field(group, field);
--
-- field = purple_request_field_string_new("password1",
-- _("Password"), "", FALSE);
-- purple_request_field_string_set_masked(field, TRUE);
-- purple_request_field_group_add_field(group, field);
--
-- field = purple_request_field_string_new("password2",
-- _("Password (retype)"), "", FALSE);
-- purple_request_field_string_set_masked(field, TRUE);
-- purple_request_field_group_add_field(group, field);
--
-- field = purple_request_field_string_new("token",
-- _("Enter current token"), "", FALSE);
-- purple_request_field_string_set_masked(field, FALSE);
-- purple_request_field_group_add_field(group, field);
--
-- /* original size: 60x24 */
-- field = purple_request_field_image_new("token_img",
-- _("Current token"), token->data, token->size);
-- purple_request_field_group_add_field(group, field);
--
-- msg = g_strdup_printf("%s %d",
-- _("Please, enter your current password and your new password for UIN: "),
-- ggp_get_uin(purple_connection_get_account(gc)));
--
-- purple_request_fields(gc,
-- _("Change Gadu-Gadu Password"),
-- _("Change Gadu-Gadu Password"),
-- msg,
-- fields, _("OK"), G_CALLBACK(ggp_callback_change_passwd_ok),
-- _("Cancel"), NULL,
-- purple_connection_get_account(gc), NULL, NULL,
-- gc);
--
-- g_free(msg);
--}
--
--static void ggp_change_passwd(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *)action->context;
--
-- ggp_token_request(gc, ggp_change_passwd_dialog);
--}
--
--/* ----- CHANGE STATUS BROADCASTING ------------------------------------------------ */
--
--static void ggp_action_change_status_broadcasting_ok(PurpleConnection *gc, PurpleRequestFields *fields)
--{
-- GGPInfo *info = gc->proto_data;
-- int selected_field;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- PurpleStatus *status;
--
-- selected_field = purple_request_fields_get_choice(fields, "status_broadcasting");
--
-- if (selected_field == 0)
-- info->status_broadcasting = TRUE;
-- else
-- info->status_broadcasting = FALSE;
--
-- status = purple_account_get_active_status(account);
--
-- ggp_set_status(account, status);
--}
--
--static void ggp_action_change_status_broadcasting(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *)action->context;
-- GGPInfo *info = gc->proto_data;
--
-- PurpleRequestFields *fields;
-- PurpleRequestFieldGroup *group;
-- PurpleRequestField *field;
--
-- fields = purple_request_fields_new();
-- group = purple_request_field_group_new(NULL);
-- purple_request_fields_add_group(fields, group);
--
-- field = purple_request_field_choice_new("status_broadcasting", _("Show status to:"), 0);
-- purple_request_field_choice_add(field, _("All people"));
-- purple_request_field_choice_add(field, _("Only buddies"));
-- purple_request_field_group_add_field(group, field);
--
-- if (info->status_broadcasting)
-- purple_request_field_choice_set_default_value(field, 0);
-- else
-- purple_request_field_choice_set_default_value(field, 1);
--
-- purple_request_fields(gc,
-- _("Change status broadcasting"),
-- _("Change status broadcasting"),
-- _("Please, select who can see your status"),
-- fields,
-- _("OK"), G_CALLBACK(ggp_action_change_status_broadcasting_ok),
-- _("Cancel"), NULL,
-- purple_connection_get_account(gc), NULL, NULL,
-- gc);
--}
--
--/* ----- CONFERENCES ---------------------------------------------------- */
--
--static void ggp_callback_add_to_chat_ok(PurpleBuddy *buddy, PurpleRequestFields *fields)
--{
-- PurpleConnection *conn;
-- PurpleRequestField *field;
-- GList *sel;
--
-- conn = purple_account_get_connection(purple_buddy_get_account(buddy));
--
-- g_return_if_fail(conn != NULL);
--
-- field = purple_request_fields_get_field(fields, "name");
-- sel = purple_request_field_list_get_selected(field);
--
-- if (sel == NULL) {
-- purple_debug_error("gg", "No chat selected\n");
-- return;
-- }
--
-- ggp_confer_participants_add_uin(conn, sel->data,
-- ggp_str_to_uin(purple_buddy_get_name(buddy)));
--}
--
--static void ggp_bmenu_add_to_chat(PurpleBlistNode *node, gpointer ignored)
--{
-- PurpleBuddy *buddy;
-- PurpleConnection *gc;
-- GGPInfo *info;
--
-- PurpleRequestFields *fields;
-- PurpleRequestFieldGroup *group;
-- PurpleRequestField *field;
--
-- GList *l;
-- gchar *msg;
--
-- buddy = (PurpleBuddy *)node;
-- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-- info = gc->proto_data;
--
-- fields = purple_request_fields_new();
-- group = purple_request_field_group_new(NULL);
-- purple_request_fields_add_group(fields, group);
--
-- field = purple_request_field_list_new("name", "Chat name");
-- for (l = info->chats; l != NULL; l = l->next) {
-- GGPChat *chat = l->data;
-- purple_request_field_list_add(field, chat->name, chat->name);
-- }
-- purple_request_field_group_add_field(group, field);
--
-- msg = g_strdup_printf(_("Select a chat for buddy: %s"),
-- purple_buddy_get_alias(buddy));
-- purple_request_fields(gc,
-- _("Add to chat..."),
-- _("Add to chat..."),
-- msg,
-- fields,
-- _("Add"), G_CALLBACK(ggp_callback_add_to_chat_ok),
-- _("Cancel"), NULL,
-- purple_connection_get_account(gc), NULL, NULL,
-- buddy);
-- g_free(msg);
--}
--
--/* ----- BLOCK BUDDIES -------------------------------------------------- */
--
--static void ggp_add_deny(PurpleConnection *gc, const char *who)
--{
-- GGPInfo *info = gc->proto_data;
-- uin_t uin = ggp_str_to_uin(who);
--
-- purple_debug_info("gg", "ggp_add_deny: %u\n", uin);
--
-- gg_remove_notify_ex(info->session, uin, GG_USER_NORMAL);
-- gg_add_notify_ex(info->session, uin, GG_USER_BLOCKED);
--}
--
--static void ggp_rem_deny(PurpleConnection *gc, const char *who)
--{
-- GGPInfo *info = gc->proto_data;
-- uin_t uin = ggp_str_to_uin(who);
--
-- purple_debug_info("gg", "ggp_rem_deny: %u\n", uin);
--
-- gg_remove_notify_ex(info->session, uin, GG_USER_BLOCKED);
-- gg_add_notify_ex(info->session, uin, GG_USER_NORMAL);
--}
--
--/* ---------------------------------------------------------------------- */
--/* ----- INTERNAL CALLBACKS --------------------------------------------- */
--/* ---------------------------------------------------------------------- */
--
--#if !DISABLE_AVATARS
--
--struct gg_fetch_avatar_data
--{
-- PurpleConnection *gc;
-- gchar *uin;
-- gchar *avatar_url;
--};
--
--
--static void gg_fetch_avatar_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
-- const gchar *data, size_t len, const gchar *error_message) {
-- struct gg_fetch_avatar_data *d = user_data;
-- PurpleAccount *account;
-- PurpleBuddy *buddy;
-- gpointer buddy_icon_data;
--
-- purple_debug_info("gg", "gg_fetch_avatar_cb: got avatar image for %s\n",
-- d->uin);
--
-- /* FIXME: This shouldn't be necessary */
-- if (!PURPLE_CONNECTION_IS_VALID(d->gc)) {
-- g_free(d->uin);
-- g_free(d->avatar_url);
-- g_free(d);
-- g_return_if_reached();
-- }
--
-- account = purple_connection_get_account(d->gc);
-- buddy = purple_find_buddy(account, d->uin);
--
-- if (buddy == NULL)
-- goto out;
--
-- buddy_icon_data = g_memdup(data, len);
--
-- purple_buddy_icons_set_for_user(account, purple_buddy_get_name(buddy),
-- buddy_icon_data, len, d->avatar_url);
-- purple_debug_info("gg", "gg_fetch_avatar_cb: UIN %s should have avatar "
-- "now\n", d->uin);
--
--out:
-- g_free(d->uin);
-- g_free(d->avatar_url);
-- g_free(d);
--}
--
--static void gg_get_avatar_url_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
-- const gchar *url_text, size_t len, const gchar *error_message) {
-- struct gg_fetch_avatar_data *data;
-- PurpleConnection *gc = user_data;
-- PurpleAccount *account;
-- PurpleBuddy *buddy;
-- const char *uin;
-- const char *is_blank;
-- const char *checksum;
--
-- gchar *bigavatar = NULL;
-- xmlnode *xml = NULL;
-- xmlnode *xmlnode_users;
-- xmlnode *xmlnode_user;
-- xmlnode *xmlnode_avatars;
-- xmlnode *xmlnode_avatar;
-- xmlnode *xmlnode_bigavatar;
--
-- g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
-- account = purple_connection_get_account(gc);
--
-- if (error_message != NULL)
-- purple_debug_error("gg", "gg_get_avatars_cb error: %s\n", error_message);
-- else if (len > 0 && url_text && *url_text) {
-- xml = xmlnode_from_str(url_text, -1);
-- if (xml == NULL)
-- goto out;
--
-- xmlnode_users = xmlnode_get_child(xml, "users");
-- if (xmlnode_users == NULL)
-- goto out;
--
-- xmlnode_user = xmlnode_get_child(xmlnode_users, "user");
-- if (xmlnode_user == NULL)
-- goto out;
--
-- uin = xmlnode_get_attrib(xmlnode_user, "uin");
--
-- xmlnode_avatars = xmlnode_get_child(xmlnode_user, "avatars");
-- if (xmlnode_avatars == NULL)
-- goto out;
--
-- xmlnode_avatar = xmlnode_get_child(xmlnode_avatars, "avatar");
-- if (xmlnode_avatar == NULL)
-- goto out;
--
-- xmlnode_bigavatar = xmlnode_get_child(xmlnode_avatar, "originBigAvatar");
-- if (xmlnode_bigavatar == NULL)
-- goto out;
--
-- is_blank = xmlnode_get_attrib(xmlnode_avatar, "blank");
-- bigavatar = xmlnode_get_data(xmlnode_bigavatar);
--
-- purple_debug_info("gg", "gg_get_avatar_url_cb: UIN %s, IS_BLANK %s, "
-- "URL %s\n",
-- uin ? uin : "(null)", is_blank ? is_blank : "(null)",
-- bigavatar ? bigavatar : "(null)");
--
-- if (uin != NULL && bigavatar != NULL) {
-- buddy = purple_find_buddy(account, uin);
-- if (buddy == NULL)
-- goto out;
--
-- checksum = purple_buddy_icons_get_checksum_for_user(buddy);
--
-- if (purple_strequal(is_blank, "1")) {
-- purple_buddy_icons_set_for_user(account,
-- purple_buddy_get_name(buddy), NULL, 0, NULL);
-- } else if (!purple_strequal(checksum, bigavatar)) {
-- data = g_new0(struct gg_fetch_avatar_data, 1);
-- data->gc = gc;
-- data->uin = g_strdup(uin);
-- data->avatar_url = g_strdup(bigavatar);
--
-- purple_debug_info("gg", "gg_get_avatar_url_cb: "
-- "requesting avatar for %s\n", uin);
-- url_data = purple_util_fetch_url_request_len_with_account(account,
-- bigavatar, TRUE, "Mozilla/4.0 (compatible; MSIE 5.0)",
-- FALSE, NULL, FALSE, -1, gg_fetch_avatar_cb, data);
-- }
-- }
-- }
--
--out:
-- if (xml)
-- xmlnode_free(xml);
-- g_free(bigavatar);
--}
--
--#endif
--
--/**
-- * Try to update avatar of the buddy.
-- *
-- * @param gc PurpleConnection
-- * @param uin UIN of the buddy.
-- */
--static void ggp_update_buddy_avatar(PurpleConnection *gc, uin_t uin)
--{
--#if DISABLE_AVATARS
-- purple_debug_warning("gg", "ggp_update_buddy_avatar: disabled, please "
-- "update to 3.0.0, when available\n");
--#else
-- gchar *avatarurl;
-- PurpleUtilFetchUrlData *url_data;
--
-- purple_debug_info("gg", "ggp_update_buddy_avatar(gc, %u)\n", uin);
--
-- avatarurl = g_strdup_printf("http://api.gadu-gadu.pl/avatars/%u/0.xml", uin);
--
-- url_data = purple_util_fetch_url_request_len_with_account(
-- purple_connection_get_account(gc), avatarurl, TRUE,
-- "Mozilla/4.0 (compatible; MSIE 5.5)", FALSE, NULL, FALSE, -1,
-- gg_get_avatar_url_cb, gc);
--
-- g_free(avatarurl);
--#endif
--}
--
--/**
-- * Handle change of the status of the buddy.
-- *
-- * @param gc PurpleConnection
-- * @param uin UIN of the buddy.
-- * @param status ID of the status.
-- * @param descr Description.
-- */
--static void ggp_generic_status_handler(PurpleConnection *gc, uin_t uin,
-- int status, const char *descr)
--{
-- gchar *from;
-- const char *st;
-- char *status_msg = NULL;
--
-- ggp_update_buddy_avatar(gc, uin);
--
-- from = g_strdup_printf("%u", uin);
--
-- switch (status) {
-- case GG_STATUS_NOT_AVAIL:
-- case GG_STATUS_NOT_AVAIL_DESCR:
-- st = purple_primitive_get_id_from_type(PURPLE_STATUS_OFFLINE);
-- break;
-- case GG_STATUS_FFC:
-- case GG_STATUS_FFC_DESCR:
-- st = purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE);
-- break;
-- case GG_STATUS_AVAIL:
-- case GG_STATUS_AVAIL_DESCR:
-- st = purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE);
-- break;
-- case GG_STATUS_BUSY:
-- case GG_STATUS_BUSY_DESCR:
-- st = purple_primitive_get_id_from_type(PURPLE_STATUS_AWAY);
-- break;
-- case GG_STATUS_DND:
-- case GG_STATUS_DND_DESCR:
-- st = purple_primitive_get_id_from_type(PURPLE_STATUS_UNAVAILABLE);
-- break;
-- case GG_STATUS_BLOCKED:
-- /* user is blocking us.... */
-- st = "blocked";
-- break;
-- default:
-- st = purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE);
-- purple_debug_info("gg",
-- "GG_EVENT_NOTIFY: Unknown status: %d\n", status);
-- break;
-- }
--
-- if (descr != NULL) {
-- status_msg = g_strdup(descr);
-- g_strstrip(status_msg);
-- if (status_msg[0] == '\0') {
-- g_free(status_msg);
-- status_msg = NULL;
-- }
-- }
--
-- purple_debug_info("gg", "status of %u is %s [%s]\n", uin, st,
-- status_msg ? status_msg : "");
-- if (status_msg == NULL) {
-- purple_prpl_got_user_status(purple_connection_get_account(gc),
-- from, st, NULL);
-- } else {
-- purple_prpl_got_user_status(purple_connection_get_account(gc),
-- from, st, "message", status_msg, NULL);
-- g_free(status_msg);
-- }
-- g_free(from);
--}
--
--static void ggp_sr_close_cb(gpointer user_data)
--{
-- GGPSearchForm *form = user_data;
-- GGPInfo *info = form->user_data;
--
-- ggp_search_remove(info->searches, form->seq);
-- purple_debug_info("gg", "ggp_sr_close_cb(): Removed seq %u\n",
-- form->seq);
-- ggp_search_form_destroy(form);
--}
--
--/**
-- * Translate a status' ID to a more user-friendly name.
-- *
-- * @param id The ID of the status.
-- *
-- * @return The user-friendly name of the status.
-- */
--static const char *ggp_status_by_id(unsigned int id)
--{
-- const char *st;
--
-- purple_debug_info("gg", "ggp_status_by_id: %d\n", id);
-- switch (id) {
-- case GG_STATUS_NOT_AVAIL:
-- case GG_STATUS_NOT_AVAIL_DESCR:
-- st = _("Offline");
-- break;
-- case GG_STATUS_AVAIL:
-- case GG_STATUS_AVAIL_DESCR:
-- st = _("Available");
-- break;
-- case GG_STATUS_FFC:
-- case GG_STATUS_FFC_DESCR:
-- return _("Chatty");
-- case GG_STATUS_DND:
-- case GG_STATUS_DND_DESCR:
-- return _("Do Not Disturb");
-- case GG_STATUS_BUSY:
-- case GG_STATUS_BUSY_DESCR:
-- st = _("Away");
-- break;
-- default:
-- st = _("Unknown");
-- break;
-- }
--
-- return st;
--}
--
--static void ggp_pubdir_handle_info(PurpleConnection *gc, gg_pubdir50_t req,
-- GGPSearchForm *form)
--{
-- PurpleNotifyUserInfo *user_info;
-- PurpleBuddy *buddy;
-- char *val, *who;
--
-- user_info = purple_notify_user_info_new();
--
-- val = ggp_search_get_result(req, 0, GG_PUBDIR50_STATUS);
-- /* XXX: Use of ggp_str_to_uin() is an ugly hack! */
-- purple_notify_user_info_add_pair(user_info, _("Status"), ggp_status_by_id(ggp_str_to_uin(val)));
-- g_free(val);
--
-- who = ggp_search_get_result(req, 0, GG_PUBDIR50_UIN);
-- purple_notify_user_info_add_pair(user_info, _("UIN"), who);
--
-- val = ggp_search_get_result(req, 0, GG_PUBDIR50_FIRSTNAME);
-- purple_notify_user_info_add_pair(user_info, _("First Name"), val);
-- g_free(val);
--
-- val = ggp_search_get_result(req, 0, GG_PUBDIR50_NICKNAME);
-- purple_notify_user_info_add_pair(user_info, _("Nickname"), val);
-- g_free(val);
--
-- val = ggp_search_get_result(req, 0, GG_PUBDIR50_CITY);
-- purple_notify_user_info_add_pair(user_info, _("City"), val);
-- g_free(val);
--
-- val = ggp_search_get_result(req, 0, GG_PUBDIR50_BIRTHYEAR);
-- if (strncmp(val, "0", 1)) {
-- purple_notify_user_info_add_pair(user_info, _("Birth Year"), val);
-- }
-- g_free(val);
--
-- /*
-- * Include a status message, if exists and buddy is in the blist.
-- */
-- buddy = purple_find_buddy(purple_connection_get_account(gc), who);
-- if (NULL != buddy) {
-- PurpleStatus *status;
-- const char *msg;
-- char *text;
--
-- status = purple_presence_get_active_status(purple_buddy_get_presence(buddy));
-- msg = purple_status_get_attr_string(status, "message");
--
-- if (msg != NULL) {
-- text = g_markup_escape_text(msg, -1);
-- purple_notify_user_info_add_pair(user_info, _("Message"), text);
-- g_free(text);
-- }
-- }
--
-- purple_notify_userinfo(gc, who, user_info, ggp_sr_close_cb, form);
-- g_free(who);
-- purple_notify_user_info_destroy(user_info);
--}
--
--static void ggp_pubdir_handle_full(PurpleConnection *gc, gg_pubdir50_t req,
-- GGPSearchForm *form)
--{
-- PurpleNotifySearchResults *results;
-- PurpleNotifySearchColumn *column;
-- int res_count;
-- int start;
-- int i;
--
-- g_return_if_fail(form != NULL);
--
-- res_count = gg_pubdir50_count(req);
-- res_count = (res_count > PUBDIR_RESULTS_MAX) ? PUBDIR_RESULTS_MAX : res_count;
-- if (form->page_size == 0)
-- form->page_size = res_count;
--
-- results = purple_notify_searchresults_new();
--
-- if (results == NULL) {
-- purple_debug_error("gg", "ggp_pubdir_reply_handler: "
-- "Unable to display the search results.\n");
-- purple_notify_error(gc, NULL,
-- _("Unable to display the search results."),
-- NULL);
-- if (form->window == NULL)
-- ggp_sr_close_cb(form);
-- return;
-- }
--
-- column = purple_notify_searchresults_column_new(_("UIN"));
-- purple_notify_searchresults_column_add(results, column);
--
-- column = purple_notify_searchresults_column_new(_("First Name"));
-- purple_notify_searchresults_column_add(results, column);
--
-- column = purple_notify_searchresults_column_new(_("Nickname"));
-- purple_notify_searchresults_column_add(results, column);
--
-- column = purple_notify_searchresults_column_new(_("City"));
-- purple_notify_searchresults_column_add(results, column);
--
-- column = purple_notify_searchresults_column_new(_("Birth Year"));
-- purple_notify_searchresults_column_add(results, column);
--
-- purple_debug_info("gg", "Going with %d entries\n", res_count);
--
-- start = (int)ggp_str_to_uin(gg_pubdir50_get(req, 0, GG_PUBDIR50_START));
-- purple_debug_info("gg", "start = %d\n", start);
--
-- for (i = 0; i < res_count; i++) {
-- GList *row = NULL;
-- char *birth = ggp_search_get_result(req, i, GG_PUBDIR50_BIRTHYEAR);
--
-- /* TODO: Status will be displayed as an icon. */
-- /* row = g_list_append(row, ggp_search_get_result(req, i, GG_PUBDIR50_STATUS)); */
-- row = g_list_append(row, ggp_search_get_result(req, i,
-- GG_PUBDIR50_UIN));
-- row = g_list_append(row, ggp_search_get_result(req, i,
-- GG_PUBDIR50_FIRSTNAME));
-- row = g_list_append(row, ggp_search_get_result(req, i,
-- GG_PUBDIR50_NICKNAME));
-- row = g_list_append(row, ggp_search_get_result(req, i,
-- GG_PUBDIR50_CITY));
-- row = g_list_append(row,
-- (birth && strncmp(birth, "0", 1)) ? birth : g_strdup("-"));
--
-- purple_notify_searchresults_row_add(results, row);
-- }
--
-- purple_notify_searchresults_button_add(results, PURPLE_NOTIFY_BUTTON_CONTINUE,
-- ggp_callback_show_next);
-- purple_notify_searchresults_button_add(results, PURPLE_NOTIFY_BUTTON_ADD,
-- ggp_callback_add_buddy);
-- purple_notify_searchresults_button_add(results, PURPLE_NOTIFY_BUTTON_IM,
-- ggp_callback_im);
--
-- if (form->window == NULL) {
-- void *h = purple_notify_searchresults(gc,
-- _("Gadu-Gadu Public Directory"),
-- _("Search results"), NULL, results,
-- (PurpleNotifyCloseCallback)ggp_sr_close_cb,
-- form);
--
-- if (h == NULL) {
-- purple_debug_error("gg", "ggp_pubdir_reply_handler: "
-- "Unable to display the search results.\n");
-- purple_notify_error(gc, NULL,
-- _("Unable to display the search results."),
-- NULL);
-- return;
-- }
--
-- form->window = h;
-- } else {
-- purple_notify_searchresults_new_rows(gc, results, form->window);
-- }
--}
--
--static void ggp_pubdir_reply_handler(PurpleConnection *gc, gg_pubdir50_t req)
--{
-- GGPInfo *info = gc->proto_data;
-- GGPSearchForm *form;
-- int res_count;
-- guint32 seq;
--
-- seq = gg_pubdir50_seq(req);
-- form = ggp_search_get(info->searches, seq);
-- purple_debug_info("gg",
-- "ggp_pubdir_reply_handler(): seq %u --> form %p\n", seq, form);
-- /*
-- * this can happen when user will request more results
-- * and close the results window before they arrive.
-- */
-- g_return_if_fail(form != NULL);
--
-- res_count = gg_pubdir50_count(req);
-- if (res_count < 1) {
-- purple_debug_info("gg", "GG_EVENT_PUBDIR50_SEARCH_REPLY: Nothing found\n");
-- purple_notify_error(gc, NULL,
-- _("No matching users found"),
-- _("There are no users matching your search criteria."));
-- if (form->window == NULL)
-- ggp_sr_close_cb(form);
-- return;
-- }
--
-- switch (form->search_type) {
-- case GGP_SEARCH_TYPE_INFO:
-- ggp_pubdir_handle_info(gc, req, form);
-- break;
-- case GGP_SEARCH_TYPE_FULL:
-- ggp_pubdir_handle_full(gc, req, form);
-- break;
-- default:
-- purple_debug_warning("gg", "Unknown search_type!\n");
-- break;
-- }
--}
--
--static void ggp_recv_image_handler(PurpleConnection *gc, const struct gg_event *ev)
--{
-- gint imgid = 0;
-- GGPInfo *info = gc->proto_data;
-- GList *entry = g_list_first(info->pending_richtext_messages);
-- gchar *handlerid = g_strdup_printf("IMGID_HANDLER-%i", ev->event.image_reply.crc32);
--
-- imgid = purple_imgstore_add_with_id(
-- g_memdup(ev->event.image_reply.image, ev->event.image_reply.size),
-- ev->event.image_reply.size,
-- ev->event.image_reply.filename);
--
-- purple_debug_info("gg", "ggp_recv_image_handler: got image with crc32: %u\n", ev->event.image_reply.crc32);
--
-- while(entry) {
-- if (strstr((gchar *)entry->data, handlerid) != NULL) {
-- gchar **split = g_strsplit((gchar *)entry->data, handlerid, 3);
-- gchar *text = g_strdup_printf("%s%i%s", split[0], imgid, split[1]);
-- purple_debug_info("gg", "ggp_recv_image_handler: found message matching crc32: %s\n", (gchar *)entry->data);
-- g_strfreev(split);
-- info->pending_richtext_messages = g_list_remove(info->pending_richtext_messages, entry->data);
-- /* We don't have any more images to download */
-- if (strstr(text, "<IMG ID=\"IMGID_HANDLER") == NULL) {
-- gchar *buf = g_strdup_printf("%lu", (unsigned long int)ev->event.image_reply.sender);
-- serv_got_im(gc, buf, text, PURPLE_MESSAGE_IMAGES, time(NULL));
-- g_free(buf);
-- purple_debug_info("gg", "ggp_recv_image_handler: richtext message: %s\n", text);
-- g_free(text);
-- break;
-- }
-- info->pending_richtext_messages = g_list_append(info->pending_richtext_messages, text);
-- break;
-- }
-- entry = g_list_next(entry);
-- }
-- g_free(handlerid);
--
-- return;
--}
--
--
--/**
-- * Dispatch a message received from a buddy.
-- *
-- * @param gc PurpleConnection.
-- * @param ev Gadu-Gadu event structure.
-- *
-- * Image receiving, some code borrowed from Kadu http://www.kadu.net
-- */
--static void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event *ev)
--{
-- GGPInfo *info = gc->proto_data;
-- PurpleConversation *conv;
-- gchar *from;
-- gchar *msg;
-- gchar *tmp;
--
-- if (ev->event.msg.message == NULL)
-- {
-- purple_debug_warning("gg", "ggp_recv_message_handler: NULL as message pointer\n");
-- return;
-- }
--
-- from = g_strdup_printf("%lu", (unsigned long int)ev->event.msg.sender);
--
-- /*
-- tmp = charset_convert((const char *)ev->event.msg.message,
-- "CP1250", "UTF-8");
-- */
-- tmp = g_strdup_printf("%s", ev->event.msg.message);
-- purple_str_strip_char(tmp, '\r');
-- msg = g_markup_escape_text(tmp, -1);
-- g_free(tmp);
--
-- /* We got richtext message */
-- if (ev->event.msg.formats_length)
-- {
-- gboolean got_image = FALSE, bold = FALSE, italic = FALSE, under = FALSE;
-- char *cformats = (char *)ev->event.msg.formats;
-- char *cformats_end = cformats + ev->event.msg.formats_length;
-- gint increased_len = 0;
-- struct gg_msg_richtext_format *actformat;
-- struct gg_msg_richtext_image *actimage;
-- GString *message = g_string_new(msg);
-- gchar *handlerid;
--
-- purple_debug_info("gg", "ggp_recv_message_handler: richtext msg from (%s): %s %i formats\n", from, msg, ev->event.msg.formats_length);
--
-- while (cformats < cformats_end)
-- {
-- gint byteoffset;
-- actformat = (struct gg_msg_richtext_format *)cformats;
-- cformats += sizeof(struct gg_msg_richtext_format);
-- byteoffset = g_utf8_offset_to_pointer(message->str, actformat->position + increased_len) - message->str;
--
-- if(actformat->position == 0 && actformat->font == 0) {
-- purple_debug_warning("gg", "ggp_recv_message_handler: bogus formatting (inc: %i)\n", increased_len);
-- continue;
-- }
-- purple_debug_info("gg", "ggp_recv_message_handler: format at pos: %i, image:%i, bold:%i, italic: %i, under:%i (inc: %i)\n",
-- actformat->position,
-- (actformat->font & GG_FONT_IMAGE) != 0,
-- (actformat->font & GG_FONT_BOLD) != 0,
-- (actformat->font & GG_FONT_ITALIC) != 0,
-- (actformat->font & GG_FONT_UNDERLINE) != 0,
-- increased_len);
--
-- if (actformat->font & GG_FONT_IMAGE) {
-- got_image = TRUE;
-- actimage = (struct gg_msg_richtext_image*)(cformats);
-- cformats += sizeof(struct gg_msg_richtext_image);
-- purple_debug_info("gg", "ggp_recv_message_handler: image received, size: %d, crc32: %i\n", actimage->size, actimage->crc32);
--
-- /* Checking for errors, image size shouldn't be
-- * larger than 255.000 bytes */
-- if (actimage->size > 255000) {
-- purple_debug_warning("gg", "ggp_recv_message_handler: received image large than 255 kb\n");
-- continue;
-- }
--
-- gg_image_request(info->session, ev->event.msg.sender,
-- actimage->size, actimage->crc32);
--
-- handlerid = g_strdup_printf("<IMG ID=\"IMGID_HANDLER-%i\">", actimage->crc32);
-- g_string_insert(message, byteoffset, handlerid);
-- increased_len += strlen(handlerid);
-- g_free(handlerid);
-- continue;
-- }
--
-- if (actformat->font & GG_FONT_BOLD) {
-- if (bold == FALSE) {
-- g_string_insert(message, byteoffset, "<b>");
-- increased_len += 3;
-- bold = TRUE;
-- }
-- } else if (bold) {
-- g_string_insert(message, byteoffset, "</b>");
-- increased_len += 4;
-- bold = FALSE;
-- }
--
-- if (actformat->font & GG_FONT_ITALIC) {
-- if (italic == FALSE) {
-- g_string_insert(message, byteoffset, "<i>");
-- increased_len += 3;
-- italic = TRUE;
-- }
-- } else if (italic) {
-- g_string_insert(message, byteoffset, "</i>");
-- increased_len += 4;
-- italic = FALSE;
-- }
--
-- if (actformat->font & GG_FONT_UNDERLINE) {
-- if (under == FALSE) {
-- g_string_insert(message, byteoffset, "<u>");
-- increased_len += 3;
-- under = TRUE;
-- }
-- } else if (under) {
-- g_string_insert(message, byteoffset, "</u>");
-- increased_len += 4;
-- under = FALSE;
-- }
--
-- if (actformat->font & GG_FONT_COLOR) {
-- cformats += sizeof(struct gg_msg_richtext_color);
-- }
-- }
--
-- msg = message->str;
-- g_string_free(message, FALSE);
--
-- if (got_image) {
-- info->pending_richtext_messages = g_list_append(info->pending_richtext_messages, msg);
-- return;
-- }
-- }
--
-- purple_debug_info("gg", "ggp_recv_message_handler: msg from (%s): %s (class = %d; rcpt_count = %d)\n",
-- from, msg, ev->event.msg.msgclass,
-- ev->event.msg.recipients_count);
--
-- if (ev->event.msg.recipients_count == 0) {
-- serv_got_im(gc, from, msg, 0, ev->event.msg.time);
-- } else {
-- const char *chat_name;
-- int chat_id;
-- char *buddy_name;
--
-- chat_name = ggp_confer_find_by_participants(gc,
-- ev->event.msg.recipients,
-- ev->event.msg.recipients_count);
--
-- if (chat_name == NULL) {
-- chat_name = ggp_confer_add_new(gc, NULL);
-- serv_got_joined_chat(gc, info->chats_count, chat_name);
--
-- ggp_confer_participants_add_uin(gc, chat_name,
-- ev->event.msg.sender);
--
-- ggp_confer_participants_add(gc, chat_name,
-- ev->event.msg.recipients,
-- ev->event.msg.recipients_count);
-- }
-- conv = ggp_confer_find_by_name(gc, chat_name);
-- chat_id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv));
--
-- buddy_name = ggp_buddy_get_name(gc, ev->event.msg.sender);
-- serv_got_chat_in(gc, chat_id, buddy_name,
-- PURPLE_MESSAGE_RECV, msg, ev->event.msg.time);
-- g_free(buddy_name);
-- }
-- g_free(msg);
-- g_free(from);
--}
--
--static void ggp_send_image_handler(PurpleConnection *gc, const struct gg_event *ev)
--{
-- GGPInfo *info = gc->proto_data;
-- PurpleStoredImage *image;
-- gint imgid = GPOINTER_TO_INT(g_hash_table_lookup(info->pending_images, GINT_TO_POINTER(ev->event.image_request.crc32)));
--
-- purple_debug_info("gg", "ggp_send_image_handler: image request received, crc32: %u, imgid: %d\n", ev->event.image_request.crc32, imgid);
--
-- if(imgid)
-- {
-- if((image = purple_imgstore_find_by_id(imgid))) {
-- gint image_size = purple_imgstore_get_size(image);
-- gconstpointer image_bin = purple_imgstore_get_data(image);
-- const char *image_filename = purple_imgstore_get_filename(image);
--
-- purple_debug_info("gg", "ggp_send_image_handler: sending image imgid: %i, crc: %u\n", imgid, ev->event.image_request.crc32);
-- gg_image_reply(info->session, (unsigned long int)ev->event.image_request.sender, image_filename, image_bin, image_size);
-- purple_imgstore_unref(image);
-- } else {
-- purple_debug_error("gg", "ggp_send_image_handler: image imgid: %i, crc: %u in hash but not found in imgstore!\n", imgid, ev->event.image_request.crc32);
-- }
-- g_hash_table_remove(info->pending_images, GINT_TO_POINTER(ev->event.image_request.crc32));
-- }
--}
--
--static void ggp_typing_notification_handler(PurpleConnection *gc, uin_t uin, int length) {
-- gchar *from;
--
-- from = g_strdup_printf("%u", uin);
-- if (length)
-- serv_got_typing(gc, from, 0, PURPLE_TYPING);
-- else
-- serv_got_typing_stopped(gc, from);
-- g_free(from);
--}
--
--/**
-- * Handling of XML events.
-- *
-- * @param gc PurpleConnection.
-- * @param data Raw XML contents.
-- *
-- * @see http://toxygen.net/libgadu/protocol/#ch1.13
-- */
--static void ggp_xml_event_handler(PurpleConnection *gc, char *data)
--{
-- xmlnode *xml = NULL;
-- xmlnode *xmlnode_next_event;
--
-- xml = xmlnode_from_str(data, -1);
-- if (xml == NULL)
-- goto out;
--
-- xmlnode_next_event = xmlnode_get_child(xml, "event");
-- while (xmlnode_next_event != NULL)
-- {
-- xmlnode *xmlnode_current_event = xmlnode_next_event;
--
-- xmlnode *xmlnode_type;
-- char *event_type_raw;
-- int event_type = 0;
--
-- xmlnode *xmlnode_sender;
-- char *event_sender_raw;
-- uin_t event_sender = 0;
--
-- xmlnode_next_event = xmlnode_get_next_twin(xmlnode_next_event);
--
-- xmlnode_type = xmlnode_get_child(xmlnode_current_event, "type");
-- if (xmlnode_type == NULL)
-- continue;
-- event_type_raw = xmlnode_get_data(xmlnode_type);
-- if (event_type_raw != NULL)
-- event_type = atoi(event_type_raw);
-- g_free(event_type_raw);
--
-- xmlnode_sender = xmlnode_get_child(xmlnode_current_event, "sender");
-- if (xmlnode_sender != NULL)
-- {
-- event_sender_raw = xmlnode_get_data(xmlnode_sender);
-- if (event_sender_raw != NULL)
-- event_sender = ggp_str_to_uin(event_sender_raw);
-- g_free(event_sender_raw);
-- }
--
-- switch (event_type)
-- {
-- case 28: /* avatar update */
-- purple_debug_info("gg",
-- "ggp_xml_event_handler: avatar updated (uid: %u)\n",
-- event_sender);
-- ggp_update_buddy_avatar(gc, event_sender);
-- break;
-- default:
-- purple_debug_error("gg",
-- "ggp_xml_event_handler: unsupported event type=%d from=%u\n",
-- event_type, event_sender);
-- }
-- }
--
-- out:
-- if (xml)
-- xmlnode_free(xml);
--}
--
--static void ggp_callback_recv(gpointer _gc, gint fd, PurpleInputCondition cond)
--{
-- PurpleConnection *gc = _gc;
-- GGPInfo *info = gc->proto_data;
-- struct gg_event *ev;
-- int i;
--
-- if (!(ev = gg_watch_fd(info->session))) {
-- purple_debug_error("gg",
-- "ggp_callback_recv: gg_watch_fd failed -- CRITICAL!\n");
-- purple_connection_error_reason (gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Unable to read from socket"));
-- return;
-- }
--
-- switch (ev->type) {
-- case GG_EVENT_NONE:
-- /* Nothing happened. */
-- break;
-- case GG_EVENT_MSG:
-- ggp_recv_message_handler(gc, ev);
-- break;
-- case GG_EVENT_ACK:
-- /* Changing %u to %i fixes compiler warning */
-- purple_debug_info("gg",
-- "ggp_callback_recv: message sent to: %i, delivery status=%d, seq=%d\n",
-- ev->event.ack.recipient, ev->event.ack.status,
-- ev->event.ack.seq);
-- break;
-- case GG_EVENT_IMAGE_REPLY:
-- ggp_recv_image_handler(gc, ev);
-- break;
-- case GG_EVENT_IMAGE_REQUEST:
-- ggp_send_image_handler(gc, ev);
-- break;
-- case GG_EVENT_NOTIFY:
-- case GG_EVENT_NOTIFY_DESCR:
-- {
-- struct gg_notify_reply *n;
-- char *descr;
--
-- purple_debug_info("gg", "notify_pre: (%d) status: %d\n",
-- ev->event.notify->uin,
-- GG_S(ev->event.notify->status));
--
-- n = (ev->type == GG_EVENT_NOTIFY) ? ev->event.notify
-- : ev->event.notify_descr.notify;
--
-- for (; n->uin; n++) {
-- descr = (ev->type == GG_EVENT_NOTIFY) ? NULL
-- : ev->event.notify_descr.descr;
--
-- purple_debug_info("gg",
-- "notify: (%d) status: %d; descr: %s\n",
-- n->uin, GG_S(n->status), descr ? descr : "(null)");
--
-- ggp_generic_status_handler(gc,
-- n->uin, GG_S(n->status), descr);
-- }
-- }
-- break;
-- case GG_EVENT_NOTIFY60:
-- for (i = 0; ev->event.notify60[i].uin; i++) {
-- purple_debug_info("gg",
-- "notify60: (%d) status=%d; version=%d; descr=%s\n",
-- ev->event.notify60[i].uin,
-- GG_S(ev->event.notify60[i].status),
-- ev->event.notify60[i].version,
-- ev->event.notify60[i].descr ? ev->event.notify60[i].descr : "(null)");
--
-- ggp_generic_status_handler(gc, ev->event.notify60[i].uin,
-- GG_S(ev->event.notify60[i].status),
-- ev->event.notify60[i].descr);
-- }
-- break;
-- case GG_EVENT_STATUS:
-- purple_debug_info("gg", "status: (%d) status=%d; descr=%s\n",
-- ev->event.status.uin, GG_S(ev->event.status.status),
-- ev->event.status.descr ? ev->event.status.descr : "(null)");
--
-- ggp_generic_status_handler(gc, ev->event.status.uin,
-- GG_S(ev->event.status.status), ev->event.status.descr);
-- break;
-- case GG_EVENT_STATUS60:
-- purple_debug_info("gg",
-- "status60: (%d) status=%d; version=%d; descr=%s\n",
-- ev->event.status60.uin, GG_S(ev->event.status60.status),
-- ev->event.status60.version,
-- ev->event.status60.descr ? ev->event.status60.descr : "(null)");
--
-- ggp_generic_status_handler(gc, ev->event.status60.uin,
-- GG_S(ev->event.status60.status), ev->event.status60.descr);
-- break;
-- case GG_EVENT_USERLIST:
-- if (ev->event.userlist.type == GG_USERLIST_GET_REPLY) {
-- purple_debug_info("gg", "GG_USERLIST_GET_REPLY\n");
-- purple_notify_info(gc, NULL,
-- _("Buddy list downloaded"),
-- _("Your buddy list was downloaded from the server."));
-- if (ev->event.userlist.reply != NULL) {
-- ggp_buddylist_load(gc, ev->event.userlist.reply);
-- }
-- } else {
-- purple_debug_info("gg", "GG_USERLIST_PUT_REPLY\n");
-- purple_notify_info(gc, NULL,
-- _("Buddy list uploaded"),
-- _("Your buddy list was stored on the server."));
-- }
-- break;
-- case GG_EVENT_PUBDIR50_SEARCH_REPLY:
-- ggp_pubdir_reply_handler(gc, ev->event.pubdir50);
-- break;
-- case GG_EVENT_TYPING_NOTIFICATION:
-- ggp_typing_notification_handler(gc, ev->event.typing_notification.uin,
-- ev->event.typing_notification.length);
-- break;
-- case GG_EVENT_XML_EVENT:
-- purple_debug_info("gg", "GG_EVENT_XML_EVENT\n");
-- ggp_xml_event_handler(gc, ev->event.xml_event.data);
-- break;
-- default:
-- purple_debug_error("gg",
-- "unsupported event type=%d\n", ev->type);
-- break;
-- }
--
-- gg_free_event(ev);
--}
--
--static void ggp_async_login_handler(gpointer _gc, gint fd, PurpleInputCondition cond)
--{
-- PurpleConnection *gc = _gc;
-- GGPInfo *info;
-- struct gg_event *ev;
--
-- g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
--
-- info = gc->proto_data;
--
-- purple_debug_info("gg", "login_handler: session: check = %d; state = %d;\n",
-- info->session->check, info->session->state);
--
-- switch (info->session->state) {
-- case GG_STATE_RESOLVING:
-- purple_debug_info("gg", "GG_STATE_RESOLVING\n");
-- break;
-- case GG_STATE_RESOLVING_GG:
-- purple_debug_info("gg", "GG_STATE_RESOLVING_GG\n");
-- break;
-- case GG_STATE_CONNECTING_HUB:
-- purple_debug_info("gg", "GG_STATE_CONNECTING_HUB\n");
-- break;
-- case GG_STATE_READING_DATA:
-- purple_debug_info("gg", "GG_STATE_READING_DATA\n");
-- break;
-- case GG_STATE_CONNECTING_GG:
-- purple_debug_info("gg", "GG_STATE_CONNECTING_GG\n");
-- break;
-- case GG_STATE_READING_KEY:
-- purple_debug_info("gg", "GG_STATE_READING_KEY\n");
-- break;
-- case GG_STATE_READING_REPLY:
-- purple_debug_info("gg", "GG_STATE_READING_REPLY\n");
-- break;
-- case GG_STATE_TLS_NEGOTIATION:
-- purple_debug_info("gg", "GG_STATE_TLS_NEGOTIATION\n");
-- break;
-- default:
-- purple_debug_error("gg", "unknown state = %d\n",
-- info->session->state);
-- break;
-- }
--
-- if (!(ev = gg_watch_fd(info->session))) {
-- purple_debug_error("gg", "login_handler: gg_watch_fd failed!\n");
-- purple_connection_error_reason (gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Unable to read from socket"));
-- return;
-- }
-- purple_debug_info("gg", "login_handler: session->fd = %d\n", info->session->fd);
-- purple_debug_info("gg", "login_handler: session: check = %d; state = %d;\n",
-- info->session->check, info->session->state);
--
-- purple_input_remove(gc->inpa);
--
-- /** XXX I think that this shouldn't be done if ev->type is GG_EVENT_CONN_FAILED or GG_EVENT_CONN_SUCCESS -datallah */
-- if (info->session->fd >= 0)
-- gc->inpa = purple_input_add(info->session->fd,
-- (info->session->check == 1) ? PURPLE_INPUT_WRITE :
-- PURPLE_INPUT_READ,
-- ggp_async_login_handler, gc);
--
-- switch (ev->type) {
-- case GG_EVENT_NONE:
-- /* Nothing happened. */
-- purple_debug_info("gg", "GG_EVENT_NONE\n");
-- break;
-- case GG_EVENT_CONN_SUCCESS:
-- {
-- purple_debug_info("gg", "GG_EVENT_CONN_SUCCESS\n");
-- purple_input_remove(gc->inpa);
-- gc->inpa = purple_input_add(info->session->fd,
-- PURPLE_INPUT_READ,
-- ggp_callback_recv, gc);
--
-- ggp_buddylist_send(gc);
-- purple_connection_update_progress(gc, _("Connected"), 1, 2);
-- purple_connection_set_state(gc, PURPLE_CONNECTED);
-- }
-- break;
-- case GG_EVENT_CONN_FAILED:
-- purple_input_remove(gc->inpa);
-- gc->inpa = 0;
-- purple_connection_error_reason (gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Connection failed"));
-- break;
-- case GG_EVENT_MSG:
-- if (ev->event.msg.sender == 0)
-- /* system messages are mostly ads */
-- purple_debug_info("gg", "System message:\n%s\n",
-- ev->event.msg.message);
-- else
-- purple_debug_warning("gg", "GG_EVENT_MSG: message from user %u "
-- "unexpected while connecting:\n%s\n",
-- ev->event.msg.sender,
-- ev->event.msg.message);
-- break;
-- default:
-- purple_debug_error("gg", "strange event: %d\n", ev->type);
-- break;
-- }
--
-- gg_free_event(ev);
--}
--
--/* ---------------------------------------------------------------------- */
--/* ----- PurplePluginProtocolInfo ----------------------------------------- */
--/* ---------------------------------------------------------------------- */
--
--static const char *ggp_list_icon(PurpleAccount *account, PurpleBuddy *buddy)
--{
-- return "gadu-gadu";
--}
--
--static char *ggp_status_text(PurpleBuddy *b)
--{
-- PurpleStatus *status;
-- const char *msg;
-- char *text;
-- char *tmp;
--
-- status = purple_presence_get_active_status(
-- purple_buddy_get_presence(b));
-- msg = purple_status_get_attr_string(status, "message");
--
-- if (msg == NULL)
-- return NULL;
--
-- tmp = purple_markup_strip_html(msg);
-- text = g_markup_escape_text(tmp, -1);
-- g_free(tmp);
--
-- return text;
--}
--
--static void ggp_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
--{
-- PurpleStatus *status;
-- char *text, *tmp;
-- const char *msg, *name, *alias;
--
-- g_return_if_fail(b != NULL);
--
-- status = purple_presence_get_active_status(purple_buddy_get_presence(b));
-- msg = purple_status_get_attr_string(status, "message");
-- name = purple_status_get_name(status);
-- alias = purple_buddy_get_alias(b);
--
-- purple_notify_user_info_add_pair (user_info, _("Alias"), alias);
--
-- if (msg != NULL) {
-- text = g_markup_escape_text(msg, -1);
-- if (PURPLE_BUDDY_IS_ONLINE(b)) {
-- tmp = g_strdup_printf("%s: %s", name, text);
-- purple_notify_user_info_add_pair(user_info, _("Status"), tmp);
-- g_free(tmp);
-- } else {
-- purple_notify_user_info_add_pair(user_info, _("Message"), text);
-- }
-- g_free(text);
-- /* We don't want to duplicate 'Status: Offline'. */
-- } else if (PURPLE_BUDDY_IS_ONLINE(b)) {
-- purple_notify_user_info_add_pair(user_info, _("Status"), name);
-- }
--}
--
--static GList *ggp_status_types(PurpleAccount *account)
--{
-- PurpleStatusType *type;
-- GList *types = NULL;
--
-- type = purple_status_type_new_with_attrs(
-- PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE,
-- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- types = g_list_append(types, type);
--
-- /*
-- * Without this selecting Invisible as own status doesn't
-- * work. It's not used and not needed to show status of buddies.
-- */
-- type = purple_status_type_new_with_attrs(
-- PURPLE_STATUS_INVISIBLE, NULL, NULL, TRUE, TRUE, FALSE,
-- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- types = g_list_append(types, type);
--
-- type = purple_status_type_new_with_attrs(
-- PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE,
-- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- types = g_list_append(types, type);
--
-- /*
-- * New statuses for GG 8.0 like PoGGadaj ze mna (not yet because
-- * libpurple can't support Chatty status) and Nie przeszkadzac
-- */
-- type = purple_status_type_new_with_attrs(
-- PURPLE_STATUS_UNAVAILABLE, NULL, NULL, TRUE, TRUE, FALSE,
-- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- types = g_list_append(types, type);
--
-- /*
-- * This status is necessary to display guys who are blocking *us*.
-- */
-- type = purple_status_type_new_with_attrs(
-- PURPLE_STATUS_INVISIBLE, "blocked", _("Blocked"), TRUE, FALSE, FALSE,
-- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), NULL);
-- types = g_list_append(types, type);
--
-- type = purple_status_type_new_with_attrs(
-- PURPLE_STATUS_OFFLINE, NULL, NULL, TRUE, TRUE, FALSE,
-- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- types = g_list_append(types, type);
--
-- return types;
--}
--
--static GList *ggp_blist_node_menu(PurpleBlistNode *node)
--{
-- PurpleMenuAction *act;
-- GList *m = NULL;
-- PurpleAccount *account;
-- GGPInfo *info;
--
-- if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
-- return NULL;
--
-- account = purple_buddy_get_account((PurpleBuddy *) node);
-- info = purple_account_get_connection(account)->proto_data;
-- if (info->chats) {
-- act = purple_menu_action_new(_("Add to chat"),
-- PURPLE_CALLBACK(ggp_bmenu_add_to_chat),
-- NULL, NULL);
-- m = g_list_append(m, act);
-- }
--
-- return m;
--}
--
--static GList *ggp_chat_info(PurpleConnection *gc)
--{
-- GList *m = NULL;
-- struct proto_chat_entry *pce;
--
-- pce = g_new0(struct proto_chat_entry, 1);
-- pce->label = _("Chat _name:");
-- pce->identifier = "name";
-- pce->required = TRUE;
-- m = g_list_append(m, pce);
--
-- return m;
--}
--
--static void ggp_login(PurpleAccount *account)
--{
-- PurpleConnection *gc;
-- PurplePresence *presence;
-- PurpleStatus *status;
-- struct gg_login_params *glp;
-- GGPInfo *info;
-- const char *address;
-- const gchar *encryption_type;
--
-- if (ggp_setup_proxy(account) == -1)
-- return;
--
-- gc = purple_account_get_connection(account);
-- glp = g_new0(struct gg_login_params, 1);
-- info = g_new0(GGPInfo, 1);
--
-- /* Probably this should be moved to *_new() function. */
-- info->session = NULL;
-- info->chats = NULL;
-- info->chats_count = 0;
-- info->token = NULL;
-- info->searches = ggp_search_new();
-- info->pending_richtext_messages = NULL;
-- info->pending_images = g_hash_table_new(g_direct_hash, g_direct_equal);
-- info->status_broadcasting = purple_account_get_bool(account, "status_broadcasting", TRUE);
--
-- gc->proto_data = info;
--
-- glp->uin = ggp_get_uin(account);
-- glp->password = (char *)purple_account_get_password(account);
-- glp->image_size = 255;
--
-- presence = purple_account_get_presence(account);
-- status = purple_presence_get_active_status(presence);
--
-- glp->encoding = GG_ENCODING_UTF8;
-- glp->protocol_features = (GG_FEATURE_STATUS80|GG_FEATURE_DND_FFC
-- |GG_FEATURE_TYPING_NOTIFICATION);
--
-- glp->async = 1;
-- glp->status = ggp_to_gg_status(status, &glp->status_descr);
--
-- encryption_type = purple_account_get_string(account, "encryption", "none");
-- purple_debug_info("gg", "Requested encryption type: %s\n", encryption_type);
-- if (strcmp(encryption_type, "opportunistic_tls") == 0)
-- glp->tls = 1;
-- else
-- glp->tls = 0;
-- purple_debug_info("gg", "TLS enabled: %d\n", glp->tls);
--
-- if (!info->status_broadcasting)
-- glp->status = glp->status|GG_STATUS_FRIENDS_MASK;
--
-- address = purple_account_get_string(account, "gg_server", "");
-- if (address && *address) {
-- /* TODO: Make this non-blocking */
-- struct in_addr *addr = gg_gethostbyname(address);
--
-- purple_debug_info("gg", "Using gg server given by user (%s)\n", address);
--
-- if (addr == NULL) {
-- gchar *tmp = g_strdup_printf(_("Unable to resolve hostname '%s': %s"),
-- address, g_strerror(errno));
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, /* should this be a settings error? */
-- tmp);
-- g_free(tmp);
-- return;
-- }
--
-- glp->server_addr = inet_addr(inet_ntoa(*addr));
-- glp->server_port = 8074;
-- free(addr);
-- } else
-- purple_debug_info("gg", "Trying to retrieve address from gg appmsg service\n");
--
-- info->session = gg_login(glp);
-- purple_connection_update_progress(gc, _("Connecting"), 0, 2);
-- if (info->session == NULL) {
-- purple_connection_error_reason (gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Connection failed"));
-- g_free(glp);
-- return;
-- }
-- gc->inpa = purple_input_add(info->session->fd, PURPLE_INPUT_READ,
-- ggp_async_login_handler, gc);
--}
--
--static void ggp_close(PurpleConnection *gc)
--{
--
-- if (gc == NULL) {
-- purple_debug_info("gg", "gc == NULL\n");
-- return;
-- }
--
-- if (gc->proto_data) {
-- PurpleAccount *account = purple_connection_get_account(gc);
-- PurpleStatus *status;
-- GGPInfo *info = gc->proto_data;
--
-- status = purple_account_get_active_status(account);
--
-- if (info->session != NULL) {
-- ggp_set_status(account, status);
-- gg_logoff(info->session);
-- gg_free_session(info->session);
-- }
--
-- purple_account_set_bool(account, "status_broadcasting", info->status_broadcasting);
--
-- /* Immediately close any notifications on this handle since that process depends
-- * upon the contents of info->searches, which we are about to destroy.
-- */
-- purple_notify_close_with_handle(gc);
--
-- ggp_search_destroy(info->searches);
-- g_list_free(info->pending_richtext_messages);
-- g_hash_table_destroy(info->pending_images);
-- g_free(info);
-- gc->proto_data = NULL;
-- }
--
-- if (gc->inpa > 0)
-- purple_input_remove(gc->inpa);
--
-- purple_debug_info("gg", "Connection closed.\n");
--}
--
--static int ggp_send_im(PurpleConnection *gc, const char *who, const char *msg,
-- PurpleMessageFlags flags)
--{
-- GGPInfo *info = gc->proto_data;
-- char *tmp, *plain;
-- int ret = 1;
-- unsigned char format[1024];
-- unsigned int format_length = sizeof(struct gg_msg_richtext);
-- gint pos = 0;
-- GData *attribs;
-- const char *start, *end = NULL, *last;
--
-- if (msg == NULL || *msg == '\0') {
-- return 0;
-- }
--
-- last = msg;
--
-- /* Check if the message is richtext */
-- /* TODO: Check formatting, too */
-- if(purple_markup_find_tag("img", last, &start, &end, &attribs)) {
--
-- GString *string_buffer = g_string_new(NULL);
-- struct gg_msg_richtext fmt;
--
-- do {
-- PurpleStoredImage *image;
-- const char *id;
--
-- /* Add text before the image */
-- if(start - last) {
-- pos = pos + g_utf8_strlen(last, start - last);
-- g_string_append_len(string_buffer, last, start - last);
-- }
--
-- if((id = g_datalist_get_data(&attribs, "id")) && (image = purple_imgstore_find_by_id(atoi(id)))) {
-- struct gg_msg_richtext_format actformat;
-- struct gg_msg_richtext_image actimage;
-- gint image_size = purple_imgstore_get_size(image);
-- gconstpointer image_bin = purple_imgstore_get_data(image);
-- const char *image_filename = purple_imgstore_get_filename(image);
-- uint32_t crc32 = gg_crc32(0, image_bin, image_size);
--
-- g_hash_table_insert(info->pending_images, GINT_TO_POINTER(crc32), GINT_TO_POINTER(atoi(id)));
-- purple_imgstore_ref(image);
-- purple_debug_info("gg", "ggp_send_im_richtext: got crc: %u for imgid: %i\n", crc32, atoi(id));
--
-- actformat.font = GG_FONT_IMAGE;
-- actformat.position = pos;
--
-- actimage.unknown1 = 0x0109;
-- actimage.size = gg_fix32(image_size);
-- actimage.crc32 = gg_fix32(crc32);
--
-- if (actimage.size > 255000) {
-- purple_debug_warning("gg", "ggp_send_im_richtext: image over 255kb!\n");
-- } else {
-- purple_debug_info("gg", "ggp_send_im_richtext: adding images to richtext, size: %i, crc32: %u, name: %s\n", actimage.size, actimage.crc32, image_filename);
--
-- memcpy(format + format_length, &actformat, sizeof(actformat));
-- format_length += sizeof(actformat);
-- memcpy(format + format_length, &actimage, sizeof(actimage));
-- format_length += sizeof(actimage);
-- }
-- } else {
-- purple_debug_error("gg", "ggp_send_im_richtext: image not found in the image store!");
-- }
--
-- last = end + 1;
-- g_datalist_clear(&attribs);
--
-- } while(purple_markup_find_tag("img", last, &start, &end, &attribs));
--
-- /* Add text after the images */
-- if(last && *last) {
-- pos = pos + g_utf8_strlen(last, -1);
-- g_string_append(string_buffer, last);
-- }
--
-- fmt.flag = 2;
-- fmt.length = format_length - sizeof(fmt);
-- memcpy(format, &fmt, sizeof(fmt));
--
-- purple_debug_info("gg", "ggp_send_im: richtext msg = %s\n", string_buffer->str);
-- plain = purple_unescape_html(string_buffer->str);
-- g_string_free(string_buffer, TRUE);
-- } else {
-- purple_debug_info("gg", "ggp_send_im: msg = %s\n", msg);
-- plain = purple_unescape_html(msg);
-- }
--
-- /*
-- tmp = charset_convert(plain, "UTF-8", "CP1250");
-- */
-- tmp = g_strdup_printf("%s", plain);
--
-- if (tmp && (format_length - sizeof(struct gg_msg_richtext))) {
-- if(gg_send_message_richtext(info->session, GG_CLASS_CHAT, ggp_str_to_uin(who), (unsigned char *)tmp, format, format_length) < 0) {
-- ret = -1;
-- } else {
-- ret = 1;
-- }
-- } else if (NULL == tmp || *tmp == 0) {
-- ret = 0;
-- } else if (strlen(tmp) > GG_MSG_MAXSIZE) {
-- ret = -E2BIG;
-- } else if (gg_send_message(info->session, GG_CLASS_CHAT,
-- ggp_str_to_uin(who), (unsigned char *)tmp) < 0) {
-- ret = -1;
-- } else {
-- ret = 1;
-- }
--
-- g_free(plain);
-- g_free(tmp);
--
-- return ret;
--}
--
--static unsigned int ggp_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state)
--{
-- int dummy_length; // we don't send real length of typed message
--
-- if (state == PURPLE_TYPED) // not supported
-- return 1;
--
-- if (state == PURPLE_TYPING)
-- dummy_length = (int)g_random_int();
-- else // PURPLE_NOT_TYPING
-- dummy_length = 0;
--
-- gg_typing_notification(
-- ((GGPInfo*)gc->proto_data)->session,
-- ggp_str_to_uin(name),
-- dummy_length);
--
-- return 1; // wait 1 second before another notification
--}
--
--static void ggp_get_info(PurpleConnection *gc, const char *name)
--{
-- GGPInfo *info = gc->proto_data;
-- GGPSearchForm *form;
-- guint32 seq;
--
-- form = ggp_search_form_new(GGP_SEARCH_TYPE_INFO);
--
-- form->user_data = info;
-- form->uin = g_strdup(name);
--
-- seq = ggp_search_start(gc, form);
-- ggp_search_add(info->searches, seq, form);
-- purple_debug_info("gg", "ggp_get_info(): Added seq %u", seq);
--}
--
--static int ggp_to_gg_status(PurpleStatus *status, char **msg)
--{
-- const char *status_id = purple_status_get_id(status);
-- int new_status, new_status_descr;
-- const char *new_msg;
--
-- g_return_val_if_fail(msg != NULL, 0);
--
-- purple_debug_info("gg", "ggp_to_gg_status: Requested status = %s\n",
-- status_id);
--
-- if (strcmp(status_id, "available") == 0) {
-- new_status = GG_STATUS_AVAIL;
-- new_status_descr = GG_STATUS_AVAIL_DESCR;
-- } else if (strcmp(status_id, "away") == 0) {
-- new_status = GG_STATUS_BUSY;
-- new_status_descr = GG_STATUS_BUSY_DESCR;
-- } else if (strcmp(status_id, "unavailable") == 0) {
-- new_status = GG_STATUS_DND;
-- new_status_descr = GG_STATUS_DND_DESCR;
-- } else if (strcmp(status_id, "invisible") == 0) {
-- new_status = GG_STATUS_INVISIBLE;
-- new_status_descr = GG_STATUS_INVISIBLE_DESCR;
-- } else if (strcmp(status_id, "offline") == 0) {
-- new_status = GG_STATUS_NOT_AVAIL;
-- new_status_descr = GG_STATUS_NOT_AVAIL_DESCR;
-- } else {
-- new_status = GG_STATUS_AVAIL;
-- new_status_descr = GG_STATUS_AVAIL_DESCR;
-- purple_debug_info("gg",
-- "ggp_set_status: unknown status requested (status_id=%s)\n",
-- status_id);
-- }
--
-- new_msg = purple_status_get_attr_string(status, "message");
--
-- if(new_msg) {
-- /*
-- char *tmp = purple_markup_strip_html(new_msg);
-- *msg = charset_convert(tmp, "UTF-8", "CP1250");
-- g_free(tmp);
-- */
-- *msg = purple_markup_strip_html(new_msg);
--
-- return new_status_descr;
-- } else {
-- *msg = NULL;
-- return new_status;
-- }
--}
--
--static void ggp_set_status(PurpleAccount *account, PurpleStatus *status)
--{
-- PurpleConnection *gc;
-- GGPInfo *info;
-- int new_status;
-- char *new_msg = NULL;
--
-- if (!purple_status_is_active(status))
-- return;
--
-- gc = purple_account_get_connection(account);
-- info = gc->proto_data;
--
-- new_status = ggp_to_gg_status(status, &new_msg);
--
-- if (!info->status_broadcasting)
-- new_status = new_status|GG_STATUS_FRIENDS_MASK;
--
-- if (new_msg == NULL) {
-- gg_change_status(info->session, new_status);
-- } else {
-- gg_change_status_descr(info->session, new_status, new_msg);
-- g_free(new_msg);
-- }
--
-- ggp_status_fake_to_self(account);
--
--}
--
--static void ggp_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
--{
-- PurpleAccount *account;
-- GGPInfo *info = gc->proto_data;
-- const gchar *name = purple_buddy_get_name(buddy);
--
-- gg_add_notify(info->session, ggp_str_to_uin(name));
--
-- account = purple_connection_get_account(gc);
-- if (strcmp(purple_account_get_username(account), name) == 0) {
-- ggp_status_fake_to_self(account);
-- }
--}
--
--static void ggp_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
-- PurpleGroup *group)
--{
-- GGPInfo *info = gc->proto_data;
--
-- gg_remove_notify(info->session, ggp_str_to_uin(purple_buddy_get_name(buddy)));
--}
--
--static void ggp_join_chat(PurpleConnection *gc, GHashTable *data)
--{
-- GGPInfo *info = gc->proto_data;
-- GGPChat *chat;
-- char *chat_name;
-- GList *l;
-- PurpleConversation *conv;
-- PurpleAccount *account = purple_connection_get_account(gc);
--
-- chat_name = g_hash_table_lookup(data, "name");
--
-- if (chat_name == NULL)
-- return;
--
-- purple_debug_info("gg", "joined %s chat\n", chat_name);
--
-- for (l = info->chats; l != NULL; l = l->next) {
-- chat = l->data;
--
-- if (chat != NULL && g_utf8_collate(chat->name, chat_name) == 0) {
-- purple_notify_error(gc, _("Chat error"),
-- _("This chat name is already in use"), NULL);
-- return;
-- }
-- }
--
-- ggp_confer_add_new(gc, chat_name);
-- conv = serv_got_joined_chat(gc, info->chats_count, chat_name);
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(conv),
-- purple_account_get_username(account), NULL,
-- PURPLE_CBFLAGS_NONE, TRUE);
--}
--
--static char *ggp_get_chat_name(GHashTable *data) {
-- return g_strdup(g_hash_table_lookup(data, "name"));
--}
--
--static int ggp_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)
--{
-- PurpleConversation *conv;
-- GGPInfo *info = gc->proto_data;
-- GGPChat *chat = NULL;
-- GList *l;
-- /* char *msg, *plain; */
-- gchar *msg;
-- uin_t *uins;
-- int count = 0;
--
-- if ((conv = purple_find_chat(gc, id)) == NULL)
-- return -EINVAL;
--
-- for (l = info->chats; l != NULL; l = l->next) {
-- chat = l->data;
--
-- if (g_utf8_collate(chat->name, conv->name) == 0) {
-- break;
-- }
--
-- chat = NULL;
-- }
--
-- if (chat == NULL) {
-- purple_debug_error("gg",
-- "ggp_chat_send: Hm... that's strange. No such chat?\n");
-- return -EINVAL;
-- }
--
-- uins = g_new0(uin_t, g_list_length(chat->participants));
--
-- for (l = chat->participants; l != NULL; l = l->next) {
-- uin_t uin = GPOINTER_TO_INT(l->data);
--
-- uins[count++] = uin;
-- }
--
-- /*
-- plain = purple_unescape_html(message);
-- msg = charset_convert(plain, "UTF-8", "CP1250");
-- g_free(plain);
-- */
-- msg = purple_unescape_html(message);
-- gg_send_message_confer(info->session, GG_CLASS_CHAT, count, uins,
-- (unsigned char *)msg);
-- g_free(msg);
-- g_free(uins);
--
-- serv_got_chat_in(gc, id,
-- purple_account_get_username(purple_connection_get_account(gc)),
-- flags, message, time(NULL));
--
-- return 0;
--}
--
--static void ggp_keepalive(PurpleConnection *gc)
--{
-- GGPInfo *info = gc->proto_data;
--
-- /* purple_debug_info("gg", "Keeping connection alive....\n"); */
--
-- if (gg_ping(info->session) < 0) {
-- purple_debug_info("gg", "Not connected to the server "
-- "or gg_session is not correct\n");
-- purple_connection_error_reason (gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Not connected to the server"));
-- }
--}
--
--static void ggp_register_user(PurpleAccount *account)
--{
-- PurpleConnection *gc = purple_account_get_connection(account);
--
-- ggp_token_request(gc, ggp_register_user_dialog);
--}
--
--static GList *ggp_actions(PurplePlugin *plugin, gpointer context)
--{
-- GList *m = NULL;
-- PurplePluginAction *act;
--
-- act = purple_plugin_action_new(_("Find buddies..."),
-- ggp_find_buddies);
-- m = g_list_append(m, act);
--
-- m = g_list_append(m, NULL);
--
-- act = purple_plugin_action_new(_("Change password..."),
-- ggp_change_passwd);
-- m = g_list_append(m, act);
--
-- m = g_list_append(m, NULL);
--
-- act = purple_plugin_action_new(_("Upload buddylist to Server"),
-- ggp_action_buddylist_put);
-- m = g_list_append(m, act);
--
-- act = purple_plugin_action_new(_("Download buddylist from Server"),
-- ggp_action_buddylist_get);
-- m = g_list_append(m, act);
--
-- act = purple_plugin_action_new(_("Delete buddylist from Server"),
-- ggp_action_buddylist_delete);
-- m = g_list_append(m, act);
--
-- act = purple_plugin_action_new(_("Save buddylist to file..."),
-- ggp_action_buddylist_save);
-- m = g_list_append(m, act);
--
-- act = purple_plugin_action_new(_("Load buddylist from file..."),
-- ggp_action_buddylist_load);
-- m = g_list_append(m, act);
--
-- act = purple_plugin_action_new(_("Change status broadcasting"),
-- ggp_action_change_status_broadcasting);
-- m = g_list_append(m, act);
--
-- return m;
--}
--
--static gboolean ggp_offline_message(const PurpleBuddy *buddy)
--{
-- return TRUE;
--}
--
--static PurplePluginProtocolInfo prpl_info =
--{
-- OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_IM_IMAGE,
-- NULL, /* user_splits */
-- NULL, /* protocol_options */
-- {"png", 32, 32, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
-- ggp_list_icon, /* list_icon */
-- NULL, /* list_emblem */
-- ggp_status_text, /* status_text */
-- ggp_tooltip_text, /* tooltip_text */
-- ggp_status_types, /* status_types */
-- ggp_blist_node_menu, /* blist_node_menu */
-- ggp_chat_info, /* chat_info */
-- NULL, /* chat_info_defaults */
-- ggp_login, /* login */
-- ggp_close, /* close */
-- ggp_send_im, /* send_im */
-- NULL, /* set_info */
-- ggp_send_typing, /* send_typing */
-- ggp_get_info, /* get_info */
-- ggp_set_status, /* set_away */
-- NULL, /* set_idle */
-- NULL, /* change_passwd */
-- ggp_add_buddy, /* add_buddy */
-- NULL, /* add_buddies */
-- ggp_remove_buddy, /* remove_buddy */
-- NULL, /* remove_buddies */
-- NULL, /* add_permit */
-- ggp_add_deny, /* add_deny */
-- NULL, /* rem_permit */
-- ggp_rem_deny, /* rem_deny */
-- NULL, /* set_permit_deny */
-- ggp_join_chat, /* join_chat */
-- NULL, /* reject_chat */
-- ggp_get_chat_name, /* get_chat_name */
-- NULL, /* chat_invite */
-- NULL, /* chat_leave */
-- NULL, /* chat_whisper */
-- ggp_chat_send, /* chat_send */
-- ggp_keepalive, /* keepalive */
-- ggp_register_user, /* 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 */
-- NULL, /* set_buddy_icon */
-- NULL, /* remove_group */
-- NULL, /* get_cb_real_name */
-- NULL, /* set_chat_topic */
-- NULL, /* find_blist_chat */
-- NULL, /* roomlist_get_list */
-- NULL, /* roomlist_cancel */
-- NULL, /* roomlist_expand_category */
-- NULL, /* can_receive_file */
-- NULL, /* send_file */
-- NULL, /* new_xfer */
-- ggp_offline_message, /* offline_message */
-- NULL, /* 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, /* can_do_media */
-- 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, /* magic */
-- PURPLE_MAJOR_VERSION, /* major_version */
-- PURPLE_MINOR_VERSION, /* minor_version */
-- PURPLE_PLUGIN_PROTOCOL, /* plugin type */
-- NULL, /* ui_requirement */
-- 0, /* flags */
-- NULL, /* dependencies */
-- PURPLE_PRIORITY_DEFAULT, /* priority */
--
-- "prpl-gg", /* id */
-- "Gadu-Gadu", /* name */
-- DISPLAY_VERSION, /* version */
--
-- N_("Gadu-Gadu Protocol Plugin"), /* summary */
-- N_("Polish popular IM"), /* description */
-- "boler@sourceforge.net", /* author */
-- PURPLE_WEBSITE, /* homepage */
--
-- NULL, /* load */
-- NULL, /* unload */
-- NULL, /* destroy */
--
-- NULL, /* ui_info */
-- &prpl_info, /* extra_info */
-- NULL, /* prefs_info */
-- ggp_actions, /* actions */
--
-- /* padding */
-- NULL,
-- NULL,
-- NULL,
-- NULL
--};
--
--static void purple_gg_debug_handler(int level, const char * format, va_list args) {
-- PurpleDebugLevel purple_level;
-- char *msg = g_strdup_vprintf(format, args);
--
-- /* This is pretty pointless since the GG_DEBUG levels don't correspond to
-- * the purple ones */
-- switch (level) {
-- case GG_DEBUG_FUNCTION:
-- purple_level = PURPLE_DEBUG_INFO;
-- break;
-- case GG_DEBUG_MISC:
-- case GG_DEBUG_NET:
-- case GG_DEBUG_DUMP:
-- case GG_DEBUG_TRAFFIC:
-- default:
-- purple_level = PURPLE_DEBUG_MISC;
-- break;
-- }
--
-- purple_debug(purple_level, "gg", "%s", msg);
-- g_free(msg);
--}
--
--static void init_plugin(PurplePlugin *plugin)
--{
-- PurpleAccountOption *option;
-- GList *encryption_options = NULL;
--
-- option = purple_account_option_string_new(_("Nickname"),
-- "nick", _("Gadu-Gadu User"));
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-- option);
--
-- option = purple_account_option_string_new(_("GG server"),
-- "gg_server", "");
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-- option);
--
--#define ADD_VALUE(list, desc, v) { \
-- PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1); \
-- kvp->key = g_strdup((desc)); \
-- kvp->value = g_strdup((v)); \
-- list = g_list_append(list, kvp); \
--}
--
-- ADD_VALUE(encryption_options, _("Don't use encryption"), "none");
-- ADD_VALUE(encryption_options, _("Use encryption if available"),
-- "opportunistic_tls");
--#if 0
-- /* TODO */
-- ADD_VALUE(encryption_options, _("Require encryption"), "require_tls");
--#endif
--
-- option = purple_account_option_list_new(_("Connection security"),
-- "encryption", encryption_options);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-- option);
--
-- my_protocol = plugin;
--
-- gg_debug_handler = purple_gg_debug_handler;
--}
--
--PURPLE_INIT_PLUGIN(gg, init_plugin, info);
--
--/* vim: set ts=8 sts=0 sw=8 noet: */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/gg.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/gg.h
---- pidgin-2.10.7/libpurple/protocols/gg/gg.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/gg.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,72 +0,0 @@
--/**
-- * @file gg.h
-- *
-- * purple
-- *
-- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--
--#ifndef _PURPLE_GG_H
--#define _PURPLE_GG_H
--
--#include <libgadu.h>
--#include "internal.h"
--#include "search.h"
--#include "connection.h"
--
--
--#define PUBDIR_RESULTS_MAX 20
--
--
--typedef struct
--{
-- char *name;
-- GList *participants;
--
--} GGPChat;
--
--typedef void (*GGPTokenCallback)(PurpleConnection *);
--
--typedef struct
--{
-- char *id;
-- char *data;
-- unsigned int size;
--
-- struct gg_http *req;
-- guint inpa;
--
-- GGPTokenCallback cb;
--
--} GGPToken;
--
--typedef struct {
--
-- struct gg_session *session;
-- GGPToken *token;
-- GList *chats;
-- GGPSearches *searches;
-- int chats_count;
-- GList *pending_richtext_messages;
-- GHashTable *pending_images;
-- gboolean status_broadcasting; //When TRUE status is visible to all, when FALSE status is visible only to friends.
--} GGPInfo;
--
--#endif /* _PURPLE_GG_H */
--
--/* vim: set ts=8 sts=0 sw=8 noet: */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/gg-utils.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/gg-utils.c
---- pidgin-2.10.7/libpurple/protocols/gg/gg-utils.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/gg-utils.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,147 +0,0 @@
--/**
-- * @file gg-utils.c
-- *
-- * purple
-- *
-- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--
--#include "gg-utils.h"
--
--
--/* uin_t ggp_str_to_uin(const char *str) {{{ */
--uin_t ggp_str_to_uin(const char *str)
--{
-- char *tmp;
-- long num;
--
-- if (!str)
-- return 0;
--
-- errno = 0;
-- num = strtol(str, &tmp, 10);
--
-- if (*str == '\0' || *tmp != '\0')
-- return 0;
--
-- if ((errno == ERANGE || (num == LONG_MAX || num == LONG_MIN))
--#if (LONG_MAX > UINT_MAX)
-- || num > (long)UINT_MAX
--#endif
-- || num < 0)
-- return 0;
--
-- return (uin_t) num;
--}
--/* }}} */
--
--/* unsigned int ggp_array_size(char **array) {{{ */
--unsigned int ggp_array_size(char **array)
--{
-- unsigned int i;
--
-- for (i = 0; array[i] != NULL && i < UINT_MAX; i++)
-- {}
--
-- return i;
--}
--/* }}} */
--
--/* char *charset_convert(const gchar *locstr, const char *encsrc, const char *encdst) {{{ */
--char *charset_convert(const gchar *locstr, const char *encsrc, const char *encdst)
--{
-- gchar *msg;
-- GError *err = NULL;
--
-- if (locstr == NULL)
-- return NULL;
--
-- msg = g_convert_with_fallback(locstr, strlen(locstr), encdst, encsrc,
-- "?", NULL, NULL, &err);
-- if (err != NULL) {
-- purple_debug_error("gg", "Error converting from %s to %s: %s\n",
-- encsrc, encdst, err->message);
-- g_error_free(err);
-- }
--
-- /* Just in case? */
-- if (msg == NULL)
-- msg = g_strdup(locstr);
--
-- return msg;
--}
--/* }}} */
--
--/* ggp_get_uin(PurpleAccount *account) {{{ */
--uin_t ggp_get_uin(PurpleAccount *account)
--{
-- return ggp_str_to_uin(purple_account_get_username(account));
--}
--/* }}} */
--
--/* char *ggp_buddy_get_name(PurpleConnection *gc, const uin_t uin) {{{ */
--char *ggp_buddy_get_name(PurpleConnection *gc, const uin_t uin)
--{
-- PurpleBuddy *buddy;
-- gchar *str_uin;
--
-- str_uin = g_strdup_printf("%lu", (unsigned long int)uin);
--
-- buddy = purple_find_buddy(purple_connection_get_account(gc), str_uin);
-- if (buddy != NULL) {
-- g_free(str_uin);
-- return g_strdup(purple_buddy_get_alias(buddy));
-- } else {
-- return str_uin;
-- }
--}
--/* }}} */
--
--void ggp_status_fake_to_self(PurpleAccount *account)
--{
-- PurplePresence *presence;
-- PurpleStatus *status;
-- const char *status_id;
-- const char *msg;
--
-- if (! purple_find_buddy(account, purple_account_get_username(account)))
-- return;
--
-- presence = purple_account_get_presence(account);
-- status = purple_presence_get_active_status(presence);
-- msg = purple_status_get_attr_string(status, "message");
-- if (msg && !*msg)
-- msg = NULL;
--
-- status_id = purple_status_get_id(status);
-- if (strcmp(status_id, "invisible") == 0) {
-- status_id = "offline";
-- }
--
-- if (msg) {
-- if (strlen(msg) > GG_STATUS_DESCR_MAXSIZE) {
-- msg = purple_markup_slice(msg, 0, GG_STATUS_DESCR_MAXSIZE);
-- }
-- }
-- purple_prpl_got_user_status(account, purple_account_get_username(account),
-- status_id,
-- msg ? "message" : NULL, msg, NULL);
--}
--
--
--/* vim: set ts=8 sts=0 sw=8 noet: */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/gg-utils.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/gg-utils.h
---- pidgin-2.10.7/libpurple/protocols/gg/gg-utils.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/gg-utils.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,106 +0,0 @@
--/**
-- * @file gg-utils.h
-- *
-- * purple
-- *
-- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _PURPLE_GG_UTILS_H
--#define _PURPLE_GG_UTILS_H
--
--#include "internal.h"
--
--#include "plugin.h"
--#include "version.h"
--#include "notify.h"
--#include "status.h"
--#include "blist.h"
--#include "accountopt.h"
--#include "debug.h"
--#include "util.h"
--#include "request.h"
--
--#include "gg.h"
--
--
--/**
-- * Convert a base 10 string to a UIN.
-- *
-- * @param str The string to convert
-- *
-- * @return UIN or 0 if an error occurred.
-- */
--uin_t
--ggp_str_to_uin(const char *str);
--
--/**
-- * Calculate size of a NULL-terminated array.
-- *
-- * @param array The array.
-- *
-- * @return Size of the array.
-- */
--unsigned int
--ggp_array_size(char **array);
--
--/**
-- * Convert enconding of a given string.
-- *
-- * @param locstr Input string.
-- * @param encsrc Current encoding of the string.
-- * @param encdst Target encoding of the string.
-- *
-- * @return Converted string (it must be g_free()ed when not used. Or NULL if
-- * locstr is NULL.
-- */
--char *
--charset_convert(const gchar *locstr, const char *encsrc, const char *encdst);
--
--/**
-- * Get UIN of a given account.
-- *
-- * @param account Current account.
-- *
-- * @return UIN of an account.
-- */
--uin_t
--ggp_get_uin(PurpleAccount *account);
--
--/**
-- * Returns the best name of a buddy from the buddylist.
-- *
-- * @param gc PurpleConnection instance.
-- * @param uin UIN of the buddy.
-- *
-- * @return Name of the buddy, or UIN converted to string.
-- */
--char *
--ggp_buddy_get_name(PurpleConnection *gc, const uin_t uin);
--
--/**
-- * Manages the display of account's status in the buddylist.
-- *
-- * @param account Current account.
-- */
--void
--ggp_status_fake_to_self(PurpleAccount *account);
--
--
--#endif /* _PURPLE_GG_UTILS_H */
--
--/* vim: set ts=8 sts=0 sw=8 noet: */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/common.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/common.c
---- pidgin-2.10.7/libpurple/protocols/gg/lib/common.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/common.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,685 +0,0 @@
--/* $Id: common.c 1101 2011-05-05 21:17:28Z wojtekka $ */
--
--/*
-- * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl>
-- * Robert J. Woźny <speedy@ziew.org>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--/**
-- * \file common.c
-- *
-- * \brief Funkcje wykorzystywane przez różne moduły biblioteki
-- */
--#ifndef _WIN32
--# include <sys/types.h>
--# include <sys/ioctl.h>
--# include <sys/socket.h>
--# include <netinet/in.h>
--# include <arpa/inet.h>
--# ifdef sun
--# include <sys/filio.h>
--# endif
--#endif
--
--#include <errno.h>
--#include <fcntl.h>
--#ifndef _WIN32
--# include <netdb.h>
--#endif
--#include <stdarg.h>
--#include <stdio.h>
--#include <stdlib.h>
--#include <string.h>
--#include <unistd.h>
--
--#include "libgadu.h"
--
--/**
-- * \internal Odpowiednik funkcji \c vsprintf alokujÄ…cy miejsce na wynik.
-- *
-- * Funkcja korzysta z funkcji \c vsnprintf, sprawdzając czy dostępna funkcja
-- * systemowa jest zgodna ze standardem C99 czy wcześniejszymi.
-- *
-- * \param format Format wiadomości (zgodny z \c printf)
-- * \param ap Lista argumentów (zgodna z \c printf)
-- *
-- * \return Zaalokowany bufor lub NULL, jeśli zabrakło pamięci.
-- *
-- * \ingroup helper
-- */
--char *gg_vsaprintf(const char *format, va_list ap)
--{
-- int size = 0;
-- char *buf = NULL;
--
--#ifdef GG_CONFIG_HAVE_VA_COPY
-- va_list aq;
--
-- va_copy(aq, ap);
--#else
--# ifdef GG_CONFIG_HAVE___VA_COPY
-- va_list aq;
--
-- __va_copy(aq, ap);
--# endif
--#endif
--
--#ifndef GG_CONFIG_HAVE_C99_VSNPRINTF
-- {
-- int res;
-- char *tmp;
--
-- size = 128;
-- do {
-- size *= 2;
-- if (!(tmp = realloc(buf, size + 1))) {
-- free(buf);
-- return NULL;
-- }
-- buf = tmp;
-- res = vsnprintf(buf, size, format, ap);
-- } while (res == size - 1 || res == -1);
-- }
--#else
-- {
-- char tmp[2];
--
-- /* libce Solarisa przy buforze NULL zawsze zwracają -1, więc
-- * musimy podać coś istniejącego jako cel printf()owania. */
-- size = vsnprintf(tmp, sizeof(tmp), format, ap);
-- if (!(buf = malloc(size + 1)))
-- return NULL;
-- }
--#endif
--
--#ifdef GG_CONFIG_HAVE_VA_COPY
-- vsnprintf(buf, size + 1, format, aq);
-- va_end(aq);
--#else
--# ifdef GG_CONFIG_HAVE___VA_COPY
-- vsnprintf(buf, size + 1, format, aq);
-- va_end(aq);
--# else
-- vsnprintf(buf, size + 1, format, ap);
--# endif
--#endif
--
-- return buf;
--}
--
--/**
-- * \internal Odpowiednik funkcji \c sprintf alokujÄ…cy miejsce na wynik.
-- *
-- * Funkcja korzysta z funkcji \c vsnprintf, sprawdzając czy dostępna funkcja
-- * systemowa jest zgodna ze standardem C99 czy wcześniejszymi.
-- *
-- * \param format Format wiadomości (zgodny z \c printf)
-- *
-- * \return Zaalokowany bufor lub NULL, jeśli zabrakło pamięci.
-- *
-- * \ingroup helper
-- */
--char *gg_saprintf(const char *format, ...)
--{
-- va_list ap;
-- char *res;
--
-- va_start(ap, format);
-- res = gg_vsaprintf(format, ap);
-- va_end(ap);
--
-- return res;
--}
--
--/**
-- * \internal Pobiera liniÄ™ tekstu z bufora.
-- *
-- * Funkcja niszczy bufor źródłowy bezpowrotnie, dzieląc go na kolejne ciągi
-- * znaków i obcina znaki końca linii.
-- *
-- * \param ptr Wskaźnik do zmiennej, która przechowuje aktualne położenie
-- * w analizowanym buforze
-- *
-- * \return Wskaźnik do kolejnej linii tekstu lub NULL, jeśli to już koniec
-- * bufora.
-- */
--char *gg_get_line(char **ptr)
--{
-- char *foo, *res;
--
-- if (!ptr || !*ptr || !strcmp(*ptr, ""))
-- return NULL;
--
-- res = *ptr;
--
-- if (!(foo = strchr(*ptr, '\n')))
-- *ptr += strlen(*ptr);
-- else {
-- size_t len;
-- *ptr = foo + 1;
-- *foo = 0;
--
-- len = strlen(res);
--
-- if (len > 1 && res[len - 1] == '\r')
-- res[len - 1] = 0;
-- }
--
-- return res;
--}
--
--/**
-- * \internal Czyta liniÄ™ tekstu z gniazda.
-- *
-- * Funkcja czyta tekst znak po znaku, więc nie jest efektywna, ale dzięki
-- * brakowi buforowania, nie koliduje z innymi funkcjami odczytu.
-- *
-- * \param sock Deskryptor gniazda
-- * \param buf Wskaźnik do bufora
-- * \param length Długość bufora
-- *
-- * \return Zwraca \c buf jeśli się powiodło, lub \c NULL w przypadku błędu.
-- */
--char *gg_read_line(int sock, char *buf, int length)
--{
-- int ret;
--
-- if (!buf || length < 0)
-- return NULL;
--
-- for (; length > 1; buf++, length--) {
-- do {
-- if ((ret = read(sock, buf, 1)) == -1 && errno != EINTR && errno != EAGAIN) {
-- gg_debug(GG_DEBUG_MISC, "// gg_read_line() error on read (errno=%d, %s)\n", errno, strerror(errno));
-- *buf = 0;
-- return NULL;
-- } else if (ret == 0) {
-- gg_debug(GG_DEBUG_MISC, "// gg_read_line() eof reached\n");
-- *buf = 0;
-- return NULL;
-- }
-- } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
--
-- if (*buf == '\n') {
-- buf++;
-- break;
-- }
-- }
--
-- *buf = 0;
-- return buf;
--}
--
--/**
-- * \internal Nawiązuje połączenie TCP.
-- *
-- * \param addr Wskaźnik na strukturę \c in_addr z adresem serwera
-- * \param port Port serwera
-- * \param async Flaga asynchronicznego połączenia
-- *
-- * \return Deskryptor gniazda lub -1 w przypadku błędu
-- *
-- * \ingroup helper
-- */
--int gg_connect(void *addr, int port, int async)
--{
-- int sock, one = 1, errno2;
-- struct sockaddr_in sin;
-- struct in_addr *a = addr;
-- struct sockaddr_in myaddr;
--
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_connect(%s, %d, %d);\n", inet_ntoa(*a), port, async);
--
-- if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_connect() socket() failed (errno=%d, %s)\n", errno, strerror(errno));
-- return -1;
-- }
--
-- memset(&myaddr, 0, sizeof(myaddr));
-- myaddr.sin_family = AF_INET;
--
-- myaddr.sin_addr.s_addr = gg_local_ip;
--
-- if (bind(sock, (struct sockaddr *) &myaddr, sizeof(myaddr)) == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_connect() bind() failed (errno=%d, %s)\n", errno, strerror(errno));
-- errno2 = errno;
-- close(sock);
-- errno = errno2;
-- return -1;
-- }
--
-- if (async) {
--#ifdef FIONBIO
-- if (ioctl(sock, FIONBIO, &one) == -1) {
--#else
-- if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) {
--#endif
-- gg_debug(GG_DEBUG_MISC, "// gg_connect() ioctl() failed (errno=%d, %s)\n", errno, strerror(errno));
-- errno2 = errno;
-- close(sock);
-- errno = errno2;
-- return -1;
-- }
-- }
--
-- memset(&sin, 0, sizeof(sin));
-- sin.sin_port = htons(port);
-- sin.sin_family = AF_INET;
-- sin.sin_addr.s_addr = a->s_addr;
--
-- if (connect(sock, (struct sockaddr*) &sin, sizeof(sin)) == -1) {
-- if (errno && (!async || errno != EINPROGRESS)) {
-- gg_debug(GG_DEBUG_MISC, "// gg_connect() connect() failed (errno=%d, %s)\n", errno, strerror(errno));
-- errno2 = errno;
-- close(sock);
-- errno = errno2;
-- return -1;
-- }
-- gg_debug(GG_DEBUG_MISC, "// gg_connect() connect() in progress\n");
-- }
--
-- return sock;
--}
--
--/**
-- * \internal Usuwa znaki końca linii.
-- *
-- * Funkcja działa bezpośrednio na buforze.
-- *
-- * \param line Bufor z tekstem
-- *
-- * \ingroup helper
-- */
--void gg_chomp(char *line)
--{
-- int len;
--
-- if (!line)
-- return;
--
-- len = strlen(line);
--
-- if (len > 0 && line[len - 1] == '\n')
-- line[--len] = 0;
-- if (len > 0 && line[len - 1] == '\r')
-- line[--len] = 0;
--}
--
--/**
-- * \internal Koduje ciąg znaków do postacji adresu HTTP.
-- *
-- * Zamienia znaki niedrukowalne, spoza ASCII i majÄ…ce specjalne znaczenie
-- * dla protokołu HTTP na encje postaci \c %XX, gdzie \c XX jest szesnastkową
-- * wartością znaku.
-- *
-- * \param str Ciąg znaków do zakodowania
-- *
-- * \return Zaalokowany bufor lub \c NULL w przypadku błędu.
-- *
-- * \ingroup helper
-- */
--char *gg_urlencode(const char *str)
--{
-- char *q, *buf;
-- const char hex[] = "0123456789abcdef";
-- const char *p;
-- unsigned int size = 0;
--
-- if (!str)
-- str = "";
--
-- for (p = str; *p; p++, size++) {
-- if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == ' ') || (*p == '@') || (*p == '.') || (*p == '-'))
-- size += 2;
-- }
--
-- if (!(buf = malloc(size + 1)))
-- return NULL;
--
-- for (p = str, q = buf; *p; p++, q++) {
-- if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || (*p == '@') || (*p == '.') || (*p == '-'))
-- *q = *p;
-- else {
-- if (*p == ' ')
-- *q = '+';
-- else {
-- *q++ = '%';
-- *q++ = hex[*p >> 4 & 15];
-- *q = hex[*p & 15];
-- }
-- }
-- }
--
-- *q = 0;
--
-- return buf;
--}
--
--/**
-- * \internal Wyznacza skrót dla usług HTTP.
-- *
-- * Funkcja jest wykorzystywana do wyznaczania skrótu adresu e-mail, hasła
-- * i innych wartości przekazywanych jako parametry usług HTTP.
-- *
-- * W parametrze \c format należy umieścić znaki określające postać kolejnych
-- * parametrów: \c 's' jeśli parametr jest ciągiem znaków, \c 'u' jeśli jest
-- * liczbÄ….
-- *
-- * \param format Format kolejnych parametrów (niezgodny z \c printf)
-- *
-- * \return Wartość skrótu
-- */
--int gg_http_hash(const char *format, ...)
--{
-- unsigned int a, c, i, j;
-- va_list ap;
-- int b = -1;
--
-- va_start(ap, format);
--
-- for (j = 0; j < strlen(format); j++) {
-- char *arg, buf[16];
--
-- if (format[j] == 'u') {
-- snprintf(buf, sizeof(buf), "%d", va_arg(ap, uin_t));
-- arg = buf;
-- } else {
-- if (!(arg = va_arg(ap, char*)))
-- arg = "";
-- }
--
-- i = 0;
-- while ((c = (unsigned char) arg[i++]) != 0) {
-- a = (c ^ b) + (c << 8);
-- b = (a >> 24) | (a << 8);
-- }
-- }
--
-- va_end(ap);
--
-- return (b < 0 ? -b : b);
--}
--
--/**
-- * \internal Zestaw znaków kodowania base64.
-- */
--static char gg_base64_charset[] =
-- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
--
--/**
-- * \internal Koduje ciąg znaków do base64.
-- *
-- * Wynik funkcji należy zwolnić za pomocą \c free.
-- *
-- * \param buf Bufor z danami do zakodowania
-- *
-- * \return Zaalokowany bufor z zakodowanymi danymi
-- *
-- * \ingroup helper
-- */
--char *gg_base64_encode(const char *buf)
--{
-- char *out, *res;
-- unsigned int i = 0, j = 0, k = 0, len = strlen(buf);
--
-- res = out = malloc((len / 3 + 1) * 4 + 2);
--
-- if (!res)
-- return NULL;
--
-- while (j <= len) {
-- switch (i % 4) {
-- case 0:
-- k = (buf[j] & 252) >> 2;
-- break;
-- case 1:
-- if (j < len)
-- k = ((buf[j] & 3) << 4) | ((buf[j + 1] & 240) >> 4);
-- else
-- k = (buf[j] & 3) << 4;
--
-- j++;
-- break;
-- case 2:
-- if (j < len)
-- k = ((buf[j] & 15) << 2) | ((buf[j + 1] & 192) >> 6);
-- else
-- k = (buf[j] & 15) << 2;
--
-- j++;
-- break;
-- case 3:
-- k = buf[j++] & 63;
-- break;
-- }
-- *out++ = gg_base64_charset[k];
-- i++;
-- }
--
-- if (i % 4)
-- for (j = 0; j < 4 - (i % 4); j++, out++)
-- *out = '=';
--
-- *out = 0;
--
-- return res;
--}
--
--/**
-- * \internal Dekoduje ciąg znaków zapisany w base64.
-- *
-- * Wynik funkcji należy zwolnić za pomocą \c free.
-- *
-- * \param buf Bufor źródłowy z danymi do zdekodowania
-- *
-- * \return Zaalokowany bufor ze zdekodowanymi danymi
-- *
-- * \ingroup helper
-- */
--char *gg_base64_decode(const char *buf)
--{
-- char *res, *save, *foo, val;
-- const char *end;
-- unsigned int index = 0;
--
-- if (!buf)
-- return NULL;
--
-- save = res = calloc(1, (strlen(buf) / 4 + 1) * 3 + 2);
--
-- if (!save)
-- return NULL;
--
-- end = buf + strlen(buf);
--
-- while (*buf && buf < end) {
-- if (*buf == '\r' || *buf == '\n') {
-- buf++;
-- continue;
-- }
-- if (!(foo = strchr(gg_base64_charset, *buf)))
-- foo = gg_base64_charset;
-- val = (int)(foo - gg_base64_charset);
-- buf++;
-- switch (index) {
-- case 0:
-- *res |= val << 2;
-- break;
-- case 1:
-- *res++ |= val >> 4;
-- *res |= val << 4;
-- break;
-- case 2:
-- *res++ |= val >> 2;
-- *res |= val << 6;
-- break;
-- case 3:
-- *res++ |= val;
-- break;
-- }
-- index++;
-- index %= 4;
-- }
-- *res = 0;
--
-- return save;
--}
--
--/**
-- * \internal Tworzy nagłówek autoryzacji serwera pośredniczącego.
-- *
-- * Dane pobiera ze zmiennych globalnych \c gg_proxy_username i
-- * \c gg_proxy_password.
-- *
-- * \return Zaalokowany bufor z tekstem lub NULL, jeśli serwer pośredniczący
-- * nie jest używany lub nie wymaga autoryzacji.
-- */
--char *gg_proxy_auth(void)
--{
-- char *tmp, *enc, *out;
-- unsigned int tmp_size;
--
-- if (!gg_proxy_enabled || !gg_proxy_username || !gg_proxy_password)
-- return NULL;
--
-- if (!(tmp = malloc((tmp_size = strlen(gg_proxy_username) + strlen(gg_proxy_password) + 2))))
-- return NULL;
--
-- snprintf(tmp, tmp_size, "%s:%s", gg_proxy_username, gg_proxy_password);
--
-- if (!(enc = gg_base64_encode(tmp))) {
-- free(tmp);
-- return NULL;
-- }
--
-- free(tmp);
--
-- if (!(out = malloc(strlen(enc) + 40))) {
-- free(enc);
-- return NULL;
-- }
--
-- snprintf(out, strlen(enc) + 40, "Proxy-Authorization: Basic %s\r\n", enc);
--
-- free(enc);
--
-- return out;
--}
--
--/**
-- * \internal Tablica pomocnicza do wyznaczania sumy kontrolnej.
-- */
--static const uint32_t gg_crc32_table[256] =
--{
-- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
-- 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
-- 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
-- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
-- 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
-- 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
-- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
-- 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
-- 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
-- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
-- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
-- 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
-- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
-- 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
-- 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
-- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
-- 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
-- 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
-- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
-- 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
-- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
-- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
-- 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
-- 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
-- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
-- 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
-- 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
-- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
-- 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
-- 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
-- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
-- 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
-- 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
-- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
-- 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
-- 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
-- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
-- 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
-- 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
-- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
-- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
-- 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
-- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
-- 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
-- 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
-- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
-- 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
-- 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
-- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
-- 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
-- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
-- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
-- 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
-- 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
-- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
-- 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
-- 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
-- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
-- 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
-- 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
-- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
-- 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
-- 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
-- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
--};
--
--/**
-- * Wyznacza sumÄ™ kontrolnÄ… CRC32.
-- *
-- * \param crc Suma kontrola poprzedniego bloku danych lub 0 jeśli liczona
-- * jest suma kontrolna pierwszego bloku
-- * \param buf Bufor danych
-- * \param len Długość bufora danych
-- *
-- * \return Suma kontrolna.
-- */
--uint32_t gg_crc32(uint32_t crc, const unsigned char *buf, int len)
--{
-- if (buf == NULL || len < 0)
-- return crc;
--
-- crc ^= 0xffffffffL;
--
-- while (len--)
-- crc = (crc >> 8) ^ gg_crc32_table[(crc ^ *buf++) & 0xff];
--
-- return crc ^ 0xffffffffL;
--}
--
--/*
-- * Local variables:
-- * c-indentation-style: k&r
-- * c-basic-offset: 8
-- * indent-tabs-mode: notnil
-- * End:
-- *
-- * vim: shiftwidth=8:
-- */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/compat.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/compat.h
---- pidgin-2.10.7/libpurple/protocols/gg/lib/compat.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/compat.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,35 +0,0 @@
--/* $Id: compat.h 506 2008-01-14 22:15:05Z wojtekka $ */
--
--/*
-- * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl>
-- * Robert J. Woźny <speedy@ziew.org>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--/**
-- * \file compat.h
-- *
-- * \brief Makra zapewniające kompatybilność API na różnych systemach
-- */
--
--#ifndef __COMPAT_H
--#define __COMPAT_H
--
--#ifdef sun
--# define INADDR_NONE ((in_addr_t) 0xffffffff)
--#endif
--
--#endif
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/COPYING pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/COPYING
---- pidgin-2.10.7/libpurple/protocols/gg/lib/COPYING 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/COPYING 1969-12-31 21:00:00.000000000 -0300
-@@ -1,504 +0,0 @@
-- GNU LESSER GENERAL PUBLIC LICENSE
-- Version 2.1, February 1999
--
-- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-- Everyone is permitted to copy and distribute verbatim copies
-- of this license document, but changing it is not allowed.
--
--[This is the first released version of the Lesser GPL. It also counts
-- as the successor of the GNU Library Public License, version 2, hence
-- the version number 2.1.]
--
-- Preamble
--
-- The licenses for most software are designed to take away your
--freedom to share and change it. By contrast, the GNU General Public
--Licenses are intended to guarantee your freedom to share and change
--free software--to make sure the software is free for all its users.
--
-- This license, the Lesser General Public License, applies to some
--specially designated software packages--typically libraries--of the
--Free Software Foundation and other authors who decide to use it. You
--can use it too, but we suggest you first think carefully about whether
--this license or the ordinary General Public License is the better
--strategy to use in any particular case, based on the explanations below.
--
-- When we speak of free software, we are referring to freedom of use,
--not price. Our General Public Licenses are designed to make sure that
--you have the freedom to distribute copies of free software (and charge
--for this service if you wish); that you receive source code or can get
--it if you want it; that you can change the software and use pieces of
--it in new free programs; and that you are informed that you can do
--these things.
--
-- To protect your rights, we need to make restrictions that forbid
--distributors to deny you these rights or to ask you to surrender these
--rights. These restrictions translate to certain responsibilities for
--you if you distribute copies of the library or if you modify it.
--
-- For example, if you distribute copies of the library, whether gratis
--or for a fee, you must give the recipients all the rights that we gave
--you. You must make sure that they, too, receive or can get the source
--code. If you link other code with the library, you must provide
--complete object files to the recipients, so that they can relink them
--with the library after making changes to the library and recompiling
--it. And you must show them these terms so they know their rights.
--
-- We protect your rights with a two-step method: (1) we copyright the
--library, and (2) we offer you this license, which gives you legal
--permission to copy, distribute and/or modify the library.
--
-- To protect each distributor, we want to make it very clear that
--there is no warranty for the free library. Also, if the library is
--modified by someone else and passed on, the recipients should know
--that what they have is not the original version, so that the original
--author's reputation will not be affected by problems that might be
--introduced by others.
--
-- Finally, software patents pose a constant threat to the existence of
--any free program. We wish to make sure that a company cannot
--effectively restrict the users of a free program by obtaining a
--restrictive license from a patent holder. Therefore, we insist that
--any patent license obtained for a version of the library must be
--consistent with the full freedom of use specified in this license.
--
-- Most GNU software, including some libraries, is covered by the
--ordinary GNU General Public License. This license, the GNU Lesser
--General Public License, applies to certain designated libraries, and
--is quite different from the ordinary General Public License. We use
--this license for certain libraries in order to permit linking those
--libraries into non-free programs.
--
-- When a program is linked with a library, whether statically or using
--a shared library, the combination of the two is legally speaking a
--combined work, a derivative of the original library. The ordinary
--General Public License therefore permits such linking only if the
--entire combination fits its criteria of freedom. The Lesser General
--Public License permits more lax criteria for linking other code with
--the library.
--
-- We call this license the "Lesser" General Public License because it
--does Less to protect the user's freedom than the ordinary General
--Public License. It also provides other free software developers Less
--of an advantage over competing non-free programs. These disadvantages
--are the reason we use the ordinary General Public License for many
--libraries. However, the Lesser license provides advantages in certain
--special circumstances.
--
-- For example, on rare occasions, there may be a special need to
--encourage the widest possible use of a certain library, so that it becomes
--a de-facto standard. To achieve this, non-free programs must be
--allowed to use the library. A more frequent case is that a free
--library does the same job as widely used non-free libraries. In this
--case, there is little to gain by limiting the free library to free
--software only, so we use the Lesser General Public License.
--
-- In other cases, permission to use a particular library in non-free
--programs enables a greater number of people to use a large body of
--free software. For example, permission to use the GNU C Library in
--non-free programs enables many more people to use the whole GNU
--operating system, as well as its variant, the GNU/Linux operating
--system.
--
-- Although the Lesser General Public License is Less protective of the
--users' freedom, it does ensure that the user of a program that is
--linked with the Library has the freedom and the wherewithal to run
--that program using a modified version of the Library.
--
-- The precise terms and conditions for copying, distribution and
--modification follow. Pay close attention to the difference between a
--"work based on the library" and a "work that uses the library". The
--former contains code derived from the library, whereas the latter must
--be combined with the library in order to run.
--
-- GNU LESSER GENERAL PUBLIC LICENSE
-- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
--
-- 0. This License Agreement applies to any software library or other
--program which contains a notice placed by the copyright holder or
--other authorized party saying it may be distributed under the terms of
--this Lesser General Public License (also called "this License").
--Each licensee is addressed as "you".
--
-- A "library" means a collection of software functions and/or data
--prepared so as to be conveniently linked with application programs
--(which use some of those functions and data) to form executables.
--
-- The "Library", below, refers to any such software library or work
--which has been distributed under these terms. A "work based on the
--Library" means either the Library or any derivative work under
--copyright law: that is to say, a work containing the Library or a
--portion of it, either verbatim or with modifications and/or translated
--straightforwardly into another language. (Hereinafter, translation is
--included without limitation in the term "modification".)
--
-- "Source code" for a work means the preferred form of the work for
--making modifications to it. For a library, complete source code means
--all the source code for all modules it contains, plus any associated
--interface definition files, plus the scripts used to control compilation
--and installation of the library.
--
-- Activities other than copying, distribution and modification are not
--covered by this License; they are outside its scope. The act of
--running a program using the Library is not restricted, and output from
--such a program is covered only if its contents constitute a work based
--on the Library (independent of the use of the Library in a tool for
--writing it). Whether that is true depends on what the Library does
--and what the program that uses the Library does.
--
-- 1. You may copy and distribute verbatim copies of the Library's
--complete source code as you receive it, in any medium, provided that
--you conspicuously and appropriately publish on each copy an
--appropriate copyright notice and disclaimer of warranty; keep intact
--all the notices that refer to this License and to the absence of any
--warranty; and distribute a copy of this License along with the
--Library.
--
-- You may charge a fee for the physical act of transferring a copy,
--and you may at your option offer warranty protection in exchange for a
--fee.
--
-- 2. You may modify your copy or copies of the Library or any portion
--of it, thus forming a work based on the Library, and copy and
--distribute such modifications or work under the terms of Section 1
--above, provided that you also meet all of these conditions:
--
-- a) The modified work must itself be a software library.
--
-- b) You must cause the files modified to carry prominent notices
-- stating that you changed the files and the date of any change.
--
-- c) You must cause the whole of the work to be licensed at no
-- charge to all third parties under the terms of this License.
--
-- d) If a facility in the modified Library refers to a function or a
-- table of data to be supplied by an application program that uses
-- the facility, other than as an argument passed when the facility
-- is invoked, then you must make a good faith effort to ensure that,
-- in the event an application does not supply such function or
-- table, the facility still operates, and performs whatever part of
-- its purpose remains meaningful.
--
-- (For example, a function in a library to compute square roots has
-- a purpose that is entirely well-defined independent of the
-- application. Therefore, Subsection 2d requires that any
-- application-supplied function or table used by this function must
-- be optional: if the application does not supply it, the square
-- root function must still compute square roots.)
--
--These requirements apply to the modified work as a whole. If
--identifiable sections of that work are not derived from the Library,
--and can be reasonably considered independent and separate works in
--themselves, then this License, and its terms, do not apply to those
--sections when you distribute them as separate works. But when you
--distribute the same sections as part of a whole which is a work based
--on the Library, the distribution of the whole must be on the terms of
--this License, whose permissions for other licensees extend to the
--entire whole, and thus to each and every part regardless of who wrote
--it.
--
--Thus, it is not the intent of this section to claim rights or contest
--your rights to work written entirely by you; rather, the intent is to
--exercise the right to control the distribution of derivative or
--collective works based on the Library.
--
--In addition, mere aggregation of another work not based on the Library
--with the Library (or with a work based on the Library) on a volume of
--a storage or distribution medium does not bring the other work under
--the scope of this License.
--
-- 3. You may opt to apply the terms of the ordinary GNU General Public
--License instead of this License to a given copy of the Library. To do
--this, you must alter all the notices that refer to this License, so
--that they refer to the ordinary GNU General Public License, version 2,
--instead of to this License. (If a newer version than version 2 of the
--ordinary GNU General Public License has appeared, then you can specify
--that version instead if you wish.) Do not make any other change in
--these notices.
--
-- Once this change is made in a given copy, it is irreversible for
--that copy, so the ordinary GNU General Public License applies to all
--subsequent copies and derivative works made from that copy.
--
-- This option is useful when you wish to copy part of the code of
--the Library into a program that is not a library.
--
-- 4. You may copy and distribute the Library (or a portion or
--derivative of it, under Section 2) in object code or executable form
--under the terms of Sections 1 and 2 above provided that you accompany
--it with the complete corresponding machine-readable source code, which
--must be distributed under the terms of Sections 1 and 2 above on a
--medium customarily used for software interchange.
--
-- If distribution of object code is made by offering access to copy
--from a designated place, then offering equivalent access to copy the
--source code from the same place satisfies the requirement to
--distribute the source code, even though third parties are not
--compelled to copy the source along with the object code.
--
-- 5. A program that contains no derivative of any portion of the
--Library, but is designed to work with the Library by being compiled or
--linked with it, is called a "work that uses the Library". Such a
--work, in isolation, is not a derivative work of the Library, and
--therefore falls outside the scope of this License.
--
-- However, linking a "work that uses the Library" with the Library
--creates an executable that is a derivative of the Library (because it
--contains portions of the Library), rather than a "work that uses the
--library". The executable is therefore covered by this License.
--Section 6 states terms for distribution of such executables.
--
-- When a "work that uses the Library" uses material from a header file
--that is part of the Library, the object code for the work may be a
--derivative work of the Library even though the source code is not.
--Whether this is true is especially significant if the work can be
--linked without the Library, or if the work is itself a library. The
--threshold for this to be true is not precisely defined by law.
--
-- If such an object file uses only numerical parameters, data
--structure layouts and accessors, and small macros and small inline
--functions (ten lines or less in length), then the use of the object
--file is unrestricted, regardless of whether it is legally a derivative
--work. (Executables containing this object code plus portions of the
--Library will still fall under Section 6.)
--
-- Otherwise, if the work is a derivative of the Library, you may
--distribute the object code for the work under the terms of Section 6.
--Any executables containing that work also fall under Section 6,
--whether or not they are linked directly with the Library itself.
--
-- 6. As an exception to the Sections above, you may also combine or
--link a "work that uses the Library" with the Library to produce a
--work containing portions of the Library, and distribute that work
--under terms of your choice, provided that the terms permit
--modification of the work for the customer's own use and reverse
--engineering for debugging such modifications.
--
-- You must give prominent notice with each copy of the work that the
--Library is used in it and that the Library and its use are covered by
--this License. You must supply a copy of this License. If the work
--during execution displays copyright notices, you must include the
--copyright notice for the Library among them, as well as a reference
--directing the user to the copy of this License. Also, you must do one
--of these things:
--
-- a) Accompany the work with the complete corresponding
-- machine-readable source code for the Library including whatever
-- changes were used in the work (which must be distributed under
-- Sections 1 and 2 above); and, if the work is an executable linked
-- with the Library, with the complete machine-readable "work that
-- uses the Library", as object code and/or source code, so that the
-- user can modify the Library and then relink to produce a modified
-- executable containing the modified Library. (It is understood
-- that the user who changes the contents of definitions files in the
-- Library will not necessarily be able to recompile the application
-- to use the modified definitions.)
--
-- b) Use a suitable shared library mechanism for linking with the
-- Library. A suitable mechanism is one that (1) uses at run time a
-- copy of the library already present on the user's computer system,
-- rather than copying library functions into the executable, and (2)
-- will operate properly with a modified version of the library, if
-- the user installs one, as long as the modified version is
-- interface-compatible with the version that the work was made with.
--
-- c) Accompany the work with a written offer, valid for at
-- least three years, to give the same user the materials
-- specified in Subsection 6a, above, for a charge no more
-- than the cost of performing this distribution.
--
-- d) If distribution of the work is made by offering access to copy
-- from a designated place, offer equivalent access to copy the above
-- specified materials from the same place.
--
-- e) Verify that the user has already received a copy of these
-- materials or that you have already sent this user a copy.
--
-- For an executable, the required form of the "work that uses the
--Library" must include any data and utility programs needed for
--reproducing the executable from it. However, as a special exception,
--the materials to be distributed need not include anything that is
--normally distributed (in either source or binary form) with the major
--components (compiler, kernel, and so on) of the operating system on
--which the executable runs, unless that component itself accompanies
--the executable.
--
-- It may happen that this requirement contradicts the license
--restrictions of other proprietary libraries that do not normally
--accompany the operating system. Such a contradiction means you cannot
--use both them and the Library together in an executable that you
--distribute.
--
-- 7. You may place library facilities that are a work based on the
--Library side-by-side in a single library together with other library
--facilities not covered by this License, and distribute such a combined
--library, provided that the separate distribution of the work based on
--the Library and of the other library facilities is otherwise
--permitted, and provided that you do these two things:
--
-- a) Accompany the combined library with a copy of the same work
-- based on the Library, uncombined with any other library
-- facilities. This must be distributed under the terms of the
-- Sections above.
--
-- b) Give prominent notice with the combined library of the fact
-- that part of it is a work based on the Library, and explaining
-- where to find the accompanying uncombined form of the same work.
--
-- 8. You may not copy, modify, sublicense, link with, or distribute
--the Library except as expressly provided under this License. Any
--attempt otherwise to copy, modify, sublicense, link with, or
--distribute the Library is void, and will automatically terminate your
--rights under this License. However, parties who have received copies,
--or rights, from you under this License will not have their licenses
--terminated so long as such parties remain in full compliance.
--
-- 9. You are not required to accept this License, since you have not
--signed it. However, nothing else grants you permission to modify or
--distribute the Library or its derivative works. These actions are
--prohibited by law if you do not accept this License. Therefore, by
--modifying or distributing the Library (or any work based on the
--Library), you indicate your acceptance of this License to do so, and
--all its terms and conditions for copying, distributing or modifying
--the Library or works based on it.
--
-- 10. Each time you redistribute the Library (or any work based on the
--Library), the recipient automatically receives a license from the
--original licensor to copy, distribute, link with or modify the Library
--subject to these terms and conditions. You may not impose any further
--restrictions on the recipients' exercise of the rights granted herein.
--You are not responsible for enforcing compliance by third parties with
--this License.
--
-- 11. If, as a consequence of a court judgment or allegation of patent
--infringement or for any other reason (not limited to patent issues),
--conditions are imposed on you (whether by court order, agreement or
--otherwise) that contradict the conditions of this License, they do not
--excuse you from the conditions of this License. If you cannot
--distribute so as to satisfy simultaneously your obligations under this
--License and any other pertinent obligations, then as a consequence you
--may not distribute the Library at all. For example, if a patent
--license would not permit royalty-free redistribution of the Library by
--all those who receive copies directly or indirectly through you, then
--the only way you could satisfy both it and this License would be to
--refrain entirely from distribution of the Library.
--
--If any portion of this section is held invalid or unenforceable under any
--particular circumstance, the balance of the section is intended to apply,
--and the section as a whole is intended to apply in other circumstances.
--
--It is not the purpose of this section to induce you to infringe any
--patents or other property right claims or to contest validity of any
--such claims; this section has the sole purpose of protecting the
--integrity of the free software distribution system which is
--implemented by public license practices. Many people have made
--generous contributions to the wide range of software distributed
--through that system in reliance on consistent application of that
--system; it is up to the author/donor to decide if he or she is willing
--to distribute software through any other system and a licensee cannot
--impose that choice.
--
--This section is intended to make thoroughly clear what is believed to
--be a consequence of the rest of this License.
--
-- 12. If the distribution and/or use of the Library is restricted in
--certain countries either by patents or by copyrighted interfaces, the
--original copyright holder who places the Library under this License may add
--an explicit geographical distribution limitation excluding those countries,
--so that distribution is permitted only in or among countries not thus
--excluded. In such case, this License incorporates the limitation as if
--written in the body of this License.
--
-- 13. The Free Software Foundation may publish revised and/or new
--versions of the Lesser General Public License from time to time.
--Such new versions will be similar in spirit to the present version,
--but may differ in detail to address new problems or concerns.
--
--Each version is given a distinguishing version number. If the Library
--specifies a version number of this License which applies to it and
--"any later version", you have the option of following the terms and
--conditions either of that version or of any later version published by
--the Free Software Foundation. If the Library does not specify a
--license version number, you may choose any version ever published by
--the Free Software Foundation.
--
-- 14. If you wish to incorporate parts of the Library into other free
--programs whose distribution conditions are incompatible with these,
--write to the author to ask for permission. For software which is
--copyrighted by the Free Software Foundation, write to the Free
--Software Foundation; we sometimes make exceptions for this. Our
--decision will be guided by the two goals of preserving the free status
--of all derivatives of our free software and of promoting the sharing
--and reuse of software generally.
--
-- NO WARRANTY
--
-- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
--WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
--EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
--OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
--KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
--IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
--PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
--LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
--THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
--
-- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
--WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
--AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
--FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
--CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
--LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
--RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
--FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
--SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
--DAMAGES.
--
-- END OF TERMS AND CONDITIONS
--
-- How to Apply These Terms to Your New Libraries
--
-- If you develop a new library, and you want it to be of the greatest
--possible use to the public, we recommend making it free software that
--everyone can redistribute and change. You can do so by permitting
--redistribution under these terms (or, alternatively, under the terms of the
--ordinary General Public License).
--
-- To apply these terms, attach the following notices to the library. It is
--safest to attach them to the start of each source file to most effectively
--convey the exclusion of warranty; and each file should have at least the
--"copyright" line and a pointer to where the full notice is found.
--
-- <one line to give the library's name and a brief idea of what it does.>
-- Copyright (C) <year> <name of author>
--
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 2.1 of the License, or (at your option) any later version.
--
-- This library 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
-- Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public
-- License along with this library; if not, write to the Free Software
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--
--Also add information on how to contact you by electronic and paper mail.
--
--You should also get your employer (if you work as a programmer) or your
--school, if any, to sign a "copyright disclaimer" for the library, if
--necessary. Here is a sample; alter the names:
--
-- Yoyodyne, Inc., hereby disclaims all copyright interest in the
-- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
--
-- <signature of Ty Coon>, 1 April 1990
-- Ty Coon, President of Vice
--
--That's all there is to it!
--
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/dcc7.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/dcc7.c
---- pidgin-2.10.7/libpurple/protocols/gg/lib/dcc7.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/dcc7.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1541 +0,0 @@
--/* $Id: dcc7.c 1087 2011-04-14 20:53:25Z wojtekka $ */
--
--/*
-- * (C) Copyright 2001-2010 Wojtek Kaniewski <wojtekka@irc.pl>
-- * Tomasz Chiliński <chilek@chilan.com>
-- * Adam Wysocki <gophi@ekg.chmurka.net>
-- * Bartłomiej Zimoń <uzi18@o2.pl>
-- *
-- * Thanks to Jakub Zawadzki <darkjames@darkjames.ath.cx>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110,
-- * USA.
-- */
--
--/**
-- * \file dcc7.c
-- *
-- * \brief Obsługa połączeń bezpośrednich od wersji Gadu-Gadu 7.x
-- */
--
--#include <sys/types.h>
--#include <sys/stat.h>
--#ifndef _WIN32
--# include <sys/ioctl.h>
--# include <sys/socket.h>
--# include <netinet/in.h>
--# include <arpa/inet.h>
--# ifdef sun
--# include <sys/filio.h>
--# endif
--#endif
--#include <time.h>
--
--#include <ctype.h>
--#include <errno.h>
--#include <fcntl.h>
--#include <stdarg.h>
--#include <string.h>
--#include <stdio.h>
--#include <stdlib.h>
--#include <unistd.h>
--
--#include "compat.h"
--#include "libgadu.h"
--#include "protocol.h"
--#include "resolver.h"
--#include "libgadu-internal.h"
--#include "libgadu-debug.h"
--
--#define gg_debug_dcc(dcc, level, fmt...) \
-- gg_debug_session(((dcc) != NULL) ? (dcc)->sess : NULL, level, fmt)
--
--#define gg_debug_dump_dcc(dcc, level, buf, len) \
-- gg_debug_dump(((dcc) != NULL) ? (dcc)->sess : NULL, level, buf, len)
--
--/**
-- * \internal Dodaje połączenie bezpośrednie do sesji.
-- *
-- * \param sess Struktura sesji
-- * \param dcc Struktura połączenia
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--static int gg_dcc7_session_add(struct gg_session *sess, struct gg_dcc7 *dcc)
--{
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_session_add(%p, %p)\n", sess, dcc);
--
-- if (!sess || !dcc || dcc->next) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_session_add() invalid parameters\n");
-- errno = EINVAL;
-- return -1;
-- }
--
-- dcc->next = sess->dcc7_list;
-- sess->dcc7_list = dcc;
--
-- return 0;
--}
--
--/**
-- * \internal Usuwa połączenie bezpośrednie z sesji.
-- *
-- * \param sess Struktura sesji
-- * \param dcc Struktura połączenia
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--static int gg_dcc7_session_remove(struct gg_session *sess, struct gg_dcc7 *dcc)
--{
-- struct gg_dcc7 *tmp;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_session_remove(%p, %p)\n", sess, dcc);
--
-- if (sess == NULL || dcc == NULL) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_session_remove() invalid parameters\n");
-- errno = EINVAL;
-- return -1;
-- }
--
-- if (sess->dcc7_list == dcc) {
-- sess->dcc7_list = dcc->next;
-- dcc->next = NULL;
-- return 0;
-- }
--
-- for (tmp = sess->dcc7_list; tmp != NULL; tmp = tmp->next) {
-- if (tmp->next == dcc) {
-- tmp->next = dcc->next;
-- dcc->next = NULL;
-- return 0;
-- }
-- }
--
-- errno = ENOENT;
-- return -1;
--}
--
--/**
-- * \internal Zwraca strukturę połączenia o danym identyfikatorze.
-- *
-- * \param sess Struktura sesji
-- * \param id Identyfikator połączenia
-- * \param uin Numer nadawcy lub odbiorcy
-- *
-- * \return Struktura połączenia lub \c NULL jeśli nie znaleziono
-- */
--static struct gg_dcc7 *gg_dcc7_session_find(struct gg_session *sess, gg_dcc7_id_t id, uin_t uin)
--{
-- struct gg_dcc7 *tmp;
-- int empty;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_session_find(%p, ..., %d)\n", sess, (int) uin);
--
-- empty = !memcmp(&id, "\0\0\0\0\0\0\0\0", 8);
--
-- for (tmp = sess->dcc7_list; tmp; tmp = tmp->next) {
-- if (empty) {
-- if (tmp->peer_uin == uin /*&& tmp->state != GG_STATE_WAITING_FOR_ACCEPT*/)
-- return tmp;
-- } else {
-- if (!memcmp(&tmp->cid, &id, sizeof(id)))
-- return tmp;
-- }
-- }
--
-- return NULL;
--}
--
--/**
-- * \internal Rozpoczyna proces pobierania adresu
-- *
-- * \param dcc Struktura połączenia
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--static int gg_dcc7_get_relay_addr(struct gg_dcc7 *dcc)
--{
-- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_get_relay_addr(%p)\n", dcc);
--
-- if (dcc == NULL || dcc->sess == NULL) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_get_relay_addr() invalid parameters\n");
-- errno = EINVAL;
-- return -1;
-- }
--
-- if (dcc->sess->resolver_start(&dcc->fd, &dcc->resolver, GG_RELAY_HOST) == -1) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_get_relay_addr() resolving failed (errno=%d, %s)\n", errno, strerror(errno));
-- return -1;
-- }
--
-- dcc->state = GG_STATE_RESOLVING_RELAY;
-- dcc->check = GG_CHECK_READ;
-- dcc->timeout = GG_DEFAULT_TIMEOUT;
--
-- return 0;
--}
--
--/**
-- * \internal Nawiązuje połączenie bezpośrednie
-- *
-- * \param dcc Struktura połączenia
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--static int gg_dcc7_connect(struct gg_dcc7 *dcc)
--{
-- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_connect(%p)\n", dcc);
--
-- if (dcc == NULL) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_connect() invalid parameters\n");
-- errno = EINVAL;
-- return -1;
-- }
--
-- if ((dcc->fd = gg_connect(&dcc->remote_addr, dcc->remote_port, 1)) == -1) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_connect() connection failed\n");
-- return -1;
-- }
--
-- dcc->state = GG_STATE_CONNECTING;
-- dcc->check = GG_CHECK_WRITE;
-- dcc->timeout = GG_DCC7_TIMEOUT_CONNECT;
-- dcc->soft_timeout = 1;
--
-- return 0;
--}
--
--/**
-- * \internal Tworzy gniazdo nasłuchujące dla połączenia bezpośredniego
-- *
-- * \param dcc Struktura połączenia
-- * \param addr Preferowany adres (jeśli równy 0, nasłuchujemy na wszystkich interfejsach)
-- * \param port Preferowany port (jeśli równy 0, nasłuchujemy na losowym)
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--static int gg_dcc7_listen(struct gg_dcc7 *dcc, uint32_t addr, uint16_t port)
--{
-- struct sockaddr_in sin;
-- socklen_t sin_len = sizeof(sin);
-- int errsv;
-- int fd;
--
-- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_listen(%p, %d)\n", dcc, port);
--
-- if (!dcc) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() invalid parameters\n");
-- errno = EINVAL;
-- return -1;
-- }
--
-- if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() can't create socket (%s)\n", strerror(errno));
-- return -1;
-- }
--
-- memset(&sin, 0, sizeof(sin));
-- sin.sin_family = AF_INET;
-- sin.sin_addr.s_addr = addr;
-- sin.sin_port = htons(port);
--
-- if (bind(fd, (struct sockaddr*) &sin, sizeof(sin)) == -1) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() unable to bind to %s:%d\n", inet_ntoa(sin.sin_addr), port);
-- goto fail;
-- }
--
-- if (port == 0 && getsockname(fd, (struct sockaddr*) &sin, &sin_len) == -1) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() unable to bind to port %d\n", port);
-- goto fail;
-- }
--
-- if (listen(fd, 1)) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() unable to listen (%s)\n", strerror(errno));
-- goto fail;
-- }
--
-- dcc->fd = fd;
-- dcc->local_addr = sin.sin_addr.s_addr;
-- dcc->local_port = ntohs(sin.sin_port);
--
-- dcc->state = GG_STATE_LISTENING;
-- dcc->check = GG_CHECK_READ;
-- dcc->timeout = GG_DCC7_TIMEOUT_FILE_ACK;
--
-- return 0;
--
--fail:
-- errsv = errno;
-- close(fd);
-- errno = errsv;
-- return -1;
--}
--
--/**
-- * \internal Tworzy gniazdo nasłuchujące i wysyła jego parametry
-- *
-- * \param dcc Struktura połączenia
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--static int gg_dcc7_listen_and_send_info(struct gg_dcc7 *dcc)
--{
-- struct gg_dcc7_info pkt;
-- uint16_t external_port;
-- uint32_t external_addr;
-- struct in_addr addr;
--
-- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_listen_and_send_info(%p)\n", dcc);
--
-- if (gg_dcc7_listen(dcc, dcc->sess->client_addr, dcc->sess->client_port) == -1)
-- return -1;
--
-- if (dcc->sess->external_port != 0)
-- external_port = dcc->sess->external_port;
-- else
-- external_port = dcc->local_port;
--
-- if (dcc->sess->external_addr != 0)
-- external_addr = dcc->sess->external_addr;
-- else
-- external_addr = dcc->local_addr;
--
-- addr.s_addr = external_addr;
--
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// dcc7_listen_and_send_info() sending IP address %s and port %d\n", inet_ntoa(addr), external_port);
--
-- memset(&pkt, 0, sizeof(pkt));
-- pkt.uin = gg_fix32(dcc->peer_uin);
-- pkt.type = GG_DCC7_TYPE_P2P;
-- pkt.id = dcc->cid;
-- snprintf((char*) pkt.info, sizeof(pkt.info), "%s %d", inet_ntoa(addr), external_port);
-- snprintf((char*) pkt.hash, sizeof(pkt.hash), "%u", external_addr + external_port * rand());
--
-- return gg_send_packet(dcc->sess, GG_DCC7_INFO, &pkt, sizeof(pkt), NULL);
--}
--
--/**
-- * \internal Odwraca połączenie po nieudanym connect()
-- *
-- * \param dcc Struktura połączenia
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--static int gg_dcc7_reverse_connect(struct gg_dcc7 *dcc)
--{
-- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_reverse_connect(%p)\n", dcc);
--
-- if (dcc->reverse) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_reverse_connect() already reverse connection\n");
-- return -1;
-- }
--
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_reverse_connect() timeout, trying reverse connection\n");
-- close(dcc->fd);
-- dcc->fd = -1;
-- dcc->reverse = 1;
--
-- return gg_dcc7_listen_and_send_info(dcc);
--}
--
--/**
-- * \internal Wysyła do serwera żądanie nadania identyfikatora sesji
-- *
-- * \param sess Struktura sesji
-- * \param type Rodzaj połączenia (\c GG_DCC7_TYPE_FILE lub \c GG_DCC7_TYPE_VOICE)
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--static int gg_dcc7_request_id(struct gg_session *sess, uint32_t type)
--{
-- struct gg_dcc7_id_request pkt;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_request_id(%p, %d)\n", sess, type);
--
-- if (!sess) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_request_id() invalid parameters\n");
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (sess->state != GG_STATE_CONNECTED) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_request_id() not connected\n");
-- errno = ENOTCONN;
-- return -1;
-- }
--
-- if (type != GG_DCC7_TYPE_VOICE && type != GG_DCC7_TYPE_FILE) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_request_id() invalid transfer type (%d)\n", type);
-- errno = EINVAL;
-- return -1;
-- }
--
-- memset(&pkt, 0, sizeof(pkt));
-- pkt.type = gg_fix32(type);
--
-- return gg_send_packet(sess, GG_DCC7_ID_REQUEST, &pkt, sizeof(pkt), NULL);
--}
--
--/**
-- * \internal Rozpoczyna wysyłanie pliku.
-- *
-- * Funkcja jest wykorzystywana przez \c gg_dcc7_send_file() oraz
-- * \c gg_dcc_send_file_fd().
-- *
-- * \param sess Struktura sesji
-- * \param rcpt Numer odbiorcy
-- * \param fd Deskryptor pliku
-- * \param size Rozmiar pliku
-- * \param filename1250 Nazwa pliku w kodowaniu CP-1250
-- * \param hash Skrót SHA-1 pliku
-- * \param seek Flaga mówiąca, czy można używać lseek()
-- *
-- * \return Struktura \c gg_dcc7 lub \c NULL w przypadku błędu
-- *
-- * \ingroup dcc7
-- */
--static struct gg_dcc7 *gg_dcc7_send_file_common(struct gg_session *sess, uin_t rcpt, int fd, size_t size, const char *filename1250, const char *hash, int seek)
--{
-- struct gg_dcc7 *dcc = NULL;
--
-- if (!sess || !rcpt || !filename1250 || !hash || fd == -1) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file_common() invalid parameters\n");
-- errno = EINVAL;
-- goto fail;
-- }
--
-- if (!(dcc = malloc(sizeof(struct gg_dcc7)))) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file_common() not enough memory\n");
-- goto fail;
-- }
--
-- if (gg_dcc7_request_id(sess, GG_DCC7_TYPE_FILE) == -1)
-- goto fail;
--
-- memset(dcc, 0, sizeof(struct gg_dcc7));
-- dcc->type = GG_SESSION_DCC7_SEND;
-- dcc->dcc_type = GG_DCC7_TYPE_FILE;
-- dcc->state = GG_STATE_REQUESTING_ID;
-- dcc->timeout = GG_DEFAULT_TIMEOUT;
-- dcc->sess = sess;
-- dcc->fd = -1;
-- dcc->uin = sess->uin;
-- dcc->peer_uin = rcpt;
-- dcc->file_fd = fd;
-- dcc->size = size;
-- dcc->seek = seek;
--
-- strncpy((char*) dcc->filename, filename1250, GG_DCC7_FILENAME_LEN - 1);
-- dcc->filename[GG_DCC7_FILENAME_LEN] = 0;
--
-- memcpy(dcc->hash, hash, GG_DCC7_HASH_LEN);
--
-- if (gg_dcc7_session_add(sess, dcc) == -1)
-- goto fail;
--
-- return dcc;
--
--fail:
-- free(dcc);
-- return NULL;
--}
--
--/**
-- * Rozpoczyna wysyłanie pliku o danej nazwie.
-- *
-- * \param sess Struktura sesji
-- * \param rcpt Numer odbiorcy
-- * \param filename Nazwa pliku w lokalnym systemie plików
-- * \param filename1250 Nazwa pliku w kodowaniu CP-1250
-- * \param hash Skrót SHA-1 pliku (lub \c NULL jeśli ma być wyznaczony)
-- *
-- * \return Struktura \c gg_dcc7 lub \c NULL w przypadku błędu
-- *
-- * \ingroup dcc7
-- */
--struct gg_dcc7 *gg_dcc7_send_file(struct gg_session *sess, uin_t rcpt, const char *filename, const char *filename1250, const char *hash)
--{
-- struct gg_dcc7 *dcc = NULL;
-- const char *tmp;
-- char hash_buf[GG_DCC7_HASH_LEN];
-- struct stat st;
-- int fd = -1;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_send_file(%p, %d, \"%s\", %p)\n", sess, rcpt, filename, hash);
--
-- if (!sess || !rcpt || !filename) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file() invalid parameters\n");
-- errno = EINVAL;
-- goto fail;
-- }
--
-- if (!filename1250)
-- filename1250 = filename;
--
-- if (stat(filename, &st) == -1) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file() stat() failed (%s)\n", strerror(errno));
-- goto fail;
-- }
--
-- if ((st.st_mode & S_IFDIR)) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file() that's a directory\n");
-- errno = EINVAL;
-- goto fail;
-- }
--
-- if ((fd = open(filename, O_RDONLY)) == -1) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file() open() failed (%s)\n", strerror(errno));
-- goto fail;
-- }
--
-- if (!hash) {
-- if (gg_file_hash_sha1(fd, (uint8_t*) hash_buf) == -1)
-- goto fail;
--
-- hash = hash_buf;
-- }
--
-- if ((tmp = strrchr(filename1250, '/')))
-- filename1250 = tmp + 1;
--
-- if (!(dcc = gg_dcc7_send_file_common(sess, rcpt, fd, st.st_size, filename1250, hash, 1)))
-- goto fail;
--
-- return dcc;
--
--fail:
-- if (fd != -1) {
-- int errsv = errno;
-- close(fd);
-- errno = errsv;
-- }
--
-- free(dcc);
-- return NULL;
--}
--
--/**
-- * \internal Rozpoczyna wysyłanie pliku o danym deskryptorze.
-- *
-- * \note Wysyłanie pliku nie będzie działać poprawnie, jeśli deskryptor
-- * źródłowy jest w trybie nieblokującym i w pewnym momencie zabraknie danych.
-- *
-- * \param sess Struktura sesji
-- * \param rcpt Numer odbiorcy
-- * \param fd Deskryptor pliku
-- * \param size Rozmiar pliku
-- * \param filename1250 Nazwa pliku w kodowaniu CP-1250
-- * \param hash Skrót SHA-1 pliku
-- *
-- * \return Struktura \c gg_dcc7 lub \c NULL w przypadku błędu
-- *
-- * \ingroup dcc7
-- */
--struct gg_dcc7 *gg_dcc7_send_file_fd(struct gg_session *sess, uin_t rcpt, int fd, size_t size, const char *filename1250, const char *hash)
--{
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_send_file_fd(%p, %d, %d, %u, \"%s\", %p)\n", sess, rcpt, fd, size, filename1250, hash);
--
-- return gg_dcc7_send_file_common(sess, rcpt, fd, size, filename1250, hash, 0);
--}
--
--
--/**
-- * Potwierdza chęć odebrania pliku.
-- *
-- * \param dcc Struktura połączenia
-- * \param offset Początkowy offset przy wznawianiu przesyłania pliku
-- *
-- * \note Biblioteka nie zmienia położenia w odbieranych plikach. Jeśli offset
-- * początkowy jest różny od zera, należy ustawić go funkcją \c lseek() lub
-- * podobnÄ….
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup dcc7
-- */
--int gg_dcc7_accept(struct gg_dcc7 *dcc, unsigned int offset)
--{
-- struct gg_dcc7_accept pkt;
--
-- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_accept(%p, %d)\n", dcc, offset);
--
-- if (!dcc || !dcc->sess) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_accept() invalid parameters\n");
-- errno = EFAULT;
-- return -1;
-- }
--
-- memset(&pkt, 0, sizeof(pkt));
-- pkt.uin = gg_fix32(dcc->peer_uin);
-- pkt.id = dcc->cid;
-- pkt.offset = gg_fix32(offset);
--
-- if (gg_send_packet(dcc->sess, GG_DCC7_ACCEPT, &pkt, sizeof(pkt), NULL) == -1)
-- return -1;
--
-- dcc->offset = offset;
--
-- return gg_dcc7_listen_and_send_info(dcc);
--}
--
--/**
-- * Odrzuca próbę przesłania pliku.
-- *
-- * \param dcc Struktura połączenia
-- * \param reason Powód odrzucenia
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup dcc7
-- */
--int gg_dcc7_reject(struct gg_dcc7 *dcc, int reason)
--{
-- struct gg_dcc7_reject pkt;
--
-- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_reject(%p, %d)\n", dcc, reason);
--
-- if (!dcc || !dcc->sess) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_reject() invalid parameters\n");
-- errno = EFAULT;
-- return -1;
-- }
--
-- memset(&pkt, 0, sizeof(pkt));
-- pkt.uin = gg_fix32(dcc->peer_uin);
-- pkt.id = dcc->cid;
-- pkt.reason = gg_fix32(reason);
--
-- return gg_send_packet(dcc->sess, GG_DCC7_REJECT, &pkt, sizeof(pkt), NULL);
--}
--
--/**
-- * \internal Obsługuje pakiet identyfikatora połączenia bezpośredniego.
-- *
-- * \param sess Struktura sesji
-- * \param e Struktura zdarzenia
-- * \param payload Treść pakietu
-- * \param len Długość pakietu
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--int gg_dcc7_handle_id(struct gg_session *sess, struct gg_event *e, const void *payload, int len)
--{
-- const struct gg_dcc7_id_reply *p = payload;
-- struct gg_dcc7 *tmp;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_id(%p, %p, %p, %d)\n", sess, e, payload, len);
--
-- for (tmp = sess->dcc7_list; tmp; tmp = tmp->next) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// checking dcc %p, state %d, type %d\n", tmp, tmp->state, tmp->dcc_type);
--
-- if (tmp->state != GG_STATE_REQUESTING_ID || tmp->dcc_type != gg_fix32(p->type))
-- continue;
--
-- tmp->cid = p->id;
--
-- switch (tmp->dcc_type) {
-- case GG_DCC7_TYPE_FILE:
-- {
-- struct gg_dcc7_new s;
--
-- memset(&s, 0, sizeof(s));
-- s.id = tmp->cid;
-- s.type = gg_fix32(GG_DCC7_TYPE_FILE);
-- s.uin_from = gg_fix32(tmp->uin);
-- s.uin_to = gg_fix32(tmp->peer_uin);
-- s.size = gg_fix32(tmp->size);
--
-- memcpy((char*) s.filename, (char*) tmp->filename, GG_DCC7_FILENAME_LEN);
--
-- tmp->state = GG_STATE_WAITING_FOR_ACCEPT;
-- tmp->timeout = GG_DCC7_TIMEOUT_FILE_ACK;
--
-- return gg_send_packet(sess, GG_DCC7_NEW, &s, sizeof(s), NULL);
-- }
-- }
-- }
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet akceptacji połączenia bezpośredniego.
-- *
-- * \param sess Struktura sesji
-- * \param e Struktura zdarzenia
-- * \param payload Treść pakietu
-- * \param len Długość pakietu
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--int gg_dcc7_handle_accept(struct gg_session *sess, struct gg_event *e, const void *payload, int len)
--{
-- const struct gg_dcc7_accept *p = payload;
-- struct gg_dcc7 *dcc;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_accept(%p, %p, %p, %d)\n", sess, e, payload, len);
--
-- if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(p->uin)))) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_accept() unknown dcc session\n");
-- // XXX wysłać reject?
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
-- return 0;
-- }
--
-- if (dcc->state != GG_STATE_WAITING_FOR_ACCEPT) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_accept() invalid state\n");
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
-- return 0;
-- }
--
-- // XXX czy dla odwrotnego połączenia powinniśmy wywołać już zdarzenie GG_DCC7_ACCEPT?
--
-- dcc->offset = gg_fix32(p->offset);
-- dcc->state = GG_STATE_WAITING_FOR_INFO;
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet informacji o połączeniu bezpośrednim.
-- *
-- * \param sess Struktura sesji
-- * \param e Struktura zdarzenia
-- * \param payload Treść pakietu
-- * \param len Długość pakietu
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--int gg_dcc7_handle_info(struct gg_session *sess, struct gg_event *e, const void *payload, int len)
--{
-- const struct gg_dcc7_info *p = payload;
-- struct gg_dcc7 *dcc;
-- char *tmp;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_info(%p, %p, %p, %d)\n", sess, e, payload, len);
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "// gg_dcc7_handle_info() received address: %s, hash: %s\n", p->info, p->hash);
--
-- if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(p->uin)))) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unknown dcc session\n");
-- return 0;
-- }
--
-- if (dcc->state == GG_STATE_CONNECTED) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() state is already connected\n");
-- return 0;
-- }
--
-- switch (p->type)
-- {
-- case GG_DCC7_TYPE_P2P:
-- if ((dcc->remote_addr = inet_addr(p->info)) == INADDR_NONE) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid IP address\n");
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
-- return 0;
-- }
--
-- if (!(tmp = strchr(p->info, ' ')) || !(dcc->remote_port = atoi(tmp + 1))) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid IP port\n");
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
-- return 0;
-- }
--
-- if (dcc->state == GG_STATE_WAITING_FOR_INFO) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() waiting for info so send one\n");
-- gg_dcc7_listen_and_send_info(dcc);
-- e->type = GG_EVENT_DCC7_PENDING;
-- e->event.dcc7_pending.dcc7 = dcc;
-- return 0;
-- }
--
-- break;
--
-- case GG_DCC7_TYPE_SERVER:
-- if (!(tmp = strstr(p->info, "GG"))) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unknown info packet\n");
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
-- return 0;
-- }
--
--#if defined(HAVE_UINT64_T) && defined(HAVE_STRTOULL)
-- {
-- uint64_t cid;
--
-- cid = strtoull(tmp + 2, NULL, 0);
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() info.str=%s, info.id=%llu, sess.id=%llu\n", tmp + 2, cid, *((unsigned long long*) &dcc->cid));
--
-- cid = gg_fix64(cid);
--
-- if (memcmp(&dcc->cid, &cid, sizeof(cid)) != 0) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid session id\n");
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
-- return 0;
-- }
-- }
--#endif
--
-- if (gg_dcc7_get_relay_addr(dcc) == -1) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unable to retrieve relay address\n");
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc7_error = GG_ERROR_DCC7_RELAY;
-- return 0;
-- }
--
-- // XXX wysyłać dopiero jeśli uda się połączyć z serwerem?
--
-- gg_send_packet(dcc->sess, GG_DCC7_INFO, payload, len, NULL);
--
-- return 0;
--
-- default:
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unhandled transfer type (%d)\n", p->type);
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
-- return 0;
-- }
--
-- // jeśli nadal czekamy na połączenie przychodzące, a druga strona nie
-- // daje rady i oferuje namiary na siebie, bierzemy co dajÄ….
--
--// if (dcc->state != GG_STATE_WAITING_FOR_INFO && (dcc->state != GG_STATE_LISTENING || dcc->reverse)) {
--// gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid state\n");
--// e->type = GG_EVENT_DCC7_ERROR;
--// e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
--// return 0;
--// }
--
-- if (dcc->state == GG_STATE_LISTENING) {
-- close(dcc->fd);
-- dcc->fd = -1;
-- dcc->reverse = 1;
-- }
--
-- if (dcc->type == GG_SESSION_DCC7_SEND) {
-- e->type = GG_EVENT_DCC7_ACCEPT;
-- e->event.dcc7_accept.dcc7 = dcc;
-- e->event.dcc7_accept.type = gg_fix32(p->type);
-- e->event.dcc7_accept.remote_ip = dcc->remote_addr;
-- e->event.dcc7_accept.remote_port = dcc->remote_port;
-- } else {
-- e->type = GG_EVENT_DCC7_PENDING;
-- e->event.dcc7_pending.dcc7 = dcc;
-- }
--
-- if (gg_dcc7_connect(dcc) == -1) {
-- if (gg_dcc7_reverse_connect(dcc) == -1) {
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc7_error = GG_ERROR_DCC7_NET;
-- return 0;
-- }
-- }
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet odrzucenia połączenia bezpośredniego.
-- *
-- * \param sess Struktura sesji
-- * \param e Struktura zdarzenia
-- * \param payload Treść pakietu
-- * \param len Długość pakietu
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--int gg_dcc7_handle_reject(struct gg_session *sess, struct gg_event *e, const void *payload, int len)
--{
-- const struct gg_dcc7_reject *p = payload;
-- struct gg_dcc7 *dcc;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_reject(%p, %p, %p, %d)\n", sess, e, payload, len);
--
-- if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(p->uin)))) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_reject() unknown dcc session\n");
-- return 0;
-- }
--
-- if (dcc->state != GG_STATE_WAITING_FOR_ACCEPT) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_reject() invalid state\n");
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
-- return 0;
-- }
--
-- e->type = GG_EVENT_DCC7_REJECT;
-- e->event.dcc7_reject.dcc7 = dcc;
-- e->event.dcc7_reject.reason = gg_fix32(p->reason);
--
-- // XXX ustawić state na rejected?
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet nowego połączenia bezpośredniego.
-- *
-- * \param sess Struktura sesji
-- * \param e Struktura zdarzenia
-- * \param payload Treść pakietu
-- * \param len Długość pakietu
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--int gg_dcc7_handle_new(struct gg_session *sess, struct gg_event *e, const void *payload, int len)
--{
-- const struct gg_dcc7_new *p = payload;
-- struct gg_dcc7 *dcc;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_new(%p, %p, %p, %d)\n", sess, e, payload, len);
--
-- switch (gg_fix32(p->type)) {
-- case GG_DCC7_TYPE_FILE:
-- if (!(dcc = malloc(sizeof(struct gg_dcc7)))) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_new() not enough memory\n");
-- return -1;
-- }
--
-- memset(dcc, 0, sizeof(struct gg_dcc7));
-- dcc->type = GG_SESSION_DCC7_GET;
-- dcc->dcc_type = GG_DCC7_TYPE_FILE;
-- dcc->fd = -1;
-- dcc->file_fd = -1;
-- dcc->uin = sess->uin;
-- dcc->peer_uin = gg_fix32(p->uin_from);
-- dcc->cid = p->id;
-- dcc->sess = sess;
--
-- if (gg_dcc7_session_add(sess, dcc) == -1) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_new() unable to add to session\n");
-- gg_dcc7_free(dcc);
-- return -1;
-- }
--
-- dcc->size = gg_fix32(p->size);
-- strncpy((char*) dcc->filename, (char*) p->filename, GG_DCC7_FILENAME_LEN - 1);
-- dcc->filename[GG_DCC7_FILENAME_LEN] = 0;
-- memcpy(dcc->hash, p->hash, GG_DCC7_HASH_LEN);
--
-- e->type = GG_EVENT_DCC7_NEW;
-- e->event.dcc7_new = dcc;
--
-- break;
--
-- case GG_DCC7_TYPE_VOICE:
-- if (!(dcc = malloc(sizeof(struct gg_dcc7)))) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_packet() not enough memory\n");
-- return -1;
-- }
--
-- memset(dcc, 0, sizeof(struct gg_dcc7));
--
-- dcc->type = GG_SESSION_DCC7_VOICE;
-- dcc->dcc_type = GG_DCC7_TYPE_VOICE;
-- dcc->fd = -1;
-- dcc->file_fd = -1;
-- dcc->uin = sess->uin;
-- dcc->peer_uin = gg_fix32(p->uin_from);
-- dcc->cid = p->id;
-- dcc->sess = sess;
--
-- if (gg_dcc7_session_add(sess, dcc) == -1) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_new() unable to add to session\n");
-- gg_dcc7_free(dcc);
-- return -1;
-- }
--
-- e->type = GG_EVENT_DCC7_NEW;
-- e->event.dcc7_new = dcc;
--
-- break;
--
-- default:
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_new() unknown dcc type (%d) from %ld\n", gg_fix32(p->type), gg_fix32(p->uin_from));
--
-- break;
-- }
--
-- return 0;
--}
--
--/**
-- * \internal Ustawia odpowiednie stany wewnętrzne w zależności od rodzaju
-- * połączenia.
-- *
-- * \param dcc Struktura połączenia
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu.
-- */
--static int gg_dcc7_postauth_fixup(struct gg_dcc7 *dcc)
--{
-- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_postauth_fixup(%p)\n", dcc);
--
-- if (!dcc) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_postauth_fixup() invalid parameters\n");
-- errno = EINVAL;
-- return -1;
-- }
--
-- switch (dcc->type) {
-- case GG_SESSION_DCC7_GET:
-- dcc->state = GG_STATE_GETTING_FILE;
-- dcc->check = GG_CHECK_READ;
-- return 0;
--
-- case GG_SESSION_DCC7_SEND:
-- dcc->state = GG_STATE_SENDING_FILE;
-- dcc->check = GG_CHECK_WRITE;
-- return 0;
--
-- case GG_SESSION_DCC7_VOICE:
-- dcc->state = GG_STATE_READING_VOICE_DATA;
-- dcc->check = GG_CHECK_READ;
-- return 0;
-- }
--
-- errno = EINVAL;
--
-- return -1;
--}
--
--/**
-- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
-- *
-- * Funkcja zwraca strukturę zdarzenia \c gg_event. Jeśli rodzaj zdarzenia
-- * to \c GG_EVENT_NONE, nie wydarzyło się jeszcze nic wartego odnotowania.
-- * Strukturę zdarzenia należy zwolnić funkcja \c gg_event_free().
-- *
-- * \param dcc Struktura połączenia
-- *
-- * \return Struktura zdarzenia lub \c NULL jeśli wystąpił błąd
-- *
-- * \ingroup dcc7
-- */
--struct gg_event *gg_dcc7_watch_fd(struct gg_dcc7 *dcc)
--{
-- struct gg_event *e;
--
-- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_watch_fd(%p)\n", dcc);
--
-- if (!dcc || (dcc->type != GG_SESSION_DCC7_SEND && dcc->type != GG_SESSION_DCC7_GET && dcc->type != GG_SESSION_DCC7_VOICE)) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() invalid parameters\n");
-- errno = EINVAL;
-- return NULL;
-- }
--
-- if (!(e = malloc(sizeof(struct gg_event)))) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() not enough memory\n");
-- return NULL;
-- }
--
-- memset(e, 0, sizeof(struct gg_event));
-- e->type = GG_EVENT_NONE;
--
-- switch (dcc->state) {
-- case GG_STATE_LISTENING:
-- {
-- struct sockaddr_in sin;
-- int fd, one = 1;
-- socklen_t sin_len = sizeof(sin);
--
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_LISTENING\n");
--
-- if ((fd = accept(dcc->fd, (struct sockaddr*) &sin, &sin_len)) == -1) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() accept() failed (%s)\n", strerror(errno));
-- return e;
-- }
--
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() connection from %s:%d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
--
--#ifdef FIONBIO
-- if (ioctl(fd, FIONBIO, &one) == -1) {
--#else
-- if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
--#endif
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() can't set nonblocking (%s)\n", strerror(errno));
-- close(fd);
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
-- return e;
-- }
--
-- close(dcc->fd);
-- dcc->fd = fd;
--
-- dcc->state = GG_STATE_READING_ID;
-- dcc->check = GG_CHECK_READ;
-- dcc->timeout = GG_DEFAULT_TIMEOUT;
-- dcc->incoming = 1;
--
-- dcc->remote_port = ntohs(sin.sin_port);
-- dcc->remote_addr = sin.sin_addr.s_addr;
--
-- e->type = GG_EVENT_DCC7_CONNECTED;
-- e->event.dcc7_connected.dcc7 = dcc;
--
-- return e;
-- }
--
-- case GG_STATE_CONNECTING:
-- {
-- int res = 0, error = 0;
-- unsigned int error_size = sizeof(error);
--
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_CONNECTING\n");
--
-- dcc->soft_timeout = 0;
--
-- if (dcc->timeout == 0)
-- error = ETIMEDOUT;
--
-- if (error || (res = getsockopt(dcc->fd, SOL_SOCKET, SO_ERROR, &error, &error_size)) == -1 || error != 0) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() connection failed (%s)\n", (res == -1) ? strerror(errno) : strerror(error));
--
-- if (dcc->relay) {
-- for (dcc->relay_index++; dcc->relay_index < dcc->relay_count; dcc->relay_index++) {
-- dcc->remote_addr = dcc->relay_list[dcc->relay_index].addr;
-- dcc->remote_port = dcc->relay_list[dcc->relay_index].port;
--
-- if (gg_dcc7_connect(dcc) == 0)
-- break;
-- }
--
-- if (dcc->relay_index >= dcc->relay_count) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() no relay available");
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
-- return e;
-- }
-- } else {
-- if (gg_dcc7_reverse_connect(dcc) != -1) {
-- e->type = GG_EVENT_DCC7_PENDING;
-- e->event.dcc7_pending.dcc7 = dcc;
-- } else {
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_NET;
-- }
--
-- return e;
-- }
-- }
--
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() connected, sending id\n");
--
-- dcc->state = GG_STATE_SENDING_ID;
-- dcc->check = GG_CHECK_WRITE;
-- dcc->timeout = GG_DEFAULT_TIMEOUT;
-- dcc->incoming = 0;
--
-- return e;
-- }
--
-- case GG_STATE_READING_ID:
-- {
-- int res;
--
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_READING_ID\n");
--
-- if (!dcc->relay) {
-- struct gg_dcc7_welcome_p2p welcome, welcome_ok;
-- welcome_ok.id = dcc->cid;
--
-- if ((res = read(dcc->fd, &welcome, sizeof(welcome))) != sizeof(welcome)) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (%d, %s)\n", res, strerror(errno));
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
-- return e;
-- }
--
-- if (memcmp(&welcome, &welcome_ok, sizeof(welcome))) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() invalid id\n");
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
-- return e;
-- }
-- } else {
-- struct gg_dcc7_welcome_server welcome, welcome_ok;
-- welcome_ok.magic = GG_DCC7_WELCOME_SERVER;
-- welcome_ok.id = dcc->cid;
--
-- if ((res = read(dcc->fd, &welcome, sizeof(welcome))) != sizeof(welcome)) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (%d, %s)\n", res, strerror(errno));
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
-- return e;
-- }
--
-- if (memcmp(&welcome, &welcome_ok, sizeof(welcome)) != 0) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() invalid id\n");
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
-- return e;
-- }
-- }
--
-- if (dcc->incoming) {
-- dcc->state = GG_STATE_SENDING_ID;
-- dcc->check = GG_CHECK_WRITE;
-- dcc->timeout = GG_DEFAULT_TIMEOUT;
-- } else {
-- gg_dcc7_postauth_fixup(dcc);
-- dcc->timeout = GG_DEFAULT_TIMEOUT;
-- }
--
-- return e;
-- }
--
-- case GG_STATE_SENDING_ID:
-- {
-- int res;
--
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_SENDING_ID\n");
--
-- if (!dcc->relay) {
-- struct gg_dcc7_welcome_p2p welcome;
--
-- welcome.id = dcc->cid;
--
-- if ((res = write(dcc->fd, &welcome, sizeof(welcome))) != sizeof(welcome)) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (%d, %s)\n", res, strerror(errno));
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
-- return e;
-- }
-- } else {
-- struct gg_dcc7_welcome_server welcome;
--
-- welcome.magic = gg_fix32(GG_DCC7_WELCOME_SERVER);
-- welcome.id = dcc->cid;
--
-- if ((res = write(dcc->fd, &welcome, sizeof(welcome))) != sizeof(welcome)) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (%d, %s)\n", res, strerror(errno));
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
-- return e;
-- }
-- }
--
-- if (dcc->incoming) {
-- gg_dcc7_postauth_fixup(dcc);
-- dcc->timeout = GG_DEFAULT_TIMEOUT;
-- } else {
-- dcc->state = GG_STATE_READING_ID;
-- dcc->check = GG_CHECK_READ;
-- dcc->timeout = GG_DEFAULT_TIMEOUT;
-- }
--
-- return e;
-- }
--
-- case GG_STATE_SENDING_FILE:
-- {
-- char buf[1024];
-- int chunk, res;
--
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_SENDING_FILE (offset=%d, size=%d)\n", dcc->offset, dcc->size);
--
-- if (dcc->offset >= dcc->size) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() offset >= size, finished\n");
-- e->type = GG_EVENT_DCC7_DONE;
-- e->event.dcc7_done.dcc7 = dcc;
-- return e;
-- }
--
-- if (dcc->seek && lseek(dcc->file_fd, dcc->offset, SEEK_SET) == (off_t) -1) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() lseek() failed (%s)\n", strerror(errno));
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_FILE;
-- return e;
-- }
--
-- if ((chunk = dcc->size - dcc->offset) > sizeof(buf))
-- chunk = sizeof(buf);
--
-- if ((res = read(dcc->file_fd, buf, chunk)) < 1) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (res=%d, %s)\n", res, strerror(errno));
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = (res == -1) ? GG_ERROR_DCC7_FILE : GG_ERROR_DCC7_EOF;
-- return e;
-- }
--
-- if ((res = write(dcc->fd, buf, res)) == -1) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (%s)\n", strerror(errno));
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_NET;
-- return e;
-- }
--
-- dcc->offset += res;
--
-- if (dcc->offset >= dcc->size) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() finished\n");
-- e->type = GG_EVENT_DCC7_DONE;
-- e->event.dcc7_done.dcc7 = dcc;
-- return e;
-- }
--
-- dcc->state = GG_STATE_SENDING_FILE;
-- dcc->check = GG_CHECK_WRITE;
-- dcc->timeout = GG_DCC7_TIMEOUT_SEND;
--
-- return e;
-- }
--
-- case GG_STATE_GETTING_FILE:
-- {
-- char buf[1024];
-- int res, wres;
--
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_GETTING_FILE (offset=%d, size=%d)\n", dcc->offset, dcc->size);
--
-- if (dcc->offset >= dcc->size) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() finished\n");
-- e->type = GG_EVENT_DCC7_DONE;
-- e->event.dcc7_done.dcc7 = dcc;
-- return e;
-- }
--
-- if ((res = read(dcc->fd, buf, sizeof(buf))) < 1) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (fd=%d, res=%d, %s)\n", dcc->fd, res, strerror(errno));
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = (res == -1) ? GG_ERROR_DCC7_NET : GG_ERROR_DCC7_EOF;
-- return e;
-- }
--
-- // XXX zapisywać do skutku?
--
-- if ((wres = write(dcc->file_fd, buf, res)) < res) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (fd=%d, res=%d, %s)\n", dcc->file_fd, wres, strerror(errno));
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_FILE;
-- return e;
-- }
--
-- dcc->offset += res;
--
-- if (dcc->offset >= dcc->size) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() finished\n");
-- e->type = GG_EVENT_DCC7_DONE;
-- e->event.dcc7_done.dcc7 = dcc;
-- return e;
-- }
--
-- dcc->state = GG_STATE_GETTING_FILE;
-- dcc->check = GG_CHECK_READ;
-- dcc->timeout = GG_DCC7_TIMEOUT_GET;
--
-- return e;
-- }
--
-- case GG_STATE_RESOLVING_RELAY:
-- {
-- struct in_addr addr;
--
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_RESOLVING_RELAY\n");
--
-- if (read(dcc->fd, &addr, sizeof(addr)) < sizeof(addr) || addr.s_addr == INADDR_NONE) {
-- int errno_save = errno;
--
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() resolving failed\n");
-- close(dcc->fd);
-- dcc->fd = -1;
-- dcc->sess->resolver_cleanup(&dcc->resolver, 0);
-- errno = errno_save;
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
-- return e;
-- }
--
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() resolved, connecting to %s:%d\n", inet_ntoa(addr), GG_RELAY_PORT);
--
-- if ((dcc->fd = gg_connect(&addr, GG_RELAY_PORT, 1)) == -1) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() connection failed (errno=%d, %s), critical\n", errno, strerror(errno));
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
-- return e;
-- }
--
-- dcc->state = GG_STATE_CONNECTING_RELAY;
-- dcc->check = GG_CHECK_WRITE;
-- dcc->timeout = GG_DEFAULT_TIMEOUT;
--
-- e->type = GG_EVENT_DCC7_PENDING;
-- e->event.dcc7_pending.dcc7 = dcc;
--
-- return e;
-- }
--
-- case GG_STATE_CONNECTING_RELAY:
-- {
-- int res;
-- unsigned int res_size = sizeof(res);
-- struct gg_dcc7_relay_req pkt;
--
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_CONNECTING_RELAY\n");
--
-- if (getsockopt(dcc->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) != 0 || res != 0) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() connection failed (errno=%d, %s)\n", res, strerror(res));
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
-- return e;
-- }
--
-- memset(&pkt, 0, sizeof(pkt));
-- pkt.magic = gg_fix32(GG_DCC7_RELAY_REQUEST);
-- pkt.len = gg_fix32(sizeof(pkt));
-- pkt.id = dcc->cid;
-- pkt.type = gg_fix16(GG_DCC7_RELAY_TYPE_SERVER);
-- pkt.dunno1 = gg_fix16(GG_DCC7_RELAY_DUNNO1);
--
-- gg_debug_dcc(dcc, GG_DEBUG_DUMP, "// gg_dcc7_watch_fd() send pkt(0x%.2x)\n", gg_fix32(pkt.magic));
-- gg_debug_dump_dcc(dcc, GG_DEBUG_DUMP, (const char*) &pkt, sizeof(pkt));
--
-- if ((res = write(dcc->fd, &pkt, sizeof(pkt))) != sizeof(pkt)) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() sending failed\n");
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
-- return e;
-- }
--
-- dcc->state = GG_STATE_READING_RELAY;
-- dcc->check = GG_CHECK_READ;
-- dcc->timeout = GG_DEFAULT_TIMEOUT;
--
-- return e;
-- }
--
-- case GG_STATE_READING_RELAY:
-- {
-- char buf[256];
-- struct gg_dcc7_relay_reply *pkt;
-- struct gg_dcc7_relay_reply_server srv;
-- int res;
-- int i;
--
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_READING_RELAY\n");
--
-- if ((res = read(dcc->fd, buf, sizeof(buf))) < sizeof(*pkt)) {
-- if (res == 0)
-- errno = ECONNRESET;
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (%d, %s)\n", res, strerror(errno));
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
-- return e;
-- }
--
-- pkt = (struct gg_dcc7_relay_reply*) buf;
--
-- if (gg_fix32(pkt->magic) != GG_DCC7_RELAY_REPLY || gg_fix32(pkt->rcount) < 1 || gg_fix32(pkt->rcount > 256) || gg_fix32(pkt->len) < sizeof(*pkt) + gg_fix32(pkt->rcount) * sizeof(srv)) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_wathc_fd() invalid reply\n");
-- errno = EINVAL;
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
-- return e;
-- }
--
-- gg_debug_dcc(dcc, GG_DEBUG_DUMP, "// gg_dcc7_get_relay() read pkt(0x%.2x)\n", gg_fix32(pkt->magic));
-- gg_debug_dump_dcc(dcc, GG_DEBUG_DUMP, buf, res);
--
-- free(dcc->relay_list);
--
-- dcc->relay_index = 0;
-- dcc->relay_count = gg_fix32(pkt->rcount);
-- dcc->relay_list = malloc(dcc->relay_count * sizeof(gg_dcc7_relay_t));
--
-- if (dcc->relay_list == NULL) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() not enough memory");
-- dcc->relay_count = 0;
-- free(e);
-- return NULL;
-- }
--
-- for (i = 0; i < dcc->relay_count; i++) {
-- struct in_addr addr;
--
-- memcpy(&srv, buf + sizeof(*pkt) + i * sizeof(srv), sizeof(srv));
-- dcc->relay_list[i].addr = srv.addr;
-- dcc->relay_list[i].port = gg_fix16(srv.port);
-- dcc->relay_list[i].family = srv.family;
--
-- addr.s_addr = srv.addr;
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// %s %d %d\n", inet_ntoa(addr), gg_fix16(srv.port), srv.family);
-- }
--
-- dcc->relay = 1;
--
-- for (; dcc->relay_index < dcc->relay_count; dcc->relay_index++) {
-- dcc->remote_addr = dcc->relay_list[dcc->relay_index].addr;
-- dcc->remote_port = dcc->relay_list[dcc->relay_index].port;
--
-- if (gg_dcc7_connect(dcc) == 0)
-- break;
-- }
--
-- if (dcc->relay_index >= dcc->relay_count) {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() no relay available");
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
-- return e;
-- }
--
-- return e;
-- }
--
-- default:
-- {
-- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_???\n");
-- e->type = GG_EVENT_DCC7_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
--
-- return e;
-- }
-- }
--
-- return e;
--}
--
--/**
-- * Zwalnia zasoby używane przez połączenie bezpośrednie.
-- *
-- * \param dcc Struktura połączenia
-- *
-- * \ingroup dcc7
-- */
--void gg_dcc7_free(struct gg_dcc7 *dcc)
--{
-- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_free(%p)\n", dcc);
--
-- if (!dcc)
-- return;
--
-- if (dcc->fd != -1)
-- close(dcc->fd);
--
-- if (dcc->file_fd != -1)
-- close(dcc->file_fd);
--
-- if (dcc->sess)
-- gg_dcc7_session_remove(dcc->sess, dcc);
--
-- free(dcc->relay_list);
--
-- free(dcc);
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/dcc.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/dcc.c
---- pidgin-2.10.7/libpurple/protocols/gg/lib/dcc.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/dcc.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1345 +0,0 @@
--/* $Id: dcc.c 1023 2010-11-16 18:27:35Z wojtekka $ */
--
--/*
-- * (C) Copyright 2001-2008 Wojtek Kaniewski <wojtekka@irc.pl>
-- * Tomasz Chiliński <chilek@chilan.com>
-- * Adam Wysocki <gophi@ekg.chmurka.net>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--/**
-- * \file dcc.c
-- *
-- * \brief Obsługa połączeń bezpośrednich do wersji Gadu-Gadu 6.x
-- */
--
--#include <sys/types.h>
--#include <sys/stat.h>
--#ifndef _WIN32
--# include <sys/ioctl.h>
--# include <sys/socket.h>
--# include <netinet/in.h>
--# include <arpa/inet.h>
--# ifdef sun
--# include <sys/filio.h>
--# endif
--#endif
--
--#include <ctype.h>
--#include <errno.h>
--#include <fcntl.h>
--#include <stdarg.h>
--#include <string.h>
--#include <stdio.h>
--#include <stdlib.h>
--#include <unistd.h>
--
--#include "compat.h"
--#include "libgadu.h"
--
--#ifndef GG_DEBUG_DISABLE
--
--/**
-- * \internal Przekazuje zawartość pakietu do odpluskwiania.
-- *
-- * \param prefix Prefiks informacji
-- * \param fd Deskryptor gniazda
-- * \param buf Bufor z danumi
-- * \param size Rozmiar bufora z danymi
-- */
--static void gg_dcc_debug_data(const char *prefix, int fd, const void *buf, unsigned int size)
--{
-- unsigned int i;
--
-- gg_debug(GG_DEBUG_MISC, "++ gg_dcc %s (fd=%d,len=%d)", prefix, fd, size);
--
-- for (i = 0; i < size; i++)
-- gg_debug(GG_DEBUG_MISC, " %.2x", ((unsigned char*) buf)[i]);
--
-- gg_debug(GG_DEBUG_MISC, "\n");
--}
--#else
--#define gg_dcc_debug_data(a,b,c,d) do { } while (0)
--#endif
--
--/**
-- * Wysyła żądanie zwrotnego połączenia bezpośredniego.
-- *
-- * Funkcję wykorzystuje się, jeśli nie ma możliwości połączenia się z odbiorcą
-- * pliku lub rozmowy głosowej. Po otrzymaniu żądania druga strona spróbuje
-- * nawiązać zwrotne połączenie bezpośrednie z nadawcą.
-- * gg_dcc_request()
-- *
-- * \param sess Struktura sesji
-- * \param uin Numer odbiorcy
-- *
-- * \return Patrz \c gg_send_message_ctcp()
-- *
-- * \ingroup dcc6
-- */
--int gg_dcc_request(struct gg_session *sess, uin_t uin)
--{
-- return gg_send_message_ctcp(sess, GG_CLASS_CTCP, uin, (unsigned char*) "\002", 1);
--}
--
--/**
-- * \internal Zamienia znacznik czasu w postaci uniksowej na format API WIN32.
-- *
-- * \note Funkcja działa jedynie gdy kompilator obsługuje typ danych
-- * \c long \c long.
-- *
-- * \param ut Czas w postaci uniksowej
-- * \param ft Czas w postaci API WIN32
-- */
--static void gg_dcc_fill_filetime(uint32_t ut, uint32_t *ft)
--{
--#ifdef GG_CONFIG_HAVE_LONG_LONG
-- unsigned long long tmp;
--
-- tmp = ut;
-- tmp += 11644473600LL;
-- tmp *= 10000000LL;
--
--#ifndef GG_CONFIG_BIGENDIAN
-- ft[0] = (uint32_t) tmp;
-- ft[1] = (uint32_t) (tmp >> 32);
--#else
-- ft[0] = gg_fix32((uint32_t) (tmp >> 32));
-- ft[1] = gg_fix32((uint32_t) tmp);
--#endif
--
--#endif
--}
--
--/**
-- * Wypełnia pola struktury \c gg_dcc niezbędne do wysłania pliku.
-- *
-- * \note Większą funkcjonalność zapewnia funkcja \c gg_dcc_fill_file_info2().
-- *
-- * \param d Struktura połączenia
-- * \param filename Nazwa pliku
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup dcc6
-- */
--int gg_dcc_fill_file_info(struct gg_dcc *d, const char *filename)
--{
-- return gg_dcc_fill_file_info2(d, filename, filename);
--}
--
--/**
-- * Wypełnia pola struktury \c gg_dcc niezbędne do wysłania pliku.
-- *
-- * \param d Struktura połączenia
-- * \param filename Nazwa pliku zapisywana w strukturze
-- * \param local_filename Nazwa pliku w lokalnym systemie plików
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup dcc6
-- */
--int gg_dcc_fill_file_info2(struct gg_dcc *d, const char *filename, const char *local_filename)
--{
-- struct stat st;
-- const char *name, *ext, *p;
-- unsigned char *q;
-- int i, j;
--
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_fill_file_info2(%p, \"%s\", \"%s\");\n", d, filename, local_filename);
--
-- if (!d || d->type != GG_SESSION_DCC_SEND) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() invalid arguments\n");
-- errno = EINVAL;
-- return -1;
-- }
--
-- if (stat(local_filename, &st) == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() stat() failed (%s)\n", strerror(errno));
-- return -1;
-- }
--
-- if ((st.st_mode & S_IFDIR)) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() that's a directory\n");
-- errno = EINVAL;
-- return -1;
-- }
--
-- if ((d->file_fd = open(local_filename, O_RDONLY)) == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() open() failed (%s)\n", strerror(errno));
-- return -1;
-- }
--
-- memset(&d->file_info, 0, sizeof(d->file_info));
--
-- if (!(st.st_mode & S_IWUSR))
-- d->file_info.mode |= gg_fix32(GG_DCC_FILEATTR_READONLY);
--
-- gg_dcc_fill_filetime(st.st_atime, d->file_info.atime);
-- gg_dcc_fill_filetime(st.st_mtime, d->file_info.mtime);
-- gg_dcc_fill_filetime(st.st_ctime, d->file_info.ctime);
--
-- d->file_info.size = gg_fix32(st.st_size);
-- d->file_info.mode = gg_fix32(0x20); /* FILE_ATTRIBUTE_ARCHIVE */
--
-- if (!(name = strrchr(filename, '/')))
-- name = filename;
-- else
-- name++;
--
-- if (!(ext = strrchr(name, '.')))
-- ext = name + strlen(name);
--
-- for (i = 0, p = name; i < 8 && p < ext; i++, p++)
-- d->file_info.short_filename[i] = toupper(name[i]);
--
-- if (i == 8 && p < ext) {
-- d->file_info.short_filename[6] = '~';
-- d->file_info.short_filename[7] = '1';
-- }
--
-- if (strlen(ext) > 0) {
-- for (j = 0; *ext && j < 4; j++, p++)
-- d->file_info.short_filename[i + j] = toupper(ext[j]);
-- }
--
-- for (q = d->file_info.short_filename; *q; q++) {
-- if (*q == 185) {
-- *q = 165;
-- } else if (*q == 230) {
-- *q = 198;
-- } else if (*q == 234) {
-- *q = 202;
-- } else if (*q == 179) {
-- *q = 163;
-- } else if (*q == 241) {
-- *q = 209;
-- } else if (*q == 243) {
-- *q = 211;
-- } else if (*q == 156) {
-- *q = 140;
-- } else if (*q == 159) {
-- *q = 143;
-- } else if (*q == 191) {
-- *q = 175;
-- }
-- }
--
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() short name \"%s\", dos name \"%s\"\n", name, d->file_info.short_filename);
-- strncpy((char*) d->file_info.filename, name, sizeof(d->file_info.filename) - 1);
--
-- return 0;
--}
--
--/**
-- * \internal Rozpoczyna połączenie bezpośrednie z danym klientem.
-- *
-- * \param ip Adres IP odbiorcy
-- * \param port Port odbiorcy
-- * \param my_uin WÅ‚asny numer
-- * \param peer_uin Numer odbiorcy
-- * \param type Rodzaj połączenia (\c GG_SESSION_DCC_SEND lub \c GG_SESSION_DCC_GET)
-- *
-- * \return Struktura \c gg_dcc lub \c NULL w przypadku błędu
-- */
--static struct gg_dcc *gg_dcc_transfer(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin, int type)
--{
-- struct gg_dcc *d = NULL;
-- struct in_addr addr;
--
-- addr.s_addr = ip;
--
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_transfer(%s, %d, %ld, %ld, %s);\n", inet_ntoa(addr), port, my_uin, peer_uin, (type == GG_SESSION_DCC_SEND) ? "SEND" : "GET");
--
-- if (!ip || ip == INADDR_NONE || !port || !my_uin || !peer_uin) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_transfer() invalid arguments\n");
-- errno = EINVAL;
-- return NULL;
-- }
--
-- if (!(d = (void*) calloc(1, sizeof(*d)))) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_transfer() not enough memory\n");
-- return NULL;
-- }
--
-- d->check = GG_CHECK_WRITE;
-- d->state = GG_STATE_CONNECTING;
-- d->type = type;
-- d->timeout = GG_DEFAULT_TIMEOUT;
-- d->file_fd = -1;
-- d->active = 1;
-- d->fd = -1;
-- d->uin = my_uin;
-- d->peer_uin = peer_uin;
--
-- if ((d->fd = gg_connect(&addr, port, 1)) == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_transfer() connection failed\n");
-- free(d);
-- return NULL;
-- }
--
-- return d;
--}
--
--/**
-- * Rozpoczyna odbieranie pliku przez zwrotne połączenie bezpośrednie.
-- *
-- * \param ip Adres IP nadawcy
-- * \param port Port nadawcy
-- * \param my_uin WÅ‚asny numer
-- * \param peer_uin Numer nadawcy
-- *
-- * \return Struktura \c gg_dcc lub \c NULL w przypadku błędu
-- *
-- * \ingroup dcc6
-- */
--struct gg_dcc *gg_dcc_get_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin)
--{
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_get_file() handing over to gg_dcc_transfer()\n");
--
-- return gg_dcc_transfer(ip, port, my_uin, peer_uin, GG_SESSION_DCC_GET);
--}
--
--/**
-- * Rozpoczyna wysyłanie pliku.
-- *
-- * \param ip Adres IP odbiorcy
-- * \param port Port odbiorcy
-- * \param my_uin WÅ‚asny numer
-- * \param peer_uin Numer odbiorcy
-- *
-- * \return Struktura \c gg_dcc lub \c NULL w przypadku błędu
-- *
-- * \ingroup dcc6
-- */
--struct gg_dcc *gg_dcc_send_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin)
--{
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_send_file() handing over to gg_dcc_transfer()\n");
--
-- return gg_dcc_transfer(ip, port, my_uin, peer_uin, GG_SESSION_DCC_SEND);
--}
--
--/**
-- * Rozpoczyna połączenie głosowe.
-- *
-- * \param ip Adres IP odbiorcy
-- * \param port Port odbiorcy
-- * \param my_uin WÅ‚asny numer
-- * \param peer_uin Numer odbiorcy
-- *
-- * \return Struktura \c gg_dcc lub \c NULL w przypadku błędu
-- *
-- * \ingroup dcc6
-- */
--struct gg_dcc *gg_dcc_voice_chat(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin)
--{
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_chat() handing over to gg_dcc_transfer()\n");
--
-- return gg_dcc_transfer(ip, port, my_uin, peer_uin, GG_SESSION_DCC_VOICE);
--}
--
--/**
-- * Ustawia typ przychodzącego połączenia bezpośredniego.
-- *
-- * Funkcję należy wywołać po otrzymaniu zdarzenia \c GG_EVENT_DCC_CALLBACK.
-- *
-- * \param d Struktura połączenia
-- * \param type Rodzaj połączenia (\c GG_SESSION_DCC_SEND lub
-- * \c GG_SESSION_DCC_VOICE)
-- *
-- * \ingroup dcc6
-- */
--void gg_dcc_set_type(struct gg_dcc *d, int type)
--{
-- d->type = type;
-- d->state = (type == GG_SESSION_DCC_SEND) ? GG_STATE_SENDING_FILE_INFO : GG_STATE_SENDING_VOICE_REQUEST;
--}
--
--/**
-- * \internal Funkcja zwrotna połączenia bezpośredniego.
-- *
-- * Pole \c callback struktury \c gg_dcc zawiera wskaźnik do tej funkcji.
-- * Wywołuje ona \c gg_watch_fd() i zachowuje wynik w polu \c event.
-- *
-- * \note Funkcjonalność funkcjo zwrotnej nie jest już wspierana.
-- *
-- * \param d Struktura połączenia
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--static int gg_dcc_callback(struct gg_dcc *d)
--{
-- struct gg_event *e = gg_dcc_watch_fd(d);
--
-- d->event = e;
--
-- return (e != NULL) ? 0 : -1;
--}
--
--/**
-- * Tworzy gniazdo nasłuchujące dla połączeń bezpośrednich.
-- *
-- * Funkcja przywiÄ…zuje gniazdo do pierwszego wolnego portu TCP.
-- *
-- * \param uin WÅ‚asny numer
-- * \param port Preferowany port (jeśli równy 0 lub -1, próbuje się domyślnego)
-- *
-- * \return Struktura \c gg_dcc lub \c NULL w przypadku błędu
-- *
-- * \ingroup dcc6
-- */
--struct gg_dcc *gg_dcc_socket_create(uin_t uin, uint16_t port)
--{
-- struct gg_dcc *c;
-- struct sockaddr_in sin;
-- int sock, bound = 0, errno2;
--
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_create_dcc_socket(%d, %d);\n", uin, port);
--
-- if (!uin) {
-- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() invalid arguments\n");
-- errno = EINVAL;
-- return NULL;
-- }
--
-- if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() can't create socket (%s)\n", strerror(errno));
-- return NULL;
-- }
--
-- if (port == 0 || port == (uint16_t)-1) /* XXX: port is unsigned */
-- port = GG_DEFAULT_DCC_PORT;
--
-- while (!bound) {
-- memset(&sin, 0, sizeof(sin));
-- sin.sin_family = AF_INET;
-- sin.sin_addr.s_addr = INADDR_ANY;
-- sin.sin_port = htons(port);
--
-- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() trying port %d\n", port);
-- if (!bind(sock, (struct sockaddr*) &sin, sizeof(sin)))
-- bound = 1;
-- else {
-- if (++port == 65535) {
-- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() no free port found\n");
-- close(sock);
-- return NULL;
-- }
-- }
-- }
--
-- if (listen(sock, 10)) {
-- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() unable to listen (%s)\n", strerror(errno));
-- errno2 = errno;
-- close(sock);
-- errno = errno2;
-- return NULL;
-- }
--
-- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() bound to port %d\n", port);
--
-- if (!(c = malloc(sizeof(*c)))) {
-- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() not enough memory for struct\n");
-- close(sock);
-- return NULL;
-- }
-- memset(c, 0, sizeof(*c));
--
-- c->port = c->id = port;
-- c->fd = sock;
-- c->type = GG_SESSION_DCC_SOCKET;
-- c->uin = uin;
-- c->timeout = -1;
-- c->state = GG_STATE_LISTENING;
-- c->check = GG_CHECK_READ;
-- c->callback = gg_dcc_callback;
-- c->destroy = gg_dcc_free;
--
-- return c;
--}
--
--/**
-- * Wysyła ramkę danych połączenia głosowego.
-- *
-- * \param d Struktura połączenia
-- * \param buf Bufor z danymi
-- * \param length Długość bufora z danymi
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup dcc6
-- */
--int gg_dcc_voice_send(struct gg_dcc *d, char *buf, int length)
--{
-- struct packet_s {
-- uint8_t type;
-- uint32_t length;
-- } GG_PACKED;
-- struct packet_s packet;
--
-- gg_debug(GG_DEBUG_FUNCTION, "++ gg_dcc_voice_send(%p, %p, %d);\n", d, buf, length);
-- if (!d || !buf || length < 0 || d->type != GG_SESSION_DCC_VOICE) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_send() invalid argument\n");
-- errno = EINVAL;
-- return -1;
-- }
--
-- packet.type = 0x03; /* XXX */
-- packet.length = gg_fix32(length);
--
-- if (write(d->fd, &packet, sizeof(packet)) < (signed)sizeof(packet)) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_send() write() failed\n");
-- return -1;
-- }
-- gg_dcc_debug_data("write", d->fd, &packet, sizeof(packet));
--
-- if (write(d->fd, buf, length) < length) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_send() write() failed\n");
-- return -1;
-- }
-- gg_dcc_debug_data("write", d->fd, buf, length);
--
-- return 0;
--}
--
--/**
-- * \internal Odbiera dane z połączenia bezpośredniego z obsługą błędów.
-- *
-- * \param fd Deskryptor gniazda
-- * \param buf Bufor na dane
-- * \param size Rozmiar bufora na dane
-- */
--#define gg_dcc_read(fd, buf, size) \
--{ \
-- int tmp = read(fd, buf, size); \
-- \
-- if (tmp < (int) size) { \
-- if (tmp == -1) { \
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed (errno=%d, %s)\n", errno, strerror(errno)); \
-- } else if (tmp == 0) { \
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed, connection broken\n"); \
-- } else { \
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed (%d bytes, %d needed)\n", tmp, size); \
-- } \
-- e->type = GG_EVENT_DCC_ERROR; \
-- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; \
-- return e; \
-- } \
-- gg_dcc_debug_data("read", fd, buf, size); \
--}
--
--/**
-- * \internal Wysyła dane do połączenia bezpośredniego z obsługą błędów.
-- *
-- * \param fd Deskryptor gniazda
-- * \param buf Bufor z danymi
-- * \param size Rozmiar bufora z danymi
-- */
--#define gg_dcc_write(fd, buf, size) \
--{ \
-- int tmp; \
-- gg_dcc_debug_data("write", fd, buf, size); \
-- tmp = write(fd, buf, size); \
-- if (tmp < (int) size) { \
-- if (tmp == -1) { \
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (errno=%d, %s)\n", errno, strerror(errno)); \
-- } else { \
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (%d needed, %d done)\n", size, tmp); \
-- } \
-- e->type = GG_EVENT_DCC_ERROR; \
-- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; \
-- return e; \
-- } \
--}
--
--/**
-- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
-- *
-- * Funkcja zwraca strukturę zdarzenia \c gg_event. Jeśli rodzaj zdarzenia
-- * to \c GG_EVENT_NONE, nie wydarzyło się jeszcze nic wartego odnotowania.
-- * Strukturę zdarzenia należy zwolnić funkcja \c gg_event_free.
-- *
-- * \param h Struktura połączenia
-- *
-- * \return Struktura zdarzenia lub \c NULL jeśli wystąpił błąd
-- *
-- * \ingroup dcc6
-- */
--struct gg_event *gg_dcc_watch_fd(struct gg_dcc *h)
--{
-- struct gg_event *e;
-- int foo;
--
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_watch_fd(%p);\n", h);
--
-- if (!h || (h->type != GG_SESSION_DCC && h->type != GG_SESSION_DCC_SOCKET && h->type != GG_SESSION_DCC_SEND && h->type != GG_SESSION_DCC_GET && h->type != GG_SESSION_DCC_VOICE)) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() invalid argument\n");
-- errno = EINVAL;
-- return NULL;
-- }
--
-- if (!(e = (void*) calloc(1, sizeof(*e)))) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() not enough memory\n");
-- return NULL;
-- }
--
-- e->type = GG_EVENT_NONE;
--
-- if (h->type == GG_SESSION_DCC_SOCKET) {
-- struct sockaddr_in sin;
-- struct gg_dcc *c;
-- int fd, one = 1;
-- unsigned int sin_len = sizeof(sin);
--
-- if ((fd = accept(h->fd, (struct sockaddr*) &sin, &sin_len)) == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() can't accept() new connection (errno=%d, %s)\n", errno, strerror(errno));
-- return e;
-- }
--
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() new direct connection from %s:%d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
--
--#ifdef FIONBIO
-- if (ioctl(fd, FIONBIO, &one) == -1) {
--#else
-- if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
--#endif
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() can't set nonblocking (errno=%d, %s)\n", errno, strerror(errno));
-- close(fd);
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
-- return e;
-- }
--
-- if (!(c = (void*) calloc(1, sizeof(*c)))) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() not enough memory for client data\n");
--
-- free(e);
-- close(fd);
-- return NULL;
-- }
--
-- c->fd = fd;
-- c->check = GG_CHECK_READ;
-- c->state = GG_STATE_READING_UIN_1;
-- c->type = GG_SESSION_DCC;
-- c->timeout = GG_DEFAULT_TIMEOUT;
-- c->file_fd = -1;
-- c->remote_addr = sin.sin_addr.s_addr;
-- c->remote_port = ntohs(sin.sin_port);
--
-- e->type = GG_EVENT_DCC_NEW;
-- e->event.dcc_new = c;
--
-- return e;
-- } else {
-- struct gg_dcc_tiny_packet tiny;
-- struct gg_dcc_small_packet small;
-- struct gg_dcc_big_packet big;
-- int size, tmp, res;
-- unsigned int utmp, res_size = sizeof(res);
-- char buf[1024], ack[] = "UDAG";
--
-- struct gg_dcc_file_info_packet {
-- struct gg_dcc_big_packet big;
-- struct gg_file_info file_info;
-- } GG_PACKED;
-- struct gg_dcc_file_info_packet file_info_packet;
--
-- switch (h->state) {
-- case GG_STATE_READING_UIN_1:
-- case GG_STATE_READING_UIN_2:
-- {
-- uin_t uin;
--
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_READING_UIN_%d\n", (h->state == GG_STATE_READING_UIN_1) ? 1 : 2);
--
-- gg_dcc_read(h->fd, &uin, sizeof(uin));
--
-- if (h->state == GG_STATE_READING_UIN_1) {
-- h->state = GG_STATE_READING_UIN_2;
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DEFAULT_TIMEOUT;
-- h->peer_uin = gg_fix32(uin);
-- } else {
-- h->state = GG_STATE_SENDING_ACK;
-- h->check = GG_CHECK_WRITE;
-- h->timeout = GG_DEFAULT_TIMEOUT;
-- h->uin = gg_fix32(uin);
-- e->type = GG_EVENT_DCC_CLIENT_ACCEPT;
-- }
--
-- return e;
-- }
--
-- case GG_STATE_SENDING_ACK:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_SENDING_ACK\n");
--
-- gg_dcc_write(h->fd, ack, 4);
--
-- h->state = GG_STATE_READING_TYPE;
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DEFAULT_TIMEOUT;
--
-- return e;
--
-- case GG_STATE_READING_TYPE:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_TYPE\n");
--
-- gg_dcc_read(h->fd, &small, sizeof(small));
--
-- small.type = gg_fix32(small.type);
--
-- switch (small.type) {
-- case 0x0003: /* XXX */
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() callback\n");
-- h->type = GG_SESSION_DCC_SEND;
-- h->state = GG_STATE_SENDING_FILE_INFO;
-- h->check = GG_CHECK_WRITE;
-- h->timeout = GG_DEFAULT_TIMEOUT;
--
-- e->type = GG_EVENT_DCC_CALLBACK;
--
-- break;
--
-- case 0x0002: /* XXX */
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() dialin\n");
-- h->type = GG_SESSION_DCC_GET;
-- h->state = GG_STATE_READING_REQUEST;
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DEFAULT_TIMEOUT;
-- h->incoming = 1;
--
-- break;
--
-- default:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown dcc type (%.4x) from %ld\n", small.type, h->peer_uin);
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
-- }
--
-- return e;
--
-- case GG_STATE_READING_REQUEST:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_REQUEST\n");
--
-- gg_dcc_read(h->fd, &small, sizeof(small));
--
-- small.type = gg_fix32(small.type);
--
-- switch (small.type) {
-- case 0x0001: /* XXX */
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() file transfer request\n");
-- h->state = GG_STATE_READING_FILE_INFO;
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DEFAULT_TIMEOUT;
-- break;
--
-- case 0x0003: /* XXX */
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() voice chat request\n");
-- h->state = GG_STATE_SENDING_VOICE_ACK;
-- h->check = GG_CHECK_WRITE;
-- h->timeout = GG_DCC_TIMEOUT_VOICE_ACK;
-- h->type = GG_SESSION_DCC_VOICE;
-- e->type = GG_EVENT_DCC_NEED_VOICE_ACK;
--
-- break;
--
-- default:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown dcc request (%.4x) from %ld\n", small.type, h->peer_uin);
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
-- }
--
-- return e;
--
-- case GG_STATE_READING_FILE_INFO:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_FILE_INFO\n");
--
-- gg_dcc_read(h->fd, &file_info_packet, sizeof(file_info_packet));
--
-- memcpy(&h->file_info, &file_info_packet.file_info, sizeof(h->file_info));
--
-- h->file_info.mode = gg_fix32(h->file_info.mode);
-- h->file_info.size = gg_fix32(h->file_info.size);
--
-- h->state = GG_STATE_SENDING_FILE_ACK;
-- h->check = GG_CHECK_WRITE;
-- h->timeout = GG_DCC_TIMEOUT_FILE_ACK;
--
-- e->type = GG_EVENT_DCC_NEED_FILE_ACK;
--
-- return e;
--
-- case GG_STATE_SENDING_FILE_ACK:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE_ACK\n");
--
-- big.type = gg_fix32(0x0006); /* XXX */
-- big.dunno1 = gg_fix32(h->offset);
-- big.dunno2 = 0;
--
-- gg_dcc_write(h->fd, &big, sizeof(big));
--
-- h->state = GG_STATE_READING_FILE_HEADER;
-- h->chunk_size = sizeof(big);
-- h->chunk_offset = 0;
-- if (!(h->chunk_buf = malloc(sizeof(big)))) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() out of memory\n");
-- free(e);
-- return NULL;
-- }
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DEFAULT_TIMEOUT;
--
-- return e;
--
-- case GG_STATE_SENDING_VOICE_ACK:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_VOICE_ACK\n");
--
-- tiny.type = 0x01; /* XXX */
--
-- gg_dcc_write(h->fd, &tiny, sizeof(tiny));
--
-- h->state = GG_STATE_READING_VOICE_HEADER;
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DEFAULT_TIMEOUT;
--
-- h->offset = 0;
--
-- return e;
--
-- case GG_STATE_READING_FILE_HEADER:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_FILE_HEADER\n");
--
-- tmp = read(h->fd, h->chunk_buf + h->chunk_offset, h->chunk_size - h->chunk_offset);
--
-- if (tmp == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() read() failed (errno=%d, %s)\n", errno, strerror(errno));
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_NET;
-- return e;
-- }
--
-- gg_dcc_debug_data("read", h->fd, h->chunk_buf + h->chunk_offset, h->chunk_size - h->chunk_offset);
--
-- h->chunk_offset += tmp;
--
-- if (h->chunk_offset < h->chunk_size)
-- return e;
--
-- memcpy(&big, h->chunk_buf, sizeof(big));
-- free(h->chunk_buf);
-- h->chunk_buf = NULL;
--
-- big.type = gg_fix32(big.type);
-- h->chunk_size = gg_fix32(big.dunno1);
-- h->chunk_offset = 0;
--
-- if (big.type == 0x0005) { /* XXX */
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() transfer refused\n");
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_REFUSED;
-- return e;
-- }
--
-- if (h->chunk_size == 0) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() empty chunk, EOF\n");
-- e->type = GG_EVENT_DCC_DONE;
-- return e;
-- }
--
-- h->state = GG_STATE_GETTING_FILE;
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DEFAULT_TIMEOUT;
-- h->established = 1;
--
-- return e;
--
-- case GG_STATE_READING_VOICE_HEADER:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_HEADER\n");
--
-- gg_dcc_read(h->fd, &tiny, sizeof(tiny));
--
-- switch (tiny.type) {
-- case 0x03: /* XXX */
-- h->state = GG_STATE_READING_VOICE_SIZE;
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DEFAULT_TIMEOUT;
-- h->established = 1;
-- break;
-- case 0x04: /* XXX */
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() peer breaking connection\n");
-- /* XXX zwracać odpowiedni event */
-- default:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown request (%.2x)\n", tiny.type);
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
-- }
--
-- return e;
--
-- case GG_STATE_READING_VOICE_SIZE:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_SIZE\n");
--
-- gg_dcc_read(h->fd, &small, sizeof(small));
--
-- small.type = gg_fix32(small.type);
--
-- if (small.type < 16 || small.type > sizeof(buf)) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() invalid voice frame size (%d)\n", small.type);
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_NET;
--
-- return e;
-- }
--
-- h->chunk_size = small.type;
-- h->chunk_offset = 0;
--
-- if (!(h->voice_buf = malloc(h->chunk_size))) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() out of memory for voice frame\n");
-- free(e);
-- return NULL;
-- }
--
-- h->state = GG_STATE_READING_VOICE_DATA;
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DEFAULT_TIMEOUT;
--
-- return e;
--
-- case GG_STATE_READING_VOICE_DATA:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_DATA\n");
--
-- tmp = read(h->fd, h->voice_buf + h->chunk_offset, h->chunk_size - h->chunk_offset);
-- if (tmp < 1) {
-- if (tmp == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed (errno=%d, %s)\n", errno, strerror(errno));
-- } else {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed, connection broken\n");
-- }
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_NET;
-- return e;
-- }
--
-- gg_dcc_debug_data("read", h->fd, h->voice_buf + h->chunk_offset, tmp);
--
-- h->chunk_offset += tmp;
--
-- if (h->chunk_offset >= h->chunk_size) {
-- e->type = GG_EVENT_DCC_VOICE_DATA;
-- e->event.dcc_voice_data.data = (unsigned char*) h->voice_buf;
-- e->event.dcc_voice_data.length = h->chunk_size;
-- h->state = GG_STATE_READING_VOICE_HEADER;
-- h->voice_buf = NULL;
-- }
--
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DEFAULT_TIMEOUT;
--
-- return e;
--
-- case GG_STATE_CONNECTING:
-- {
-- uin_t uins[2];
--
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_CONNECTING\n");
--
-- res = 0;
-- if ((foo = getsockopt(h->fd, SOL_SOCKET, SO_ERROR, &res, &res_size)) || res) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() connection failed (fd=%d,errno=%d(%s),foo=%d,res=%d(%s))\n", h->fd, errno, strerror(errno), foo, res, strerror(res));
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
-- return e;
-- }
--
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() connected, sending uins\n");
--
-- uins[0] = gg_fix32(h->uin);
-- uins[1] = gg_fix32(h->peer_uin);
--
-- gg_dcc_write(h->fd, uins, sizeof(uins));
--
-- h->state = GG_STATE_READING_ACK;
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DEFAULT_TIMEOUT;
--
-- return e;
-- }
--
-- case GG_STATE_READING_ACK:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_ACK\n");
--
-- gg_dcc_read(h->fd, buf, 4);
--
-- if (strncmp(buf, ack, 4)) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() did't get ack\n");
--
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
-- return e;
-- }
--
-- h->check = GG_CHECK_WRITE;
-- h->timeout = GG_DEFAULT_TIMEOUT;
-- h->state = GG_STATE_SENDING_REQUEST;
--
-- return e;
--
-- case GG_STATE_SENDING_VOICE_REQUEST:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_VOICE_REQUEST\n");
--
-- small.type = gg_fix32(0x0003);
--
-- gg_dcc_write(h->fd, &small, sizeof(small));
--
-- h->state = GG_STATE_READING_VOICE_ACK;
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DEFAULT_TIMEOUT;
--
-- return e;
--
-- case GG_STATE_SENDING_REQUEST:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_REQUEST\n");
--
-- small.type = (h->type == GG_SESSION_DCC_GET) ? gg_fix32(0x0003) : gg_fix32(0x0002); /* XXX */
--
-- gg_dcc_write(h->fd, &small, sizeof(small));
--
-- switch (h->type) {
-- case GG_SESSION_DCC_GET:
-- h->state = GG_STATE_READING_REQUEST;
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DEFAULT_TIMEOUT;
-- break;
--
-- case GG_SESSION_DCC_SEND:
-- h->state = GG_STATE_SENDING_FILE_INFO;
-- h->check = GG_CHECK_WRITE;
-- h->timeout = GG_DEFAULT_TIMEOUT;
--
-- if (h->file_fd == -1)
-- e->type = GG_EVENT_DCC_NEED_FILE_INFO;
-- break;
--
-- case GG_SESSION_DCC_VOICE:
-- h->state = GG_STATE_SENDING_VOICE_REQUEST;
-- h->check = GG_CHECK_WRITE;
-- h->timeout = GG_DEFAULT_TIMEOUT;
-- break;
-- }
--
-- return e;
--
-- case GG_STATE_SENDING_FILE_INFO:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE_INFO\n");
--
-- if (h->file_fd == -1) {
-- e->type = GG_EVENT_DCC_NEED_FILE_INFO;
-- return e;
-- }
--
-- small.type = gg_fix32(0x0001); /* XXX */
--
-- gg_dcc_write(h->fd, &small, sizeof(small));
--
-- file_info_packet.big.type = gg_fix32(0x0003); /* XXX */
-- file_info_packet.big.dunno1 = 0;
-- file_info_packet.big.dunno2 = 0;
--
-- memcpy(&file_info_packet.file_info, &h->file_info, sizeof(h->file_info));
--
-- /* zostają teraz u nas, więc odwracamy z powrotem */
-- h->file_info.size = gg_fix32(h->file_info.size);
-- h->file_info.mode = gg_fix32(h->file_info.mode);
--
-- gg_dcc_write(h->fd, &file_info_packet, sizeof(file_info_packet));
--
-- h->state = GG_STATE_READING_FILE_ACK;
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DCC_TIMEOUT_FILE_ACK;
--
-- return e;
--
-- case GG_STATE_READING_FILE_ACK:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_FILE_ACK\n");
--
-- gg_dcc_read(h->fd, &big, sizeof(big));
--
-- /* XXX sprawdzać wynik */
-- h->offset = gg_fix32(big.dunno1);
--
-- h->state = GG_STATE_SENDING_FILE_HEADER;
-- h->check = GG_CHECK_WRITE;
-- h->timeout = GG_DEFAULT_TIMEOUT;
--
-- e->type = GG_EVENT_DCC_ACK;
--
-- return e;
--
-- case GG_STATE_READING_VOICE_ACK:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_ACK\n");
--
-- gg_dcc_read(h->fd, &tiny, sizeof(tiny));
--
-- if (tiny.type != 0x01) {
-- gg_debug(GG_DEBUG_MISC, "// invalid reply (%.2x), connection refused\n", tiny.type);
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_REFUSED;
-- return e;
-- }
--
-- h->state = GG_STATE_READING_VOICE_HEADER;
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DEFAULT_TIMEOUT;
--
-- e->type = GG_EVENT_DCC_ACK;
--
-- return e;
--
-- case GG_STATE_SENDING_FILE_HEADER:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE_HEADER\n");
--
-- h->chunk_offset = 0;
--
-- if ((h->chunk_size = h->file_info.size - h->offset) > 4096) {
-- h->chunk_size = 4096;
-- big.type = gg_fix32(0x0003); /* XXX */
-- } else
-- big.type = gg_fix32(0x0002); /* XXX */
--
-- big.dunno1 = gg_fix32(h->chunk_size);
-- big.dunno2 = 0;
--
-- gg_dcc_write(h->fd, &big, sizeof(big));
--
-- h->state = GG_STATE_SENDING_FILE;
-- h->check = GG_CHECK_WRITE;
-- h->timeout = GG_DEFAULT_TIMEOUT;
-- h->established = 1;
--
-- return e;
--
-- case GG_STATE_SENDING_FILE:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE\n");
--
-- if ((utmp = h->chunk_size - h->chunk_offset) > sizeof(buf))
-- utmp = sizeof(buf);
--
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() offset=%d, size=%d\n", h->offset, h->file_info.size);
--
-- /* koniec pliku? */
-- if (h->file_info.size == 0) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() reached eof on empty file\n");
-- e->type = GG_EVENT_DCC_DONE;
--
-- return e;
-- }
--
-- if (h->offset >= h->file_info.size) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() offset >= size, finished\n");
-- e->type = GG_EVENT_DCC_DONE;
-- return e;
-- }
--
-- lseek(h->file_fd, h->offset, SEEK_SET);
--
-- size = read(h->file_fd, buf, utmp);
--
-- /* błąd */
-- if (size == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed. (errno=%d, %s)\n", errno, strerror(errno));
--
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_FILE;
--
-- return e;
-- }
--
-- /* koniec pliku? */
-- if (size == 0) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() reached eof\n");
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_EOF;
--
-- return e;
-- }
--
-- /* jeśli wczytaliśmy więcej, utnijmy. */
-- if (h->offset + size > h->file_info.size) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() too much (read=%d, ofs=%d, size=%d)\n", size, h->offset, h->file_info.size);
-- size = h->file_info.size - h->offset;
--
-- if (size < 1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() reached EOF after cutting\n");
-- e->type = GG_EVENT_DCC_DONE;
-- return e;
-- }
-- }
--
-- tmp = write(h->fd, buf, size);
--
-- if (tmp == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (%s)\n", strerror(errno));
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_NET;
-- return e;
-- }
--
-- if (tmp == 0) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (connection reset)\n");
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_NET;
-- return e;
-- }
--
-- h->offset += tmp;
--
-- if (h->offset >= h->file_info.size) {
-- e->type = GG_EVENT_DCC_DONE;
-- return e;
-- }
--
-- h->chunk_offset += tmp;
--
-- if (h->chunk_offset >= h->chunk_size) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() chunk finished\n");
-- h->state = GG_STATE_SENDING_FILE_HEADER;
-- h->timeout = GG_DEFAULT_TIMEOUT;
-- } else {
-- h->state = GG_STATE_SENDING_FILE;
-- h->timeout = GG_DCC_TIMEOUT_SEND;
-- }
--
-- h->check = GG_CHECK_WRITE;
--
-- return e;
--
-- case GG_STATE_GETTING_FILE:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_GETTING_FILE\n");
--
-- if ((utmp = h->chunk_size - h->chunk_offset) > sizeof(buf))
-- utmp = sizeof(buf);
--
-- if (h->offset >= h->file_info.size) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() offset >= size, finished\n");
-- e->type = GG_EVENT_DCC_DONE;
-- return e;
-- }
--
-- size = read(h->fd, buf, utmp);
--
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() ofs=%d, size=%d, read()=%d\n", h->offset, h->file_info.size, size);
--
-- /* błąd */
-- if (size == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed. (errno=%d, %s)\n", errno, strerror(errno));
--
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_NET;
--
-- return e;
-- }
--
-- /* koniec? */
-- if (size == 0) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() reached eof\n");
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_EOF;
--
-- return e;
-- }
--
-- tmp = write(h->file_fd, buf, size);
--
-- if (tmp == -1 || tmp < size) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (%d:fd=%d:res=%d:%s)\n", tmp, h->file_fd, size, strerror(errno));
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_NET;
-- return e;
-- }
--
-- h->offset += size;
--
-- if (h->offset >= h->file_info.size) {
-- e->type = GG_EVENT_DCC_DONE;
-- return e;
-- }
--
-- h->chunk_offset += size;
--
-- if (h->chunk_offset >= h->chunk_size) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() chunk finished\n");
-- h->state = GG_STATE_READING_FILE_HEADER;
-- h->timeout = GG_DEFAULT_TIMEOUT;
-- h->chunk_offset = 0;
-- h->chunk_size = sizeof(big);
-- if (!(h->chunk_buf = malloc(sizeof(big)))) {
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() out of memory\n");
-- free(e);
-- return NULL;
-- }
-- } else {
-- h->state = GG_STATE_GETTING_FILE;
-- h->timeout = GG_DCC_TIMEOUT_GET;
-- }
--
-- h->check = GG_CHECK_READ;
--
-- return e;
--
-- default:
-- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_???\n");
-- e->type = GG_EVENT_DCC_ERROR;
-- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
--
-- return e;
-- }
-- }
--
-- return e;
--}
--
--/**
-- * Zwalnia zasoby używane przez połączenie bezpośrednie.
-- *
-- * \param d Struktura połączenia
-- *
-- * \ingroup dcc6
-- */
--void gg_dcc_free(struct gg_dcc *d)
--{
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_free(%p);\n", d);
--
-- if (!d)
-- return;
--
-- if (d->fd != -1)
-- close(d->fd);
--
-- free(d->chunk_buf);
-- free(d);
--}
--
--/*
-- * Local variables:
-- * c-indentation-style: k&r
-- * c-basic-offset: 8
-- * indent-tabs-mode: notnil
-- * End:
-- *
-- * vim: shiftwidth=8:
-- */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/debug.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/debug.c
---- pidgin-2.10.7/libpurple/protocols/gg/lib/debug.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/debug.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,364 +0,0 @@
--/*
-- * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl>
-- * Robert J. Woźny <speedy@ziew.org>
-- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
-- * Tomasz Chiliński <chilek@chilan.com>
-- * Adam Wysocki <gophi@ekg.chmurka.net>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--/**
-- * \file debug.c
-- *
-- * \brief Funkcje odpluskwiania
-- */
--#include <sys/types.h>
--#include <errno.h>
--#include <stdarg.h>
--#include <stdio.h>
--#include <string.h>
--
--#include "libgadu.h"
--#include "libgadu-debug.h"
--
--/**
-- * Poziom rejestracji informacji odpluskwiajÄ…cych. Zmienna jest maskÄ… bitowÄ…
-- * składającą się ze stałych \c GG_DEBUG_...
-- *
-- * \ingroup debug
-- */
--int gg_debug_level = 0;
--
--/**
-- * Funkcja, do której są przekazywane informacje odpluskwiające. Jeśli zarówno
-- * ten \c gg_debug_handler, jak i \c gg_debug_handler_session, są równe
-- * \c NULL, informacje są wysyłane do standardowego wyjścia błędu (\c stderr).
-- *
-- * \param level Poziom rejestracji
-- * \param format Format wiadomości (zgodny z \c printf)
-- * \param ap Lista argumentów (zgodna z \c printf)
-- *
-- * \note Funkcja jest przesłaniana przez \c gg_debug_handler_session.
-- *
-- * \ingroup debug
-- */
--void (*gg_debug_handler)(int level, const char *format, va_list ap) = NULL;
--
--/**
-- * Funkcja, do której są przekazywane informacje odpluskwiające. Jeśli zarówno
-- * ten \c gg_debug_handler, jak i \c gg_debug_handler_session, są równe
-- * \c NULL, informacje są wysyłane do standardowego wyjścia błędu.
-- *
-- * \param sess Sesja której dotyczy informacja lub \c NULL
-- * \param level Poziom rejestracji
-- * \param format Format wiadomości (zgodny z \c printf)
-- * \param ap Lista argumentów (zgodna z \c printf)
-- *
-- * \note Funkcja przesłania przez \c gg_debug_handler_session.
-- *
-- * \ingroup debug
-- */
--void (*gg_debug_handler_session)(struct gg_session *sess, int level, const char *format, va_list ap) = NULL;
--
--/**
-- * Plik, do którego będą przekazywane informacje odpluskwiania.
-- *
-- * Funkcja \c gg_debug() i pochodne mogą być przechwytywane przez aplikację
-- * korzystającą z biblioteki, by wyświetlić je na żądanie użytkownika lub
-- * zapisać do późniejszej analizy. Jeśli nie określono pliku, wybrane
-- * informacje będą wysyłane do standardowego wyjścia błędu (\c stderr).
-- *
-- * \ingroup debug
-- */
--FILE *gg_debug_file = NULL;
--
--#ifndef GG_DEBUG_DISABLE
--
--/**
-- * \internal Przekazuje informacje odpluskwiania do odpowiedniej funkcji.
-- *
-- * Jeśli aplikacja ustawiła odpowiednią funkcję obsługi w
-- * \c gg_debug_handler_session lub \c gg_debug_handler, jest ona wywoływana.
-- * W przeciwnym wypadku wynik jest wysyłany do standardowego wyjścia błędu.
-- *
-- * \param sess Struktura sesji (może być \c NULL)
-- * \param level Poziom informacji
-- * \param format Format wiadomości (zgodny z \c printf)
-- * \param ap Lista argumentów (zgodna z \c printf)
-- */
--void gg_debug_common(struct gg_session *sess, int level, const char *format, va_list ap)
--{
-- if (gg_debug_handler_session != NULL)
-- (*gg_debug_handler_session)(sess, level, format, ap);
-- else if (gg_debug_handler != NULL)
-- (*gg_debug_handler)(level, format, ap);
-- else if ((gg_debug_level & level) != 0)
-- vfprintf((gg_debug_file) ? gg_debug_file : stderr, format, ap);
--}
--
--
--/**
-- * \internal Przekazuje informacjÄ™ odpluskawiania.
-- *
-- * \param level Poziom wiadomości
-- * \param format Format wiadomości (zgodny z \c printf)
-- *
-- * \ingroup debug
-- */
--void gg_debug(int level, const char *format, ...)
--{
-- va_list ap;
-- int old_errno = errno;
--
-- va_start(ap, format);
-- gg_debug_common(NULL, level, format, ap);
-- va_end(ap);
-- errno = old_errno;
--}
--
--/**
-- * \internal Przekazuje informacjÄ™ odpluskwiania zwiÄ…zanÄ… z sesjÄ….
-- *
-- * \param gs Struktura sesji
-- * \param level Poziom wiadomości
-- * \param format Format wiadomości (zgodny z \c printf)
-- *
-- * \ingroup debug
-- */
--void gg_debug_session(struct gg_session *gs, int level, const char *format, ...)
--{
-- va_list ap;
-- int old_errno = errno;
--
-- va_start(ap, format);
-- gg_debug_common(gs, level, format, ap);
-- va_end(ap);
-- errno = old_errno;
--}
--
--/**
-- * \internal Przekazuje zrzut bufora do odpluskwiania.
-- *
-- * \param gs Struktura sesji
-- * \param level Poziom wiadomości
-- * \param buf Bufor danych
-- * \param len Długość bufora danych
-- *
-- * \ingroup debug
-- */
--void gg_debug_dump(struct gg_session *gs, int level, const char *buf, size_t len)
--{
-- char line[80];
-- int i, j;
--
-- for (i = 0; i < len; i += 16) {
-- int ofs;
--
-- sprintf(line, "%.4x: ", i);
-- ofs = 6;
--
-- for (j = 0; j < 16; j++) {
-- if (i + j < len)
-- sprintf(line + ofs, " %02x", (unsigned char) buf[i + j]);
-- else
-- sprintf(line + ofs, " ");
--
-- ofs += 3;
-- }
--
-- sprintf(line + ofs, " ");
-- ofs += 2;
--
-- for (j = 0; j < 16; j++) {
-- unsigned char ch;
--
-- if (i + j < len) {
-- ch = buf[i + j];
--
-- if (ch < 32 || ch > 126)
-- ch = '.';
-- } else {
-- ch = ' ';
-- }
--
-- line[ofs++] = ch;
-- }
--
-- line[ofs++] = '\n';
-- line[ofs++] = 0;
--
-- gg_debug_session(gs, level, "%s", line);
-- }
--}
--
--/**
-- * \internal Zwraca ciÄ…g z nazwÄ… podanego stanu sesji.
-- *
-- * \param state Stan sesji.
-- *
-- * \return CiÄ…g z nazwÄ… stanu
-- *
-- * \ingroup debug
-- */
--const char *gg_debug_state(enum gg_state_t state)
--{
-- switch (state) {
--#define GG_DEBUG_STATE(x) case x: return #x;
-- GG_DEBUG_STATE(GG_STATE_IDLE)
-- GG_DEBUG_STATE(GG_STATE_RESOLVING)
-- GG_DEBUG_STATE(GG_STATE_CONNECTING)
-- GG_DEBUG_STATE(GG_STATE_READING_DATA)
-- GG_DEBUG_STATE(GG_STATE_ERROR)
-- GG_DEBUG_STATE(GG_STATE_CONNECTING_HUB)
-- GG_DEBUG_STATE(GG_STATE_CONNECTING_GG)
-- GG_DEBUG_STATE(GG_STATE_READING_KEY)
-- GG_DEBUG_STATE(GG_STATE_READING_REPLY)
-- GG_DEBUG_STATE(GG_STATE_CONNECTED)
-- GG_DEBUG_STATE(GG_STATE_SENDING_QUERY)
-- GG_DEBUG_STATE(GG_STATE_READING_HEADER)
-- GG_DEBUG_STATE(GG_STATE_PARSING)
-- GG_DEBUG_STATE(GG_STATE_DONE)
-- GG_DEBUG_STATE(GG_STATE_LISTENING)
-- GG_DEBUG_STATE(GG_STATE_READING_UIN_1)
-- GG_DEBUG_STATE(GG_STATE_READING_UIN_2)
-- GG_DEBUG_STATE(GG_STATE_SENDING_ACK)
-- GG_DEBUG_STATE(GG_STATE_READING_ACK)
-- GG_DEBUG_STATE(GG_STATE_READING_REQUEST)
-- GG_DEBUG_STATE(GG_STATE_SENDING_REQUEST)
-- GG_DEBUG_STATE(GG_STATE_SENDING_FILE_INFO)
-- GG_DEBUG_STATE(GG_STATE_READING_PRE_FILE_INFO)
-- GG_DEBUG_STATE(GG_STATE_READING_FILE_INFO)
-- GG_DEBUG_STATE(GG_STATE_SENDING_FILE_ACK)
-- GG_DEBUG_STATE(GG_STATE_READING_FILE_ACK)
-- GG_DEBUG_STATE(GG_STATE_SENDING_FILE_HEADER)
-- GG_DEBUG_STATE(GG_STATE_READING_FILE_HEADER)
-- GG_DEBUG_STATE(GG_STATE_GETTING_FILE)
-- GG_DEBUG_STATE(GG_STATE_SENDING_FILE)
-- GG_DEBUG_STATE(GG_STATE_READING_VOICE_ACK)
-- GG_DEBUG_STATE(GG_STATE_READING_VOICE_HEADER)
-- GG_DEBUG_STATE(GG_STATE_READING_VOICE_SIZE)
-- GG_DEBUG_STATE(GG_STATE_READING_VOICE_DATA)
-- GG_DEBUG_STATE(GG_STATE_SENDING_VOICE_ACK)
-- GG_DEBUG_STATE(GG_STATE_SENDING_VOICE_REQUEST)
-- GG_DEBUG_STATE(GG_STATE_READING_TYPE)
-- GG_DEBUG_STATE(GG_STATE_TLS_NEGOTIATION)
-- GG_DEBUG_STATE(GG_STATE_REQUESTING_ID)
-- GG_DEBUG_STATE(GG_STATE_WAITING_FOR_ACCEPT)
-- GG_DEBUG_STATE(GG_STATE_WAITING_FOR_INFO)
-- GG_DEBUG_STATE(GG_STATE_READING_ID)
-- GG_DEBUG_STATE(GG_STATE_SENDING_ID)
-- GG_DEBUG_STATE(GG_STATE_RESOLVING_GG)
-- GG_DEBUG_STATE(GG_STATE_RESOLVING_RELAY)
-- GG_DEBUG_STATE(GG_STATE_CONNECTING_RELAY)
-- GG_DEBUG_STATE(GG_STATE_READING_RELAY)
-- GG_DEBUG_STATE(GG_STATE_DISCONNECTING)
--#undef GG_DEBUG_STATE
--
-- /* Celowo nie ma default, żeby kompilator wyłapał brakujące stany */
--
-- }
--
-- return NULL;
--}
--
--/**
-- * \internal Zwraca ciÄ…g z nazwÄ… podanego zdarzenia.
-- *
-- * \param event Zdarzenie.
-- *
-- * \return CiÄ…g z nazwÄ… zdarzenia
-- *
-- * \ingroup debug
-- */
--const char *gg_debug_event(enum gg_event_t event)
--{
-- switch (event) {
--#define GG_DEBUG_EVENT(x) case x: return #x;
-- GG_DEBUG_EVENT(GG_EVENT_NONE)
-- GG_DEBUG_EVENT(GG_EVENT_MSG)
-- GG_DEBUG_EVENT(GG_EVENT_NOTIFY)
-- GG_DEBUG_EVENT(GG_EVENT_NOTIFY_DESCR)
-- GG_DEBUG_EVENT(GG_EVENT_STATUS)
-- GG_DEBUG_EVENT(GG_EVENT_ACK)
-- GG_DEBUG_EVENT(GG_EVENT_PONG)
-- GG_DEBUG_EVENT(GG_EVENT_CONN_FAILED)
-- GG_DEBUG_EVENT(GG_EVENT_CONN_SUCCESS)
-- GG_DEBUG_EVENT(GG_EVENT_DISCONNECT)
-- GG_DEBUG_EVENT(GG_EVENT_DCC_NEW)
-- GG_DEBUG_EVENT(GG_EVENT_DCC_ERROR)
-- GG_DEBUG_EVENT(GG_EVENT_DCC_DONE)
-- GG_DEBUG_EVENT(GG_EVENT_DCC_CLIENT_ACCEPT)
-- GG_DEBUG_EVENT(GG_EVENT_DCC_CALLBACK)
-- GG_DEBUG_EVENT(GG_EVENT_DCC_NEED_FILE_INFO)
-- GG_DEBUG_EVENT(GG_EVENT_DCC_NEED_FILE_ACK)
-- GG_DEBUG_EVENT(GG_EVENT_DCC_NEED_VOICE_ACK)
-- GG_DEBUG_EVENT(GG_EVENT_DCC_VOICE_DATA)
-- GG_DEBUG_EVENT(GG_EVENT_PUBDIR50_SEARCH_REPLY)
-- GG_DEBUG_EVENT(GG_EVENT_PUBDIR50_READ)
-- GG_DEBUG_EVENT(GG_EVENT_PUBDIR50_WRITE)
-- GG_DEBUG_EVENT(GG_EVENT_STATUS60)
-- GG_DEBUG_EVENT(GG_EVENT_NOTIFY60)
-- GG_DEBUG_EVENT(GG_EVENT_USERLIST)
-- GG_DEBUG_EVENT(GG_EVENT_IMAGE_REQUEST)
-- GG_DEBUG_EVENT(GG_EVENT_IMAGE_REPLY)
-- GG_DEBUG_EVENT(GG_EVENT_DCC_ACK)
-- GG_DEBUG_EVENT(GG_EVENT_DCC7_NEW)
-- GG_DEBUG_EVENT(GG_EVENT_DCC7_ACCEPT)
-- GG_DEBUG_EVENT(GG_EVENT_DCC7_REJECT)
-- GG_DEBUG_EVENT(GG_EVENT_DCC7_CONNECTED)
-- GG_DEBUG_EVENT(GG_EVENT_DCC7_ERROR)
-- GG_DEBUG_EVENT(GG_EVENT_DCC7_DONE)
-- GG_DEBUG_EVENT(GG_EVENT_DCC7_PENDING)
-- GG_DEBUG_EVENT(GG_EVENT_XML_EVENT)
-- GG_DEBUG_EVENT(GG_EVENT_DISCONNECT_ACK)
-- GG_DEBUG_EVENT(GG_EVENT_TYPING_NOTIFICATION)
-- GG_DEBUG_EVENT(GG_EVENT_USER_DATA)
-- GG_DEBUG_EVENT(GG_EVENT_MULTILOGON_MSG)
-- GG_DEBUG_EVENT(GG_EVENT_MULTILOGON_INFO)
-- GG_DEBUG_EVENT(GG_EVENT_USERLIST100_VERSION)
-- GG_DEBUG_EVENT(GG_EVENT_USERLIST100_REPLY)
--#undef GG_DEBUG_EVENT
--
-- /* Celowo nie ma default, żeby kompilator wyłapał brakujące zdarzenia */
--
-- }
--
-- return NULL;
--}
--
--#else
--
--#undef gg_debug_common
--void gg_debug_common(struct gg_session *sess, int level, const char *format, va_list ap)
--{
--}
--
--#undef gg_debug
--void gg_debug(int level, const char *format, ...)
--{
--}
--
--#undef gg_debug_session
--void gg_debug_session(struct gg_session *gs, int level, const char *format, ...)
--{
--}
--
--#undef gg_debug_dump
--void gg_debug_dump(struct gg_session *gs, int level, const char *buf, size_t len)
--{
--}
--
--#endif
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/deflate.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/deflate.c
---- pidgin-2.10.7/libpurple/protocols/gg/lib/deflate.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/deflate.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,219 +0,0 @@
--/* $Id$ */
--
--/*
-- * (C) Copyright 2011 Bartosz Brachaczek <b.brachaczek@gmail.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--/**
-- * \file deflate.c
-- *
-- * \brief Funkcje kompresji Deflate
-- */
--
--#include <stdlib.h>
--#include <string.h>
--
--#include "libgadu.h"
--#include "deflate.h"
--
--#ifdef GG_CONFIG_HAVE_ZLIB
--#include <zlib.h>
--#endif
--
--/**
-- * \internal Kompresuje dane wejściowe algorytmem Deflate z najwyższym
-- * stopniem kompresji, tak samo jak oryginalny klient.
-- *
-- * Wynik funkcji należy zwolnić za pomocą \c free.
-- *
-- * \param in Ciąg znaków do skompresowania, zakończony \c \\0
-- * \param out_lenp Wskaźnik na zmienną, do której zostanie zapisana
-- * długość bufora wynikowego
-- *
-- * \return Skompresowany ciąg znaków lub \c NULL w przypadku niepowodzenia.
-- */
--unsigned char *gg_deflate(const char *in, size_t *out_lenp)
--{
--#ifdef GG_CONFIG_HAVE_ZLIB
-- int ret;
-- z_stream strm;
-- unsigned char *out, *out2;
-- size_t out_len;
--
-- if (in == NULL || out_lenp == NULL)
-- return NULL;
--
-- strm.zalloc = Z_NULL;
-- strm.zfree = Z_NULL;
-- strm.opaque = Z_NULL;
-- strm.avail_in = strlen(in);
-- strm.next_in = (unsigned char*) in;
--
-- ret = deflateInit(&strm, Z_BEST_COMPRESSION);
-- if (ret != Z_OK) {
-- gg_debug(GG_DEBUG_MISC, "// gg_deflate() deflateInit() failed (%d)\n", ret);
-- return NULL;
-- }
--
-- out_len = deflateBound(&strm, strm.avail_in);
-- out = malloc(out_len);
--
-- if (out == NULL) {
-- gg_debug(GG_DEBUG_MISC, "// gg_deflate() not enough memory for output data (%d)\n", out_len);
-- goto fail;
-- }
--
-- strm.avail_out = out_len;
-- strm.next_out = out;
--
-- for (;;) {
-- ret = deflate(&strm, Z_FINISH);
--
-- if (ret == Z_STREAM_END)
-- break;
--
-- /* raczej nie powinno się zdarzyć przy Z_FINISH i out_len == deflateBound(),
-- * ale dokumentacja zlib nie wyklucza takiej możliwości */
-- if (ret == Z_OK) {
-- out_len *= 2;
-- out2 = realloc(out, out_len);
--
-- if (out2 == NULL) {
-- gg_debug(GG_DEBUG_MISC, "// gg_deflate() not enough memory for output data (%d)\n", out_len);
-- goto fail;
-- }
--
-- out = out2;
--
-- strm.avail_out = out_len / 2;
-- strm.next_out = out + out_len / 2;
-- } else {
-- gg_debug(GG_DEBUG_MISC, "// gg_deflate() deflate() failed (ret=%d, msg=%s)\n", ret, strm.msg != NULL ? strm.msg : "no error message provided");
-- goto fail;
-- }
-- }
--
-- out_len = strm.total_out;
-- out2 = realloc(out, out_len);
--
-- if (out2 == NULL) {
-- gg_debug(GG_DEBUG_MISC, "// gg_deflate() not enough memory for output data (%d)\n", out_len);
-- goto fail;
-- }
--
-- *out_lenp = out_len;
-- deflateEnd(&strm);
--
-- return out2;
--
--fail:
-- *out_lenp = 0;
-- deflateEnd(&strm);
-- free(out);
--#endif
-- return NULL;
--}
--
--/**
-- * \internal Dekompresuje dane wejściowe w formacie Deflate.
-- *
-- * Wynik funkcji należy zwolnić za pomocą \c free.
-- *
-- * \param in Bufor danych skompresowanych algorytmem Deflate
-- * \param length Długość bufora wejściowego
-- *
-- * \note Dokleja \c \\0 na końcu bufora wynikowego.
-- *
-- * \return Zdekompresowany ciąg znaków, zakończony \c \\0,
-- * lub \c NULL w przypadku niepowodzenia.
-- */
--char *gg_inflate(const unsigned char *in, size_t length)
--{
--#ifdef GG_CONFIG_HAVE_ZLIB
-- int ret;
-- z_stream strm;
-- char *out = NULL, *out2;
-- size_t out_len = 1024;
-- int first = 1;
--
-- if (in == NULL)
-- return NULL;
--
-- strm.zalloc = Z_NULL;
-- strm.zfree = Z_NULL;
-- strm.opaque = Z_NULL;
-- strm.avail_in = length;
-- strm.next_in = (unsigned char*) in;
--
-- ret = inflateInit(&strm);
-- if (ret != Z_OK) {
-- gg_debug(GG_DEBUG_MISC, "// gg_inflate() inflateInit() failed (%d)\n", ret);
-- return NULL;
-- }
--
-- do {
-- out_len *= 2;
-- out2 = realloc(out, out_len);
--
-- if (out2 == NULL) {
-- gg_debug(GG_DEBUG_MISC, "// gg_inflate() not enough memory for output data (%d)\n", out_len);
-- goto fail;
-- }
--
-- out = out2;
--
-- if (first) {
-- strm.avail_out = out_len;
-- strm.next_out = (unsigned char*) out;
-- } else {
-- strm.avail_out = out_len / 2;
-- strm.next_out = (unsigned char*) out + out_len / 2;
-- }
--
-- ret = inflate(&strm, Z_NO_FLUSH);
--
-- if (ret != Z_OK && ret != Z_STREAM_END) {
-- gg_debug(GG_DEBUG_MISC, "// gg_inflate() inflate() failed (ret=%d, msg=%s)\n", ret, strm.msg != NULL ? strm.msg : "no error message provided");
-- goto fail;
-- }
--
-- first = 0;
-- } while (ret != Z_STREAM_END);
--
-- /* rezerwujemy ostatni znak na NULL-a */
-- out_len = strm.total_out + 1;
-- out2 = realloc(out, out_len);
--
-- if (out2 == NULL) {
-- gg_debug(GG_DEBUG_MISC, "// gg_inflate() not enough memory for output data (%d)\n", out_len);
-- goto fail;
-- }
--
-- out = out2;
-- out[out_len - 1] = '\0';
--
-- inflateEnd(&strm);
--
-- return out;
--
--fail:
-- inflateEnd(&strm);
-- free(out);
--#endif
-- return NULL;
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/deflate.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/deflate.h
---- pidgin-2.10.7/libpurple/protocols/gg/lib/deflate.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/deflate.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,29 +0,0 @@
--/* $Id$ */
--
--/*
-- * (C) Copyright 2009 Jakub Zawadzki <darkjames@darkjames.ath.cx>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--#ifndef LIBGADU_DEFLATE_H
--#define LIBGADU_DEFLATE_H
--
--#include "libgadu.h"
--
--unsigned char *gg_deflate(const char *in, size_t *out_lenp);
--char *gg_inflate(const unsigned char *in, size_t length);
--
--#endif /* LIBGADU_DEFLATE_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/encoding.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/encoding.c
---- pidgin-2.10.7/libpurple/protocols/gg/lib/encoding.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/encoding.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,275 +0,0 @@
--/*
-- * (C) Copyright 2008-2009 Jakub Zawadzki <darkjames@darkjames.ath.cx>
-- * Wojtek Kaniewski <wojtekka@irc.pl>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--#include <stdlib.h>
--#include <string.h>
--#include <errno.h>
--
--#include "libgadu.h"
--#include "encoding.h"
--
--/**
-- * \file encoding.c
-- *
-- * \brief Funkcje konwersji kodowania tekstu
-- */
--
--/**
-- * \internal Tablica konwersji CP1250 na Unikod.
-- */
--static const uint16_t table_cp1250[] =
--{
-- 0x20ac, '?', 0x201a, '?', 0x201e, 0x2026, 0x2020, 0x2021,
-- '?', 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179,
-- '?', 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
-- '?', 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a,
-- 0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7,
-- 0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b,
-- 0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
-- 0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c,
-- 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,
-- 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
-- 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,
-- 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
-- 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,
-- 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
-- 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,
-- 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9,
--};
--
--/**
-- * \internal Zamienia tekst kodowany CP1250 na UTF-8.
-- *
-- * \param src Tekst źródłowy w CP1250.
-- * \param src_length Długość ciągu źródłowego (nigdy ujemna).
-- * \param dst_length Długość ciągu docelowego (jeśli -1, nieograniczona).
-- *
-- * \return Zaalokowany bufor z tekstem w UTF-8.
-- */
--static char *gg_encoding_convert_cp1250_utf8(const char *src, int src_length, int dst_length)
--{
-- int i, j, len;
-- char *result = NULL;
--
-- for (i = 0, len = 0; (src[i] != 0) && (i < src_length); i++) {
-- uint16_t uc;
--
-- if ((unsigned char) src[i] < 0x80)
-- uc = (unsigned char) src[i];
-- else
-- uc = table_cp1250[(unsigned char) src[i] - 128];
--
-- if (uc < 0x80)
-- len += 1;
-- else if (uc < 0x800)
-- len += 2;
-- else
-- len += 3;
-- }
--
-- if ((dst_length != -1) && (len > dst_length))
-- len = dst_length;
--
-- result = malloc(len + 1);
--
-- if (result == NULL)
-- return NULL;
--
-- for (i = 0, j = 0; (src[i] != 0) && (i < src_length) && (j < len); i++) {
-- uint16_t uc;
--
-- if ((unsigned char) src[i] < 0x80)
-- uc = (unsigned char) src[i];
-- else
-- uc = table_cp1250[(unsigned char) src[i] - 128];
--
-- if (uc < 0x80)
-- result[j++] = uc;
-- else if (uc < 0x800) {
-- if (j + 1 > len)
-- break;
-- result[j++] = 0xc0 | ((uc >> 6) & 0x1f);
-- result[j++] = 0x80 | (uc & 0x3f);
-- } else {
-- if (j + 2 > len)
-- break;
-- result[j++] = 0xe0 | ((uc >> 12) & 0x1f);
-- result[j++] = 0x80 | ((uc >> 6) & 0x3f);
-- result[j++] = 0x80 | (uc & 0x3f);
-- }
-- }
--
-- result[j] = 0;
--
-- return result;
--}
--
--/**
-- * \internal Zamienia tekst kodowany UTF-8 na CP1250.
-- *
-- * \param src Tekst źródłowy w UTF-8.
-- * \param src_length Długość ciągu źródłowego (nigdy ujemna).
-- * \param dst_length Długość ciągu docelowego (jeśli -1, nieograniczona).
-- *
-- * \return Zaalokowany bufor z tekstem w CP1250.
-- */
--static char *gg_encoding_convert_utf8_cp1250(const char *src, int src_length, int dst_length)
--{
-- char *result;
-- int i, j, len, uc_left = 0;
-- uint32_t uc = 0, uc_min = 0;
--
-- for (i = 0, len = 0; (src[i] != 0) && (i < src_length); i++) {
-- if ((src[i] & 0xc0) == 0xc0) {
-- len++;
-- } else if ((src[i] & 0x80) == 0x00) {
-- len++;
-- }
-- }
--
-- if ((dst_length != -1) && (len > dst_length))
-- len = dst_length;
--
-- result = malloc(len + 1);
--
-- if (result == NULL)
-- return NULL;
--
-- for (i = 0, j = 0; (src[i] != 0) && (i < src_length) && (j < len); i++) {
-- if ((unsigned char) src[i] >= 0xf5) {
-- if (uc_left != 0)
-- result[j++] = '?';
-- /* Restricted sequences */
-- result[j++] = '?';
-- uc_left = 0;
-- } else if ((src[i] & 0xf8) == 0xf0) {
-- if (uc_left != 0)
-- result[j++] = '?';
-- uc = src[i] & 0x07;
-- uc_left = 3;
-- uc_min = 0x10000;
-- } else if ((src[i] & 0xf0) == 0xe0) {
-- if (uc_left != 0)
-- result[j++] = '?';
-- uc = src[i] & 0x0f;
-- uc_left = 2;
-- uc_min = 0x800;
-- } else if ((src[i] & 0xe0) == 0xc0) {
-- if (uc_left != 0)
-- result[j++] = '?';
-- uc = src[i] & 0x1f;
-- uc_left = 1;
-- uc_min = 0x80;
-- } else if ((src[i] & 0xc0) == 0x80) {
-- if (uc_left > 0) {
-- uc <<= 6;
-- uc |= src[i] & 0x3f;
-- uc_left--;
--
-- if (uc_left == 0) {
-- int valid = 0;
-- int k;
--
-- if (uc >= uc_min) {
-- for (k = 0; k < 128; k++) {
-- if (uc == table_cp1250[k]) {
-- result[j++] = k + 128;
-- valid = 1;
-- break;
-- }
-- }
-- }
--
-- if (!valid && uc != 0xfeff) /* Byte Order Mark */
-- result[j++] = '?';
-- }
-- }
-- } else {
-- if (uc_left != 0) {
-- result[j++] = '?';
-- uc_left = 0;
-- }
-- result[j++] = src[i];
-- }
-- }
--
-- if ((uc_left != 0) && (src[i] == 0))
-- result[j++] = '?';
--
-- result[j] = 0;
--
-- return result;
--}
--
--/**
-- * \internal Zamienia kodowanie tekstu.
-- *
-- * \param src Tekst źródłowy.
-- * \param src_encoding Kodowanie tekstu źródłowego.
-- * \param dst_encoding Kodowanie tekstu docelowego.
-- * \param src_length Długość ciągu źródłowego w bajtach (nigdy ujemna).
-- * \param dst_length Długość ciągu docelowego w bajtach (jeśli -1, nieograniczona).
-- *
-- * \return Zaalokowany bufor z tekstem w kodowaniu docelowym.
-- */
--char *gg_encoding_convert(const char *src, gg_encoding_t src_encoding, gg_encoding_t dst_encoding, int src_length, int dst_length)
--{
-- char *result;
--
-- if (src == NULL) {
-- errno = EINVAL;
-- return NULL;
-- }
--
-- // specjalny przypadek obsługiwany ekspresowo
-- if ((dst_encoding == src_encoding) && (dst_length == -1) && (src_length == -1))
-- return strdup(src);
--
-- if (src_length == -1)
-- src_length = strlen(src);
--
-- if (dst_encoding == src_encoding) {
-- int len;
--
-- if (dst_length == -1)
-- len = src_length;
-- else
-- len = (src_length < dst_length) ? src_length : dst_length;
--
-- result = malloc(len + 1);
--
-- if (result == NULL)
-- return NULL;
--
-- strncpy(result, src, len);
-- result[len] = 0;
--
-- return result;
-- }
--
-- if (dst_encoding == GG_ENCODING_CP1250 && src_encoding == GG_ENCODING_UTF8)
-- return gg_encoding_convert_utf8_cp1250(src, src_length, dst_length);
--
-- if (dst_encoding == GG_ENCODING_UTF8 && src_encoding == GG_ENCODING_CP1250)
-- return gg_encoding_convert_cp1250_utf8(src, src_length, dst_length);
--
-- errno = EINVAL;
-- return NULL;
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/encoding.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/encoding.h
---- pidgin-2.10.7/libpurple/protocols/gg/lib/encoding.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/encoding.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,27 +0,0 @@
--/*
-- * (C) Copyright 2008-2009 Jakub Zawadzki <darkjames@darkjames.ath.cx>
-- * Wojtek Kaniewski <wojtekka@irc.pl>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--#ifndef LIBGADU_ENCODING_H
--#define LIBGADU_ENCODING_H
--
--#include "libgadu.h"
--
--char *gg_encoding_convert(const char *src, gg_encoding_t src_encoding, gg_encoding_t dst_encoding, int src_length, int dst_length);
--
--#endif /* LIBGADU_SESSION_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/events.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/events.c
---- pidgin-2.10.7/libpurple/protocols/gg/lib/events.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/events.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1027 +0,0 @@
--/* $Id: events.c 1105 2011-05-25 21:34:50Z wojtekka $ */
--
--/*
-- * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl>
-- * Robert J. Woźny <speedy@ziew.org>
-- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
-- * Adam Wysocki <gophi@ekg.chmurka.net>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--/**
-- * \file events.c
-- *
-- * \brief Obsługa zdarzeń
-- */
--
--#include <sys/types.h>
--#ifndef _WIN32
--# include <sys/ioctl.h>
--# include <sys/socket.h>
--# include <netinet/in.h>
--# include <arpa/inet.h>
--#endif
--#include <ctype.h>
--
--#include "compat.h"
--#include "libgadu.h"
--#include "libgadu-config.h"
--#include "protocol.h"
--#include "libgadu-internal.h"
--#include "encoding.h"
--#include "libgadu-debug.h"
--#include "session.h"
--
--#include <errno.h>
--#include <stdio.h>
--#include <string.h>
--#include <stdlib.h>
--#include <time.h>
--#include <unistd.h>
--#include <ctype.h>
--#ifdef GG_CONFIG_HAVE_GNUTLS
--# include <gnutls/gnutls.h>
--# include <gnutls/x509.h>
--#endif
--#ifdef GG_CONFIG_HAVE_OPENSSL
--# include <openssl/err.h>
--# include <openssl/x509.h>
--#endif
--
--/**
-- * Zwalnia pamięć zajmowaną przez informację o zdarzeniu.
-- *
-- * Funkcję należy wywoływać za każdym razem gdy funkcja biblioteki zwróci
-- * strukturÄ™ \c gg_event.
-- *
-- * \param e Struktura zdarzenia
-- *
-- * \ingroup events
-- */
--void gg_event_free(struct gg_event *e)
--{
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_event_free(%p);\n", e);
--
-- if (!e)
-- return;
--
-- switch (e->type) {
-- case GG_EVENT_MSG:
-- case GG_EVENT_MULTILOGON_MSG:
-- free(e->event.msg.message);
-- free(e->event.msg.formats);
-- free(e->event.msg.recipients);
-- free(e->event.msg.xhtml_message);
-- break;
--
-- case GG_EVENT_NOTIFY:
-- free(e->event.notify);
-- break;
--
-- case GG_EVENT_NOTIFY60:
-- {
-- int i;
--
-- for (i = 0; e->event.notify60[i].uin; i++)
-- free(e->event.notify60[i].descr);
--
-- free(e->event.notify60);
--
-- break;
-- }
--
-- case GG_EVENT_STATUS60:
-- free(e->event.status60.descr);
-- break;
--
-- case GG_EVENT_STATUS:
-- free(e->event.status.descr);
-- break;
--
-- case GG_EVENT_NOTIFY_DESCR:
-- free(e->event.notify_descr.notify);
-- free(e->event.notify_descr.descr);
-- break;
--
-- case GG_EVENT_DCC_VOICE_DATA:
-- free(e->event.dcc_voice_data.data);
-- break;
--
-- case GG_EVENT_PUBDIR50_SEARCH_REPLY:
-- case GG_EVENT_PUBDIR50_READ:
-- case GG_EVENT_PUBDIR50_WRITE:
-- gg_pubdir50_free(e->event.pubdir50);
-- break;
--
-- case GG_EVENT_USERLIST:
-- free(e->event.userlist.reply);
-- break;
--
-- case GG_EVENT_IMAGE_REPLY:
-- free(e->event.image_reply.filename);
-- free(e->event.image_reply.image);
-- break;
--
-- case GG_EVENT_XML_EVENT:
-- free(e->event.xml_event.data);
-- break;
--
-- case GG_EVENT_USER_DATA:
-- {
-- int i, j;
--
-- for (i = 0; i < e->event.user_data.user_count; i++) {
-- for (j = 0; j < e->event.user_data.users[i].attr_count; j++) {
-- free(e->event.user_data.users[i].attrs[j].key);
-- free(e->event.user_data.users[i].attrs[j].value);
-- }
--
-- free(e->event.user_data.users[i].attrs);
-- }
--
-- free(e->event.user_data.users);
--
-- break;
-- }
--
-- case GG_EVENT_MULTILOGON_INFO:
-- {
-- int i;
--
-- for (i = 0; i < e->event.multilogon_info.count; i++)
-- free(e->event.multilogon_info.sessions[i].name);
--
-- free(e->event.multilogon_info.sessions);
--
-- break;
-- }
--
-- case GG_EVENT_USERLIST100_REPLY:
-- free(e->event.userlist100_reply.reply);
-- break;
-- }
--
-- free(e);
--}
--
--/** \cond internal */
--
--/**
-- * \internal Usuwa obrazek z kolejki do wysłania.
-- *
-- * \param s Struktura sesji
-- * \param q Struktura obrazka
-- * \param freeq Flaga zwolnienia elementu kolejki
-- *
-- * \return 0 jeśli się powiodło, -1 jeśli wystąpił błąd
-- */
--int gg_image_queue_remove(struct gg_session *s, struct gg_image_queue *q, int freeq)
--{
-- if (!s || !q) {
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (s->images == q)
-- s->images = q->next;
-- else {
-- struct gg_image_queue *qq;
--
-- for (qq = s->images; qq; qq = qq->next) {
-- if (qq->next == q) {
-- qq->next = q->next;
-- break;
-- }
-- }
-- }
--
-- if (freeq) {
-- free(q->image);
-- free(q->filename);
-- free(q);
-- }
--
-- return 0;
--}
--
--/** \endcond */
--
--/**
-- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze sesji.
-- *
-- * Funkcja zwraca strukturę zdarzenia \c gg_event. Jeśli rodzaj zdarzenia
-- * to \c GG_EVENT_NONE, nie wydarzyło się jeszcze nic wartego odnotowania.
-- * Strukturę zdarzenia należy zwolnić funkcja \c gg_event_free().
-- *
-- * \param sess Struktura sesji
-- *
-- * \return Struktura zdarzenia lub \c NULL jeśli wystąpił błąd
-- *
-- * \ingroup events
-- */
--struct gg_event *gg_watch_fd(struct gg_session *sess)
--{
-- struct gg_event *e;
-- int res = 0;
-- int port = 0;
-- int errno2 = 0;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_watch_fd(%p);\n", sess);
--
-- if (!sess) {
-- errno = EFAULT;
-- return NULL;
-- }
--
-- if (!(e = (void*) calloc(1, sizeof(*e)))) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() not enough memory for event data\n");
-- return NULL;
-- }
--
-- e->type = GG_EVENT_NONE;
--
-- if (sess->send_buf && (sess->state == GG_STATE_READING_REPLY || sess->state == GG_STATE_CONNECTED)) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() sending %d bytes of queued data\n", sess->send_left);
--
-- res = write(sess->fd, sess->send_buf, sess->send_left);
--
-- if (res == -1 && errno != EAGAIN) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() write() failed (errno=%d, %s)\n", errno, strerror(errno));
--
-- if (sess->state == GG_STATE_READING_REPLY)
-- e->event.failure = GG_FAILURE_CONNECTING;
--
-- goto fail;
-- }
--
-- if (res == sess->send_left) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() sent all queued data\n");
-- free(sess->send_buf);
-- sess->send_buf = NULL;
-- sess->send_left = 0;
-- } else if (res > 0) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() sent %d bytes of queued data, %d bytes left\n", res, sess->send_left - res);
--
-- memmove(sess->send_buf, sess->send_buf + res, sess->send_left - res);
-- sess->send_left -= res;
-- }
--
-- res = 0;
-- }
--
-- switch (sess->state) {
-- case GG_STATE_RESOLVING:
-- {
-- struct in_addr addr;
-- int failed = 0;
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_RESOLVING\n");
--
-- if (read(sess->fd, &addr, sizeof(addr)) < (signed)sizeof(addr) || addr.s_addr == INADDR_NONE) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() resolving failed\n");
-- failed = 1;
-- errno2 = errno;
-- }
--
-- close(sess->fd);
-- sess->fd = -1;
--
-- sess->resolver_cleanup(&sess->resolver, 0);
--
-- if (failed) {
-- errno = errno2;
-- goto fail_proxy_hub;
-- }
--
-- /* jeśli jesteśmy w resolverze i mamy ustawiony port
-- * proxy, znaczy, że resolvowaliśmy proxy. zatem
-- * wpiszmy jego adres. */
-- if (sess->proxy_port)
-- sess->proxy_addr = addr.s_addr;
--
-- /* zapiszmy sobie adres huba i adres serwera (do
-- * bezpośredniego połączenia, jeśli hub leży)
-- * z resolvera. */
-- if (sess->proxy_addr && sess->proxy_port)
-- port = sess->proxy_port;
-- else {
-- sess->server_addr = sess->hub_addr = addr.s_addr;
-- port = GG_APPMSG_PORT;
-- }
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() resolved, connecting to %s:%d\n", inet_ntoa(addr), port);
--
-- /* łączymy się albo z hubem, albo z proxy, zależnie
-- * od tego, co resolvowaliśmy. */
-- if ((sess->fd = gg_connect(&addr, port, sess->async)) == -1) {
-- /* jeśli w trybie asynchronicznym gg_connect()
-- * zwróci błąd, nie ma sensu próbować dalej. */
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), critical\n", errno, strerror(errno));
-- goto fail_proxy_hub;
-- }
--
-- /* jeśli podano serwer i łączmy się przez proxy,
-- * jest to bezpośrednie połączenie, inaczej jest
-- * do huba. */
--
-- if (sess->proxy_addr && sess->proxy_port && sess->server_addr) {
-- sess->state = GG_STATE_CONNECTING_GG;
-- sess->soft_timeout = 1;
-- } else
-- sess->state = GG_STATE_CONNECTING_HUB;
--
-- sess->check = GG_CHECK_WRITE;
-- sess->timeout = GG_DEFAULT_TIMEOUT;
--
-- break;
-- }
--
-- case GG_STATE_CONNECTING_HUB:
-- {
-- char buf[1024], *client, *auth;
-- int res = 0;
-- socklen_t res_size = sizeof(res);
-- const char *host;
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_CONNECTING_HUB\n");
--
-- /* jeśli asynchroniczne, sprawdzamy, czy nie wystąpił
-- * przypadkiem jakiś błąd. */
-- if (sess->async && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection to %s failed (errno=%d, %s)\n", (sess->proxy_addr && sess->proxy_port) ? "proxy" : "hub", res, strerror(res));
-- goto fail_proxy_hub;
-- }
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connected to hub, sending query\n");
--
-- if (sess->client_version != NULL && isdigit(sess->client_version[0]))
-- client = gg_urlencode(sess->client_version);
-- else
-- client = gg_urlencode(GG_DEFAULT_CLIENT_VERSION);
--
-- if (client == NULL) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() out of memory for client version\n");
-- goto fail;
-- }
--
-- if (!gg_proxy_http_only && sess->proxy_addr && sess->proxy_port)
-- host = "http://" GG_APPMSG_HOST;
-- else
-- host = "";
--
-- auth = gg_proxy_auth();
--
--#if defined(GG_CONFIG_HAVE_GNUTLS) || defined(GG_CONFIG_HAVE_OPENSSL)
-- if (sess->ssl != NULL) {
-- snprintf(buf, sizeof(buf) - 1,
-- "GET %s/appsvc/appmsg_ver10.asp?fmnumber=%u&fmt=2&lastmsg=%d&version=%s&age=2&gender=1 HTTP/1.0\r\n"
-- "Connection: close\r\n"
-- "Host: " GG_APPMSG_HOST "\r\n"
-- "%s"
-- "\r\n", host, sess->uin, sess->last_sysmsg, client, (auth) ? auth : "");
-- } else
--#endif
-- {
-- snprintf(buf, sizeof(buf) - 1,
-- "GET %s/appsvc/appmsg_ver8.asp?fmnumber=%u&fmt=2&lastmsg=%d&version=%s HTTP/1.0\r\n"
-- "Host: " GG_APPMSG_HOST "\r\n"
-- "%s"
-- "\r\n", host, sess->uin, sess->last_sysmsg, client, (auth) ? auth : "");
-- }
--
-- free(auth);
-- free(client);
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "=> -----BEGIN-HTTP-QUERY-----\n%s\n=> -----END-HTTP-QUERY-----\n", buf);
--
-- /* zapytanie jest krótkie, więc zawsze zmieści się
-- * do bufora gniazda. jeśli write() zwróci mniej,
-- * stało się coś złego. */
-- if (write(sess->fd, buf, strlen(buf)) < (signed)strlen(buf)) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() sending query failed\n");
-- goto fail_proxy_hub;
-- }
--
-- sess->state = GG_STATE_READING_DATA;
-- sess->check = GG_CHECK_READ;
-- sess->timeout = GG_DEFAULT_TIMEOUT;
--
-- break;
-- }
--
-- case GG_STATE_READING_DATA:
-- {
-- char buf[1024], *tmp, *host;
-- int port = GG_DEFAULT_PORT;
-- struct in_addr addr;
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_READING_DATA\n");
--
-- /* czytamy liniÄ™ z gniazda i obcinamy \r\n. */
-- gg_read_line(sess->fd, buf, sizeof(buf) - 1);
-- gg_chomp(buf);
-- gg_debug_session(sess, GG_DEBUG_TRAFFIC, "// gg_watch_fd() received http header (%s)\n", buf);
--
-- /* sprawdzamy, czy wszystko w porzÄ…dku. */
-- if (strncmp(buf, "HTTP/1.", 7) || strncmp(buf + 9, "200", 3)) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() invalid http reply, connection failed\n");
-- goto fail_proxy_hub;
-- }
--
-- /* ignorujemy resztę nagłówka. */
-- while (strcmp(buf, "\r\n") && strcmp(buf, ""))
-- gg_read_line(sess->fd, buf, sizeof(buf) - 1);
--
-- /* czytamy pierwszÄ… liniÄ™ danych. */
-- if (gg_read_line(sess->fd, buf, sizeof(buf) - 1) == NULL) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() read error\n");
-- goto fail_proxy_hub;
-- }
-- gg_chomp(buf);
--
-- /* jeśli pierwsza liczba w linii nie jest równa zeru,
-- * oznacza to, że mamy wiadomość systemową. */
-- if (atoi(buf)) {
-- char tmp[1024], *foo, *sysmsg_buf = NULL;
-- int len = 0;
--
-- while (gg_read_line(sess->fd, tmp, sizeof(tmp) - 1)) {
-- if (!(foo = realloc(sysmsg_buf, len + strlen(tmp) + 2))) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() out of memory for system message, ignoring\n");
-- break;
-- }
--
-- sysmsg_buf = foo;
--
-- if (!len)
-- strcpy(sysmsg_buf, tmp);
-- else
-- strcat(sysmsg_buf, tmp);
--
-- len += strlen(tmp);
-- }
--
-- e->type = GG_EVENT_MSG;
-- e->event.msg.msgclass = atoi(buf);
-- e->event.msg.sender = 0;
-- e->event.msg.message = (unsigned char*) sysmsg_buf;
-- }
--
-- close(sess->fd);
-- sess->fd = -1;
--
-- gg_debug_session(sess, GG_DEBUG_TRAFFIC, "// gg_watch_fd() received http data (%s)\n", buf);
--
-- /* analizujemy otrzymane dane. */
-- tmp = buf;
--
-- while (*tmp && *tmp != ' ')
-- tmp++;
-- while (*tmp && *tmp == ' ')
-- tmp++;
-- while (*tmp && *tmp != ' ')
-- tmp++;
-- while (*tmp && *tmp == ' ')
-- tmp++;
-- host = tmp;
-- while (*tmp && *tmp != ' ')
-- tmp++;
-- *tmp = 0;
--
-- if ((tmp = strchr(host, ':'))) {
-- *tmp = 0;
-- port = atoi(tmp + 1);
-- }
--
-- if (strcmp(host, "") == 0) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() invalid response\n");
-- e->event.failure = GG_FAILURE_HUB;
-- goto fail;
-- }
--
-- if (!strcmp(host, "notoperating")) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() service unavailable\n", errno, strerror(errno));
-- e->event.failure = GG_FAILURE_UNAVAILABLE;
-- goto fail;
-- }
--
-- addr.s_addr = inet_addr(host);
-- sess->server_addr = addr.s_addr;
--
-- if (!gg_proxy_http_only && sess->proxy_addr && sess->proxy_port) {
-- /* jeśli mamy proxy, łączymy się z nim. */
-- if ((sess->fd = gg_connect(&sess->proxy_addr, sess->proxy_port, sess->async)) == -1) {
-- /* nie wyszło? trudno. */
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection to proxy failed (errno=%d, %s)\n", errno, strerror(errno));
-- e->event.failure = GG_FAILURE_PROXY;
-- goto fail;
-- }
--
-- sess->state = GG_STATE_CONNECTING_GG;
-- sess->check = GG_CHECK_WRITE;
-- sess->timeout = GG_DEFAULT_TIMEOUT;
-- sess->soft_timeout = 1;
-- break;
-- }
--
-- sess->port = port;
--
-- /* Jeśli podano nazwę, nie adres serwera... */
-- if (sess->server_addr == INADDR_NONE) {
-- if (sess->resolver_start(&sess->fd, &sess->resolver, host) == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_login() resolving failed (errno=%d, %s)\n", errno, strerror(errno));
-- goto fail;
-- }
--
-- sess->state = GG_STATE_RESOLVING_GG;
-- sess->check = GG_CHECK_READ;
-- sess->timeout = GG_DEFAULT_TIMEOUT;
-- break;
-- }
--
-- /* łączymy się z właściwym serwerem. */
-- if ((sess->fd = gg_connect(&addr, sess->port, sess->async)) == -1) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), trying https\n", errno, strerror(errno));
--
-- sess->port = GG_HTTPS_PORT;
--
-- /* nie wyszło? próbujemy portu 443. */
-- if ((sess->fd = gg_connect(&addr, GG_HTTPS_PORT, sess->async)) == -1) {
-- /* ostatnia deska ratunku zawiodła?
-- * w takim razie zwijamy manatki. */
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", errno, strerror(errno));
-- e->event.failure = GG_FAILURE_CONNECTING;
-- goto fail;
-- }
-- }
--
-- sess->state = GG_STATE_CONNECTING_GG;
-- sess->check = GG_CHECK_WRITE;
-- sess->timeout = GG_DEFAULT_TIMEOUT;
-- sess->soft_timeout = 1;
--
-- break;
-- }
--
-- case GG_STATE_RESOLVING_GG:
-- {
-- struct in_addr addr;
-- int failed = 0;
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_RESOLVING_GG\n");
--
-- if (read(sess->fd, &addr, sizeof(addr)) < (signed)sizeof(addr) || addr.s_addr == INADDR_NONE) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() resolving failed\n");
-- failed = 1;
-- errno2 = errno;
-- }
--
-- close(sess->fd);
-- sess->fd = -1;
--
-- sess->resolver_cleanup(&sess->resolver, 0);
--
-- if (failed) {
-- errno = errno2;
-- e->event.failure = GG_FAILURE_RESOLVING;
-- goto fail;
-- }
--
-- sess->server_addr = addr.s_addr;
--
-- /* łączymy się z właściwym serwerem. */
-- if ((sess->fd = gg_connect(&addr, sess->port, sess->async)) == -1) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), trying https\n", errno, strerror(errno));
--
-- sess->port = GG_HTTPS_PORT;
--
-- /* nie wyszło? próbujemy portu 443. */
-- if ((sess->fd = gg_connect(&addr, GG_HTTPS_PORT, sess->async)) == -1) {
-- /* ostatnia deska ratunku zawiodła?
-- * w takim razie zwijamy manatki. */
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", errno, strerror(errno));
-- e->event.failure = GG_FAILURE_CONNECTING;
-- goto fail;
-- }
-- }
--
-- sess->state = GG_STATE_CONNECTING_GG;
-- sess->check = GG_CHECK_WRITE;
-- sess->timeout = GG_DEFAULT_TIMEOUT;
-- sess->soft_timeout = 1;
--
-- break;
-- }
--
-- case GG_STATE_CONNECTING_GG:
-- {
-- int res = 0;
-- socklen_t res_size = sizeof(res);
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_CONNECTING_GG\n");
--
-- sess->soft_timeout = 0;
--
-- /* jeśli wystąpił błąd podczas łączenia się... */
-- if (sess->async && (sess->timeout == 0 || getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) {
-- /* jeśli nie udało się połączenie z proxy,
-- * nie mamy czego próbować więcej. */
-- if (sess->proxy_addr && sess->proxy_port) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection to proxy failed (errno=%d, %s)\n", res, strerror(res));
-- e->event.failure = GG_FAILURE_PROXY;
-- goto fail;
-- }
--
-- close(sess->fd);
-- sess->fd = -1;
--
--#ifdef ETIMEDOUT
-- if (sess->timeout == 0)
-- errno = ETIMEDOUT;
--#endif
--
--#if defined(GG_CONFIG_HAVE_GNUTLS) || defined(GG_CONFIG_HAVE_OPENSSL)
-- /* jeśli logujemy się po TLS, nie próbujemy
-- * się łączyć już z niczym innym w przypadku
-- * błędu. nie dość, że nie ma sensu, to i
-- * trzeba by się bawić w tworzenie na nowo
-- * SSL i SSL_CTX. */
--
-- if (sess->ssl) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", res, strerror(res));
-- e->event.failure = GG_FAILURE_CONNECTING;
-- goto fail;
-- }
--#endif
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), trying https\n", res, strerror(res));
--
-- if (sess->port == GG_HTTPS_PORT) {
-- e->event.failure = GG_FAILURE_CONNECTING;
-- goto fail;
-- }
--
-- sess->port = GG_HTTPS_PORT;
--
-- /* próbujemy na port 443. */
-- if ((sess->fd = gg_connect(&sess->server_addr, sess->port, sess->async)) == -1) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", errno, strerror(errno));
-- e->event.failure = GG_FAILURE_CONNECTING;
-- goto fail;
-- }
--
-- sess->state = GG_STATE_CONNECTING_GG;
-- sess->check = GG_CHECK_WRITE;
-- sess->timeout = GG_DEFAULT_TIMEOUT;
-- sess->soft_timeout = 1;
--
-- break;
-- }
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connected\n");
--
-- if (gg_proxy_http_only)
-- sess->proxy_port = 0;
--
-- /* jeśli mamy proxy, wyślijmy zapytanie. */
-- if (sess->proxy_addr && sess->proxy_port) {
-- char buf[100], *auth = gg_proxy_auth();
-- struct in_addr addr;
--
-- if (sess->server_addr)
-- addr.s_addr = sess->server_addr;
-- else
-- addr.s_addr = sess->hub_addr;
--
-- snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.0\r\n", inet_ntoa(addr), sess->port);
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() proxy request:\n// %s", buf);
--
-- /* wysyłamy zapytanie. jest ono na tyle krótkie,
-- * że musi się zmieścić w buforze gniazda. jeśli
-- * write() zawiedzie, stało się coś złego. */
-- if (write(sess->fd, buf, strlen(buf)) < (signed)strlen(buf)) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() can't send proxy request\n");
-- free(auth);
-- e->event.failure = GG_FAILURE_PROXY;
-- goto fail;
-- }
--
-- if (auth) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// %s", auth);
-- if (write(sess->fd, auth, strlen(auth)) < (signed)strlen(auth)) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() can't send proxy request\n");
-- free(auth);
-- e->event.failure = GG_FAILURE_PROXY;
-- goto fail;
-- }
--
-- free(auth);
-- }
--
-- if (write(sess->fd, "\r\n", 2) < 2) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() can't send proxy request\n");
-- e->event.failure = GG_FAILURE_PROXY;
-- goto fail;
-- }
-- }
--
--#if defined(GG_CONFIG_HAVE_GNUTLS) || defined(GG_CONFIG_HAVE_OPENSSL)
-- if (sess->ssl != NULL) {
--#ifdef GG_CONFIG_HAVE_GNUTLS
-- gnutls_transport_set_ptr(GG_SESSION_GNUTLS(sess), (gnutls_transport_ptr_t) sess->fd);
--#endif
--#ifdef GG_CONFIG_HAVE_OPENSSL
-- SSL_set_fd(sess->ssl, sess->fd);
--#endif
--
-- sess->state = GG_STATE_TLS_NEGOTIATION;
-- sess->check = GG_CHECK_WRITE;
-- sess->timeout = GG_DEFAULT_TIMEOUT;
--
-- break;
-- }
--#endif
--
-- sess->state = GG_STATE_READING_KEY;
-- sess->check = GG_CHECK_READ;
-- sess->timeout = GG_DEFAULT_TIMEOUT;
--
-- break;
-- }
--
--#ifdef GG_CONFIG_HAVE_GNUTLS
-- case GG_STATE_TLS_NEGOTIATION:
-- {
-- int res;
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_TLS_NEGOTIATION\n");
--
--gnutls_handshake_repeat:
-- res = gnutls_handshake(GG_SESSION_GNUTLS(sess));
--
-- if (res == GNUTLS_E_AGAIN) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() TLS handshake GNUTLS_E_AGAIN\n");
--
-- sess->state = GG_STATE_TLS_NEGOTIATION;
-- if (gnutls_record_get_direction(GG_SESSION_GNUTLS(sess)) == 0)
-- sess->check = GG_CHECK_READ;
-- else
-- sess->check = GG_CHECK_WRITE;
-- sess->timeout = GG_DEFAULT_TIMEOUT;
-- break;
-- }
--
-- if (res == GNUTLS_E_INTERRUPTED) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() TLS handshake GNUTLS_E_INTERRUPTED\n");
-- goto gnutls_handshake_repeat;
-- }
--
-- if (res != 0) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() TLS handshake error %d\n", res);
-- e->type = GG_EVENT_CONN_FAILED;
-- e->event.failure = GG_FAILURE_TLS;
-- sess->state = GG_STATE_IDLE;
-- close(sess->fd);
-- sess->fd = -1;
-- break;
-- }
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() TLS negotiation succeded:\n");
-- gg_debug_session(sess, GG_DEBUG_MISC, "// cipher: VERS-%s:%s:%s:%s:COMP-%s\n",
-- gnutls_protocol_get_name(gnutls_protocol_get_version(GG_SESSION_GNUTLS(sess))),
-- gnutls_cipher_get_name(gnutls_cipher_get(GG_SESSION_GNUTLS(sess))),
-- gnutls_kx_get_name(gnutls_kx_get(GG_SESSION_GNUTLS(sess))),
-- gnutls_mac_get_name(gnutls_mac_get(GG_SESSION_GNUTLS(sess))),
-- gnutls_compression_get_name(gnutls_compression_get(GG_SESSION_GNUTLS(sess))));
--
-- if (gnutls_certificate_type_get(GG_SESSION_GNUTLS(sess)) == GNUTLS_CRT_X509) {
-- unsigned int peer_count;
-- const gnutls_datum_t *peers;
-- gnutls_x509_crt_t cert;
--
-- if (gnutls_x509_crt_init(&cert) >= 0) {
-- peers = gnutls_certificate_get_peers(GG_SESSION_GNUTLS(sess), &peer_count);
--
-- if (peers != NULL) {
-- char buf[256];
-- size_t size;
--
-- if (gnutls_x509_crt_import(cert, &peers[0], GNUTLS_X509_FMT_DER) >= 0) {
-- size = sizeof(buf);
-- gnutls_x509_crt_get_dn(cert, buf, &size);
-- gg_debug_session(sess, GG_DEBUG_MISC, "// cert subject: %s\n", buf);
-- size = sizeof(buf);
-- gnutls_x509_crt_get_issuer_dn(cert, buf, &size);
-- gg_debug_session(sess, GG_DEBUG_MISC, "// cert issuer: %s\n", buf);
-- }
-- }
-- }
-- }
--
-- sess->state = GG_STATE_READING_KEY;
-- sess->check = GG_CHECK_READ;
-- sess->timeout = GG_DEFAULT_TIMEOUT;
--
-- break;
-- }
--#endif
--
--#ifdef GG_CONFIG_HAVE_OPENSSL
-- case GG_STATE_TLS_NEGOTIATION:
-- {
-- int res;
-- X509 *peer;
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_TLS_NEGOTIATION\n");
--
-- if ((res = SSL_connect(sess->ssl)) <= 0) {
-- int err = SSL_get_error(sess->ssl, res);
--
-- if (res == 0) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() disconnected during TLS negotiation\n");
--
-- e->type = GG_EVENT_CONN_FAILED;
-- e->event.failure = GG_FAILURE_TLS;
-- sess->state = GG_STATE_IDLE;
-- close(sess->fd);
-- sess->fd = -1;
-- break;
-- }
--
-- if (err == SSL_ERROR_WANT_READ) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() SSL_connect() wants to read\n");
--
-- sess->state = GG_STATE_TLS_NEGOTIATION;
-- sess->check = GG_CHECK_READ;
-- sess->timeout = GG_DEFAULT_TIMEOUT;
--
-- break;
-- } else if (err == SSL_ERROR_WANT_WRITE) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() SSL_connect() wants to write\n");
--
-- sess->state = GG_STATE_TLS_NEGOTIATION;
-- sess->check = GG_CHECK_WRITE;
-- sess->timeout = GG_DEFAULT_TIMEOUT;
--
-- break;
-- } else {
-- char buf[256];
--
-- ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() SSL_connect() bailed out: %s\n", buf);
--
-- e->type = GG_EVENT_CONN_FAILED;
-- e->event.failure = GG_FAILURE_TLS;
-- sess->state = GG_STATE_IDLE;
-- close(sess->fd);
-- sess->fd = -1;
-- break;
-- }
-- }
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() TLS negotiation succeded:\n// cipher: %s\n", SSL_get_cipher_name(sess->ssl));
--
-- peer = SSL_get_peer_certificate(sess->ssl);
--
-- if (!peer)
-- gg_debug_session(sess, GG_DEBUG_MISC, "// WARNING! unable to get peer certificate!\n");
-- else {
-- char buf[256];
--
-- X509_NAME_oneline(X509_get_subject_name(peer), buf, sizeof(buf));
-- gg_debug_session(sess, GG_DEBUG_MISC, "// cert subject: %s\n", buf);
--
-- X509_NAME_oneline(X509_get_issuer_name(peer), buf, sizeof(buf));
-- gg_debug_session(sess, GG_DEBUG_MISC, "// cert issuer: %s\n", buf);
-- }
--
-- sess->state = GG_STATE_READING_KEY;
-- sess->check = GG_CHECK_READ;
-- sess->timeout = GG_DEFAULT_TIMEOUT;
--
-- break;
-- }
--#endif
--
-- case GG_STATE_READING_KEY:
-- case GG_STATE_READING_REPLY:
-- case GG_STATE_CONNECTED:
-- case GG_STATE_DISCONNECTING:
-- {
-- struct gg_header *gh;
--
-- if (sess->state == GG_STATE_READING_KEY)
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_READING_KEY\n");
-- else if (sess->state == GG_STATE_READING_REPLY)
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_READING_REPLY\n");
-- else if (sess->state == GG_STATE_CONNECTED)
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_CONNECTED\n");
-- else if (sess->state == GG_STATE_DISCONNECTING)
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_DISCONNECTING\n");
--
-- /* XXX bardzo, bardzo, bardzo głupi pomysł na pozbycie
-- * siÄ™ tekstu wrzucanego przez proxy. */
-- if (sess->state == GG_STATE_READING_KEY && sess->proxy_addr && sess->proxy_port) {
-- char buf[100];
--
-- strcpy(buf, "");
-- gg_read_line(sess->fd, buf, sizeof(buf) - 1);
-- gg_chomp(buf);
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() proxy response:\n// %s\n", buf);
--
-- while (strcmp(buf, "")) {
-- gg_read_line(sess->fd, buf, sizeof(buf) - 1);
-- gg_chomp(buf);
-- if (strcmp(buf, ""))
-- gg_debug_session(sess, GG_DEBUG_MISC, "// %s\n", buf);
-- }
--
-- /* XXX niech czeka jeszcze raz w tej samej
-- * fazie. głupio, ale działa. */
-- sess->proxy_port = 0;
--
-- break;
-- }
--
-- sess->last_event = time(NULL);
--
-- gh = gg_recv_packet(sess);
--
-- if (gh == NULL) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd_connected() gg_recv_packet failed (errno=%d, %s)\n", errno, strerror(errno));
--
-- if (errno != EAGAIN)
-- goto fail;
-- } else {
-- if (gg_session_handle_packet(sess, gh->type, (const char *) gh + sizeof(struct gg_header), gh->length, e) == -1) {
-- free(gh);
-- goto fail;
-- }
--
-- free(gh);
-- }
--
-- sess->check = GG_CHECK_READ;
--
-- break;
-- }
-- }
--
-- if (sess->send_buf && (sess->state == GG_STATE_READING_REPLY || sess->state == GG_STATE_CONNECTED))
-- sess->check |= GG_CHECK_WRITE;
--
-- return e;
--
--fail_proxy_hub:
-- if (sess->proxy_port)
-- e->event.failure = GG_FAILURE_PROXY;
-- else
-- e->event.failure = GG_FAILURE_HUB;
--
--fail:
-- sess->resolver_cleanup(&sess->resolver, 1);
--
-- sess->state = GG_STATE_IDLE;
--
-- if (sess->fd != -1) {
-- int errno2;
--
-- errno2 = errno;
-- close(sess->fd);
-- errno = errno2;
-- sess->fd = -1;
-- }
--
-- if (e->event.failure != 0) {
-- e->type = GG_EVENT_CONN_FAILED;
-- return e;
-- } else {
-- free(e);
-- return NULL;
-- }
--}
--
--/*
-- * Local variables:
-- * c-indentation-style: k&r
-- * c-basic-offset: 8
-- * indent-tabs-mode: notnil
-- * End:
-- *
-- * vim: shiftwidth=8:
-- */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/handlers.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/handlers.c
---- pidgin-2.10.7/libpurple/protocols/gg/lib/handlers.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/handlers.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1857 +0,0 @@
--/*
-- * (C) Copyright 2001-2011 Wojtek Kaniewski <wojtekka@irc.pl>
-- * Robert J. Woźny <speedy@ziew.org>
-- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
-- * Tomasz Chiliński <chilek@chilan.com>
-- * Adam Wysocki <gophi@ekg.chmurka.net>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--/**
-- * \file handlers.c
-- *
-- * \brief Funkcje obsługi przychodzących pakietów
-- */
--
--#include <sys/types.h>
--#ifndef _WIN32
--# include <sys/socket.h>
--# include <netinet/in.h>
--# include <arpa/inet.h>
--#endif
--#include <ctype.h>
--#ifndef _WIN32
--# ifdef sun
--# include <sys/filio.h>
--# endif
--#endif
--
--#include "compat.h"
--#include "libgadu.h"
--#include "libgadu-config.h"
--#include "resolver.h"
--#include "session.h"
--#include "protocol.h"
--#include "encoding.h"
--#include "message.h"
--#include "libgadu-internal.h"
--#include "deflate.h"
--
--#include <errno.h>
--#ifndef _WIN32
--# include <netdb.h>
--#endif
--#include <stdarg.h>
--#include <stdio.h>
--#include <stdlib.h>
--#include <string.h>
--#include <signal.h>
--#include <unistd.h>
--#include <time.h>
--#ifdef GG_CONFIG_HAVE_OPENSSL
--# include <openssl/err.h>
--# include <openssl/rand.h>
--#endif
--
--/**
-- * \internal Struktura opisująca funkcję obsługi pakietu.
-- */
--typedef struct {
-- /* Typ pakietu */
-- uint32_t type;
-- /* Stan w którym pakiet jest obsługiwany */
-- int state;
-- /* Minimalny rozmiar danych pakietu */
-- int min_length;
-- /* Funkcja obsługująca pakiet. Patrz gg_session_handle_packet(). */
-- int (*handler)(struct gg_session *, uint32_t, const char *, size_t, struct gg_event *);
--} gg_packet_handler_t;
--
--/**
-- * \internal Obsługuje pakiet GG_WELCOME.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_welcome(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- struct gg_welcome *w;
-- int ret;
-- uint8_t hash_buf[64];
-- uint32_t local_ip;
-- struct sockaddr_in sin;
-- unsigned int sin_len = sizeof(sin);
--
-- if (len < sizeof(struct gg_welcome)) {
-- ge->type = GG_EVENT_CONN_FAILED;
-- ge->event.failure = GG_FAILURE_INVALID;
-- gs->state = GG_STATE_IDLE;
-- close(gs->fd);
-- gs->fd = -1;
-- return 0;
-- }
--
-- w = (struct gg_welcome*) ptr;
-- w->key = gg_fix32(w->key);
--
-- memset(hash_buf, 0, sizeof(hash_buf));
--
-- switch (gs->hash_type) {
-- case GG_LOGIN_HASH_GG32:
-- {
-- uint32_t hash;
--
-- hash = gg_fix32(gg_login_hash((unsigned char*) gs->password, w->key));
-- gg_debug_session(gs, GG_DEBUG_DUMP, "// gg_watch_fd() challenge %.4x --> GG32 hash %.8x\n", w->key, hash);
-- memcpy(hash_buf, &hash, sizeof(hash));
--
-- break;
-- }
--
-- case GG_LOGIN_HASH_SHA1:
-- {
--#ifndef GG_DEBUG_DISABLE
-- char tmp[41];
-- int i;
--#endif
--
-- gg_login_hash_sha1(gs->password, w->key, hash_buf);
--
--#ifndef GG_DEBUG_DISABLE
-- for (i = 0; i < 40; i += 2)
-- snprintf(tmp + i, sizeof(tmp) - i, "%02x", hash_buf[i / 2]);
--
-- gg_debug_session(gs, GG_DEBUG_DUMP, "// gg_watch_fd() challenge %.4x --> SHA1 hash: %s\n", w->key, tmp);
--#endif
--
-- break;
-- }
--
-- default:
-- break;
-- }
--
--#if 0
-- if (gs->password != NULL && (gs->flags & (1 << GG_SESSION_FLAG_CLEAR_PASSWORD))) {
-- memset(gs->password, 0, strlen(gs->password));
-- free(gs->password);
-- gs->password = NULL;
-- }
--#endif
--
-- if (!getsockname(gs->fd, (struct sockaddr*) &sin, &sin_len)) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() detected address to %s\n", inet_ntoa(sin.sin_addr));
-- local_ip = sin.sin_addr.s_addr;
-- } else {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() unable to detect address\n");
-- local_ip = 0;
-- }
--
-- if (GG_SESSION_IS_PROTOCOL_8_0(gs)) {
-- struct gg_login80 l80;
-- const char *client_name, *version, *descr;
-- uint32_t client_name_len, version_len, descr_len;
--
-- if (gs->external_addr == 0)
-- gs->external_addr = local_ip;
--
-- memset(&l80, 0, sizeof(l80));
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() sending GG_LOGIN80 packet\n");
-- l80.uin = gg_fix32(gs->uin);
-- memcpy(l80.language, GG8_LANG, sizeof(l80.language));
-- l80.hash_type = gs->hash_type;
-- memcpy(l80.hash, hash_buf, sizeof(l80.hash));
-- l80.status = gg_fix32(gs->initial_status ? gs->initial_status : GG_STATUS_AVAIL);
-- l80.flags = gg_fix32(gs->status_flags);
-- l80.features = gg_fix32(gs->protocol_features);
-- l80.image_size = gs->image_size;
-- l80.dunno2 = 0x64;
--
-- if (gs->client_version != NULL && !isdigit(gs->client_version[0])) {
-- client_name = "";
-- client_name_len = 0;
-- } else {
-- client_name = GG8_VERSION;
-- client_name_len = strlen(GG8_VERSION);
-- }
--
-- version = (gs->client_version != NULL) ? gs->client_version : GG_DEFAULT_CLIENT_VERSION;
-- version_len = gg_fix32(client_name_len + strlen(version));
--
-- descr = (gs->initial_descr != NULL) ? gs->initial_descr : "";
-- descr_len = (gs->initial_descr != NULL) ? gg_fix32(strlen(gs->initial_descr)) : 0;
--
-- ret = gg_send_packet(gs,
-- GG_LOGIN80,
-- &l80, sizeof(l80),
-- &version_len, sizeof(version_len),
-- client_name, client_name_len,
-- version, strlen(version),
-- &descr_len, sizeof(descr_len),
-- descr, strlen(descr),
-- NULL);
-- } else {
-- struct gg_login70 l70;
--
-- if (gg_dcc_ip != (unsigned long) inet_addr("255.255.255.255"))
-- local_ip = gg_dcc_ip;
--
-- gs->client_addr = local_ip;
--
-- memset(&l70, 0, sizeof(l70));
-- l70.uin = gg_fix32(gs->uin);
-- l70.hash_type = gs->hash_type;
-- memcpy(l70.hash, hash_buf, sizeof(l70.hash));
-- l70.status = gg_fix32(gs->initial_status ? gs->initial_status : GG_STATUS_AVAIL);
-- l70.version = gg_fix32(gs->protocol_version | gs->protocol_flags);
-- if (gs->external_addr && gs->external_port > 1023) {
-- l70.local_ip = gs->external_addr;
-- l70.local_port = gg_fix16(gs->external_port);
-- } else {
-- l70.local_ip = local_ip;
-- l70.local_port = gg_fix16(gg_dcc_port);
-- }
--
-- l70.image_size = gs->image_size;
-- l70.dunno2 = 0xbe;
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() sending GG_LOGIN70 packet\n");
-- ret = gg_send_packet(gs, GG_LOGIN70, &l70, sizeof(l70), gs->initial_descr, (gs->initial_descr) ? strlen(gs->initial_descr) : 0, NULL);
-- }
--
-- if (ret == -1) {
-- int errno_copy;
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() sending packet failed. (errno=%d, %s)\n", errno, strerror(errno));
-- errno_copy = errno;
-- close(gs->fd);
-- errno = errno_copy;
-- gs->fd = -1;
-- ge->type = GG_EVENT_CONN_FAILED;
-- ge->event.failure = GG_FAILURE_WRITING;
-- gs->state = GG_STATE_IDLE;
-- return -1;
-- }
--
-- gs->state = GG_STATE_READING_REPLY;
-- gs->check = GG_CHECK_READ;
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_LOGIN_OK.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_login_ok(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() login succeded\n");
-- ge->type = GG_EVENT_CONN_SUCCESS;
-- gs->state = GG_STATE_CONNECTED;
-- gs->check = GG_CHECK_READ;
-- gs->timeout = -1;
-- gs->status = (gs->initial_status) ? gs->initial_status : GG_STATUS_AVAIL;
--#if 0
-- free(gs->status_descr);
-- gs->status_descr = gs->initial_descr;
--#else
-- free(gs->initial_descr);
--#endif
-- gs->initial_descr = NULL;
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_LOGIN_FAILED.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_login_failed(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- if (type != GG_DISCONNECTING)
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() login failed\n");
-- else
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() too many incorrect password attempts\n");
-- ge->type = GG_EVENT_CONN_FAILED;
-- ge->event.failure = (type != GG_DISCONNECTING) ? GG_FAILURE_PASSWORD : GG_FAILURE_INTRUDER;
-- gs->state = GG_STATE_IDLE;
-- close(gs->fd);
-- gs->fd = -1;
-- errno = EACCES;
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_SEND_MSG_ACK.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_send_msg_ack(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- struct gg_send_msg_ack *s = (struct gg_send_msg_ack*) ptr;
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a message ack\n");
--
-- ge->type = GG_EVENT_ACK;
-- ge->event.ack.status = gg_fix32(s->status);
-- ge->event.ack.recipient = gg_fix32(s->recipient);
-- ge->event.ack.seq = gg_fix32(s->seq);
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_PONG.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_pong(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a pong\n");
--
-- ge->type = GG_EVENT_PONG;
--
-- gs->last_pong = time(NULL);
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_DISCONNECTING.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_disconnecting(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received disconnection warning\n");
--
-- ge->type = GG_EVENT_DISCONNECT;
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_DISCONNECT_ACK.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_disconnect_ack(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received logoff acknowledge\n");
--
-- ge->type = GG_EVENT_DISCONNECT_ACK;
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiety GG_XML_EVENT i GG_XML_ACTION.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_xml_event(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received XML event\n");
--
-- ge->type = GG_EVENT_XML_EVENT;
-- ge->event.xml_event.data = malloc(len + 1);
--
-- if (ge->event.xml_event.data == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
-- return -1;
-- }
--
-- memcpy(ge->event.xml_event.data, ptr, len);
-- ge->event.xml_event.data[len] = 0;
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_PUBDIR50_REPLY.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_pubdir50_reply(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received pubdir/search reply\n");
--
-- return gg_pubdir50_handle_reply_sess(gs, ge, ptr, len);
--}
--
--/**
-- * \internal Obsługuje pakiet GG_USERLIST_REPLY.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_userlist_reply(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- char reply_type;
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received userlist reply\n");
--
-- reply_type = ptr[0];
--
-- /* jeśli odpowiedź na eksport, wywołaj zdarzenie tylko
-- * gdy otrzymano wszystkie odpowiedzi */
-- if (reply_type == GG_USERLIST_PUT_REPLY || reply_type == GG_USERLIST_PUT_MORE_REPLY) {
-- if (--gs->userlist_blocks)
-- return 0;
--
-- reply_type = GG_USERLIST_PUT_REPLY;
-- }
--
-- if (len > 1) {
-- unsigned int reply_len = (gs->userlist_reply != NULL) ? strlen(gs->userlist_reply) : 0;
-- char *tmp;
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "userlist_reply=%p, len=%d\n", gs->userlist_reply, len);
--
-- tmp = realloc(gs->userlist_reply, reply_len + len);
--
-- if (tmp == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
-- return -1;
-- }
--
-- gs->userlist_reply = tmp;
-- memcpy(gs->userlist_reply + reply_len, ptr + 1, len - 1);
-- gs->userlist_reply[reply_len + len - 1] = 0;
-- }
--
-- if (reply_type == GG_USERLIST_GET_MORE_REPLY)
-- return 0;
--
-- ge->type = GG_EVENT_USERLIST;
-- ge->event.userlist.type = reply_type;
-- ge->event.userlist.reply = gs->userlist_reply;
--
-- gs->userlist_reply = NULL;
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_DCC7_ID_REPLY.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_dcc7_id_reply(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received dcc7 id packet\n");
--
-- return gg_dcc7_handle_id(gs, ge, ptr, len);
--}
--
--/**
-- * \internal Obsługuje pakiet GG_DCC7_ACCEPT.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_dcc7_accept(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received dcc7 accept\n");
--
-- return gg_dcc7_handle_accept(gs, ge, ptr, len);
--}
--
--/**
-- * \internal Obsługuje pakiet GG_DCC7_NEW.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_dcc7_new(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received dcc7 request\n");
--
-- return gg_dcc7_handle_new(gs, ge, ptr, len);
--}
--
--/**
-- * \internal Obsługuje pakiet GG_DCC7_REJECT.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_dcc7_reject(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received dcc7 reject\n");
--
-- return gg_dcc7_handle_reject(gs, ge, ptr, len);
--}
--
--/**
-- * \internal Obsługuje pakiet GG_DCC7_INFO.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_dcc7_info(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received dcc7 info\n");
--
-- return gg_dcc7_handle_info(gs, ge, ptr, len);
--}
--
--/**
-- * \internal Analizuje przychodzÄ…cy pakiet z obrazkiem.
-- *
-- * \param e Struktura zdarzenia
-- * \param p Bufor z danymi
-- * \param len Długość bufora
-- * \param sess Struktura sesji
-- * \param sender Numer nadawcy
-- */
--static void gg_image_queue_parse(struct gg_event *e, const char *p, unsigned int len, struct gg_session *sess, uin_t sender)
--{
-- struct gg_msg_image_reply *i = (void*) p;
-- struct gg_image_queue *q, *qq;
--
-- if (!p || !sess || !e) {
-- errno = EFAULT;
-- return;
-- }
--
-- /* znajdź dany obrazek w kolejce danej sesji */
--
-- for (qq = sess->images, q = NULL; qq; qq = qq->next) {
-- if (sender == qq->sender && i->size == qq->size && i->crc32 == qq->crc32) {
-- q = qq;
-- break;
-- }
-- }
--
-- if (!q) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_image_queue_parse() unknown image from %d, size=%d, crc32=%.8x\n", sender, i->size, i->crc32);
-- return;
-- }
--
-- if (p[0] == GG_MSG_OPTION_IMAGE_REPLY) {
-- q->done = 0;
--
-- len -= sizeof(struct gg_msg_image_reply);
-- p += sizeof(struct gg_msg_image_reply);
--
-- if (memchr(p, 0, len) == NULL) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_image_queue_parse() malformed packet from %d, unlimited filename\n", sender);
-- return;
-- }
--
-- if (!(q->filename = strdup(p))) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_image_queue_parse() out of memory\n");
-- return;
-- }
--
-- len -= strlen(p) + 1;
-- p += strlen(p) + 1;
-- } else {
-- len -= sizeof(struct gg_msg_image_reply);
-- p += sizeof(struct gg_msg_image_reply);
-- }
--
-- if (q->done + len > q->size)
-- len = q->size - q->done;
--
-- memcpy(q->image + q->done, p, len);
-- q->done += len;
--
-- /* jeśli skończono odbierać obrazek, wygeneruj zdarzenie */
--
-- if (q->done >= q->size) {
-- e->type = GG_EVENT_IMAGE_REPLY;
-- e->event.image_reply.sender = sender;
-- e->event.image_reply.size = q->size;
-- e->event.image_reply.crc32 = q->crc32;
-- e->event.image_reply.filename = q->filename;
-- e->event.image_reply.image = q->image;
--
-- gg_image_queue_remove(sess, q, 0);
--
-- free(q);
-- }
--}
--
--/**
-- * \internal Analizuje informacje rozszerzone wiadomości.
-- *
-- * \param sess Struktura sesji.
-- * \param e Struktura zdarzenia.
-- * \param sender Numer nadawcy.
-- * \param p Wskaźnik na dane rozszerzone.
-- * \param packet_end Wskaźnik na koniec pakietu.
-- *
-- * \return 0 jeśli się powiodło, -1 jeśli wiadomość obsłużono i wynik ma
-- * zostać przekazany aplikacji, -2 jeśli wystąpił błąd ogólny, -3 jeśli
-- * wiadomość jest niepoprawna.
-- */
--static int gg_handle_recv_msg_options(struct gg_session *sess, struct gg_event *e, uin_t sender, const char *p, const char *packet_end)
--{
-- while (p < packet_end) {
-- switch (*p) {
-- case GG_MSG_OPTION_CONFERENCE:
-- {
-- struct gg_msg_recipients *m = (void*) p;
-- uint32_t i, count;
--
-- p += sizeof(*m);
--
-- if (p > packet_end) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() packet out of bounds (1)\n");
-- goto malformed;
-- }
--
-- count = gg_fix32(m->count);
--
-- if (p + count * sizeof(uin_t) > packet_end || p + count * sizeof(uin_t) < p || count > 0xffff) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() packet out of bounds (1.5)\n");
-- goto malformed;
-- }
--
-- if (e->event.msg.recipients != NULL) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() e->event.msg.recipients already exist\n");
-- goto malformed;
-- }
--
-- e->event.msg.recipients = malloc(count * sizeof(uin_t));
--
-- if (e->event.msg.recipients == NULL) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() not enough memory for recipients data\n");
-- goto fail;
-- }
--
-- memcpy(e->event.msg.recipients, p, count * sizeof(uin_t));
-- p += count * sizeof(uin_t);
--
-- for (i = 0; i < count; i++)
-- e->event.msg.recipients[i] = gg_fix32(e->event.msg.recipients[i]);
--
-- e->event.msg.recipients_count = count;
--
-- break;
-- }
--
-- case GG_MSG_OPTION_ATTRIBUTES:
-- {
-- uint16_t len;
-- char *buf;
--
-- if (p + 3 > packet_end) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() packet out of bounds (2)\n");
-- goto malformed;
-- }
--
-- memcpy(&len, p + 1, sizeof(uint16_t));
-- len = gg_fix16(len);
--
-- if (e->event.msg.formats != NULL) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() e->event.msg.formats already exist\n");
-- goto malformed;
-- }
--
-- buf = malloc(len);
--
-- if (buf == NULL) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() not enough memory for richtext data\n");
-- goto fail;
-- }
--
-- p += 3;
--
-- if (p + len > packet_end) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() packet out of bounds (3)\n");
-- free(buf);
-- goto malformed;
-- }
--
-- memcpy(buf, p, len);
--
-- e->event.msg.formats = buf;
-- e->event.msg.formats_length = len;
--
-- p += len;
--
-- break;
-- }
--
-- case GG_MSG_OPTION_IMAGE_REQUEST:
-- {
-- struct gg_msg_image_request *i = (void*) p;
--
-- if (p + sizeof(*i) > packet_end) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg() packet out of bounds (3)\n");
-- goto malformed;
-- }
--
-- if (e->event.msg.formats != NULL || e->event.msg.recipients != NULL) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() mixed options (1)\n");
-- goto malformed;
-- }
--
-- e->event.image_request.sender = sender;
-- e->event.image_request.size = gg_fix32(i->size);
-- e->event.image_request.crc32 = gg_fix32(i->crc32);
--
-- e->type = GG_EVENT_IMAGE_REQUEST;
--
-- goto handled;
-- }
--
-- case GG_MSG_OPTION_IMAGE_REPLY:
-- case GG_MSG_OPTION_IMAGE_REPLY_MORE:
-- {
-- struct gg_msg_image_reply *rep = (void*) p;
--
-- if (e->event.msg.formats != NULL || e->event.msg.recipients != NULL) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() mixed options (2)\n");
-- goto malformed;
-- }
--
-- if (p + sizeof(struct gg_msg_image_reply) == packet_end) {
--
-- /* pusta odpowiedź - klient po drugiej stronie nie ma żądanego obrazka */
--
-- e->type = GG_EVENT_IMAGE_REPLY;
-- e->event.image_reply.sender = sender;
-- e->event.image_reply.size = 0;
-- e->event.image_reply.crc32 = gg_fix32(rep->crc32);
-- e->event.image_reply.filename = NULL;
-- e->event.image_reply.image = NULL;
-- goto handled;
--
-- } else if (p + sizeof(struct gg_msg_image_reply) + 1 > packet_end) {
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg() packet out of bounds (4)\n");
-- goto malformed;
-- }
--
-- rep->size = gg_fix32(rep->size);
-- rep->crc32 = gg_fix32(rep->crc32);
-- gg_image_queue_parse(e, p, (unsigned int)(packet_end - p), sess, sender);
--
-- goto handled;
-- }
--
-- default:
-- {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg() unknown payload 0x%.2x\n", *p);
-- p = packet_end;
-- }
-- }
-- }
--
-- return 0;
--
--handled:
-- return -1;
--
--fail:
-- return -2;
--
--malformed:
-- return -3;
--}
--
--/**
-- * \internal Wysyła potwierdzenie odebrania wiadomości.
-- *
-- * \param gs Struktura sesji
-- * \param seq Numer sekwencyjny odebranej wiadomości
-- *
-- * \return 0 jeśli się powiodło, -1 jeśli wystąpił błąd
-- */
--static int gg_session_send_msg_ack(struct gg_session *gs, uint32_t seq)
--{
-- struct gg_recv_msg_ack pkt;
--
-- gg_debug_session(gs, GG_DEBUG_FUNCTION, "** gg_session_send_msg_ack(%p);\n", gs);
--
-- if ((gs->protocol_features & GG_FEATURE_MSG_ACK) == 0)
-- return 0;
--
-- /* Kiedyś zdawało nam się, że mamy wysyłać liczbę odebranych
-- * wiadomości, ale okazało się, że numer sekwencyjny. */
-- gs->recv_msg_count++;
--
-- pkt.seq = gg_fix32(seq);
--
-- return gg_send_packet(gs, GG_RECV_MSG_ACK, &pkt, sizeof(pkt), NULL);
--}
--
--/**
-- * \internal Obsługuje pakiet GG_RECV_MSG.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_recv_msg(struct gg_session *sess, uint32_t type, const char *packet, size_t length, struct gg_event *e)
--{
-- const struct gg_recv_msg *r = (const struct gg_recv_msg*) packet;
-- const char *payload = packet + sizeof(struct gg_recv_msg);
-- const char *payload_end = packet + length;
-- char *tmp;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_handle_recv_msg(%p, %d, %p);\n", packet, length, e);
--
-- if ((r->seq == 0) && (r->msgclass == 0)) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg() oops, silently ignoring the bait\n");
-- goto malformed;
-- }
--
-- // jednobajtowa wiadomość o treści \x02 to żądanie połączenia DCC
-- if (*payload == GG_MSG_CALLBACK && payload == payload_end - 1) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg() received ctcp packet\n");
-- length = 1;
-- } else {
-- const char *options;
--
-- options = memchr(payload, 0, (size_t) (payload_end - payload));
--
-- if (options == NULL) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg() malformed packet, message out of bounds (0)\n");
-- goto malformed;
-- }
--
-- length = (size_t) (options - payload);
--
-- switch (gg_handle_recv_msg_options(sess, e, gg_fix32(r->sender), options + 1, payload_end)) {
-- case -1: // handled
-- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
-- return 0;
--
-- case -2: // failed
-- goto fail;
--
-- case -3: // malformed
-- goto malformed;
-- }
-- }
--
-- e->type = GG_EVENT_MSG;
-- e->event.msg.msgclass = gg_fix32(r->msgclass);
-- e->event.msg.sender = gg_fix32(r->sender);
-- e->event.msg.time = gg_fix32(r->time);
-- e->event.msg.seq = gg_fix32(r->seq);
--
-- tmp = gg_encoding_convert(payload, GG_ENCODING_CP1250, sess->encoding, length, -1);
-- if (tmp == NULL)
-- goto fail;
-- e->event.msg.message = (unsigned char*) tmp;
--
-- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
-- return 0;
--
--fail:
-- free(e->event.msg.message);
-- free(e->event.msg.recipients);
-- free(e->event.msg.formats);
-- return -1;
--
--malformed:
-- e->type = GG_EVENT_NONE;
-- free(e->event.msg.message);
-- free(e->event.msg.xhtml_message);
-- free(e->event.msg.recipients);
-- free(e->event.msg.formats);
-- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_RECV_MSG80.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, const char *packet, size_t length, struct gg_event *e)
--{
-- const struct gg_recv_msg80 *r = (const struct gg_recv_msg80*) packet;
-- uint32_t offset_plain;
-- uint32_t offset_attr;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_handle_recv_msg80(%p, %d, %p);\n", packet, length, e);
--
-- if (r->seq == 0 && r->msgclass == 0) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg80() oops, silently ignoring the bait\n");
-- goto malformed;
-- }
--
-- offset_plain = gg_fix32(r->offset_plain);
-- offset_attr = gg_fix32(r->offset_attr);
--
-- if (offset_plain < sizeof(struct gg_recv_msg80) || offset_plain >= length) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg80() malformed packet, message out of bounds (0)\n");
-- goto malformed;
-- }
--
-- if (offset_attr < sizeof(struct gg_recv_msg80) || offset_attr > length) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg80() malformed packet, attr out of bounds (1)\n");
-- offset_attr = 0; /* nie parsuj attr. */
-- }
--
-- /* Normalna sytuacja, więc nie podpada pod powyższy warunek. */
-- if (offset_attr == length)
-- offset_attr = 0;
--
-- if (memchr(packet + offset_plain, 0, length - offset_plain) == NULL) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg80() malformed packet, message out of bounds (2)\n");
-- goto malformed;
-- }
--
-- if (offset_plain > sizeof(struct gg_recv_msg80) && memchr(packet + sizeof(struct gg_recv_msg80), 0, offset_plain - sizeof(struct gg_recv_msg80)) == NULL) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg80() malformed packet, message out of bounds (3)\n");
-- goto malformed;
-- }
--
-- e->type = (type != GG_RECV_OWN_MSG) ? GG_EVENT_MSG : GG_EVENT_MULTILOGON_MSG;
-- e->event.msg.msgclass = gg_fix32(r->msgclass);
-- e->event.msg.sender = gg_fix32(r->sender);
-- e->event.msg.time = gg_fix32(r->time);
-- e->event.msg.seq = gg_fix32(r->seq);
--
-- if (offset_attr != 0) {
-- switch (gg_handle_recv_msg_options(sess, e, gg_fix32(r->sender), packet + offset_attr, packet + length)) {
-- case -1: // handled
-- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
-- return 0;
--
-- case -2: // failed
-- goto fail;
--
-- case -3: // malformed
-- goto malformed;
-- }
-- }
--
-- if (sess->encoding == GG_ENCODING_CP1250) {
-- e->event.msg.message = (unsigned char*) strdup(packet + offset_plain);
-- } else {
-- if (offset_plain > sizeof(struct gg_recv_msg80)) {
-- int len;
--
-- len = gg_message_html_to_text(NULL, packet + sizeof(struct gg_recv_msg80));
-- e->event.msg.message = malloc(len + 1);
--
-- if (e->event.msg.message == NULL)
-- goto fail;
--
-- gg_message_html_to_text((char*) e->event.msg.message, packet + sizeof(struct gg_recv_msg80));
-- } else {
-- e->event.msg.message = (unsigned char*) gg_encoding_convert(packet + offset_plain, GG_ENCODING_CP1250, sess->encoding, -1, -1);
-- }
-- }
--
-- if (offset_plain > sizeof(struct gg_recv_msg80))
-- e->event.msg.xhtml_message = gg_encoding_convert(packet + sizeof(struct gg_recv_msg80), GG_ENCODING_UTF8, sess->encoding, -1, -1);
-- else
-- e->event.msg.xhtml_message = NULL;
--
-- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
-- return 0;
--
--fail:
-- free(e->event.msg.message);
-- free(e->event.msg.xhtml_message);
-- free(e->event.msg.recipients);
-- free(e->event.msg.formats);
-- return -1;
--
--malformed:
-- e->type = GG_EVENT_NONE;
-- free(e->event.msg.message);
-- free(e->event.msg.xhtml_message);
-- free(e->event.msg.recipients);
-- free(e->event.msg.formats);
-- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_STATUS.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_status(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- struct gg_status *s = (void*) ptr;
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a status change\n");
--
-- ge->type = GG_EVENT_STATUS;
-- ge->event.status.uin = gg_fix32(s->uin);
-- ge->event.status.status = gg_fix32(s->status);
-- ge->event.status.descr = NULL;
--
-- if (len > sizeof(*s)) {
-- ge->event.status.descr = gg_encoding_convert(ptr + sizeof(*s), GG_ENCODING_CP1250, gs->encoding, len - sizeof(*s), -1);
--
-- if (ge->event.status.descr == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
-- return -1;
-- }
-- }
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiety GG_STATUS60, GG_STATUS77 i GG_STATUS80BETA.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_status_60_77_80beta(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- struct gg_status60 *s60 = (void*) ptr;
-- struct gg_status77 *s77 = (void*) ptr;
-- size_t struct_len;
-- uint32_t uin;
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a status change\n");
--
-- ge->type = GG_EVENT_STATUS60;
-- ge->event.status60.descr = NULL;
-- ge->event.status60.time = 0;
--
-- if (type == GG_STATUS60) {
-- uin = gg_fix32(s60->uin);
-- ge->event.status60.status = s60->status;
-- ge->event.status60.remote_ip = s60->remote_ip;
-- ge->event.status60.remote_port = gg_fix16(s60->remote_port);
-- ge->event.status60.version = s60->version;
-- ge->event.status60.image_size = s60->image_size;
-- struct_len = sizeof(*s60);
-- } else {
-- uin = gg_fix32(s77->uin);
-- ge->event.status60.status = s77->status;
-- ge->event.status60.remote_ip = s77->remote_ip;
-- ge->event.status60.remote_port = gg_fix16(s77->remote_port);
-- ge->event.status60.version = s77->version;
-- ge->event.status60.image_size = s77->image_size;
-- struct_len = sizeof(*s77);
-- }
--
-- ge->event.status60.uin = uin & 0x00ffffff;
--
-- if (uin & 0x40000000)
-- ge->event.status60.version |= GG_HAS_AUDIO_MASK;
-- if (uin & 0x20000000)
-- ge->event.status60.version |= GG_HAS_AUDIO7_MASK;
-- if (uin & 0x08000000)
-- ge->event.status60.version |= GG_ERA_OMNIX_MASK;
--
-- if (len > struct_len) {
-- size_t descr_len;
--
-- descr_len = len - struct_len;
--
-- ge->event.status60.descr = gg_encoding_convert(ptr + struct_len, (type == GG_STATUS80BETA) ? GG_ENCODING_UTF8 : GG_ENCODING_CP1250, gs->encoding, descr_len, -1);
--
-- if (ge->event.status60.descr == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
-- return -1;
-- }
--
-- if (descr_len > 4 && ptr[len - 5] == 0) {
-- uint32_t t;
-- memcpy(&t, ptr + len - 4, sizeof(uint32_t));
-- ge->event.status60.time = gg_fix32(t);
-- }
-- }
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_NOTIFY_REPLY.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_notify_reply(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- struct gg_notify_reply *n = (void*) ptr;
-- char *descr;
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a notify reply\n");
--
-- if (gg_fix32(n->status) == GG_STATUS_BUSY_DESCR || gg_fix32(n->status) == GG_STATUS_NOT_AVAIL_DESCR || gg_fix32(n->status) == GG_STATUS_AVAIL_DESCR) {
-- size_t descr_len;
--
-- ge->type = GG_EVENT_NOTIFY_DESCR;
--
-- if (!(ge->event.notify_descr.notify = (void*) malloc(sizeof(*n) * 2))) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
-- return -1;
-- }
-- ge->event.notify_descr.notify[1].uin = 0;
-- memcpy(ge->event.notify_descr.notify, ptr, sizeof(*n));
-- ge->event.notify_descr.notify[0].uin = gg_fix32(ge->event.notify_descr.notify[0].uin);
-- ge->event.notify_descr.notify[0].status = gg_fix32(ge->event.notify_descr.notify[0].status);
-- ge->event.notify_descr.notify[0].remote_port = gg_fix16(ge->event.notify_descr.notify[0].remote_port);
-- ge->event.notify_descr.notify[0].version = gg_fix32(ge->event.notify_descr.notify[0].version);
--
-- descr_len = len - sizeof(*n);
--
-- descr = gg_encoding_convert(ptr + sizeof(*n), GG_ENCODING_CP1250, gs->encoding, descr_len, -1);
--
-- if (descr == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
-- return -1;
-- }
--
-- ge->event.notify_descr.descr = descr;
--
-- } else {
-- unsigned int i, count;
--
-- ge->type = GG_EVENT_NOTIFY;
--
-- if (!(ge->event.notify = (void*) malloc(len + 2 * sizeof(*n)))) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
-- return -1;
-- }
--
-- memcpy(ge->event.notify, ptr, len);
-- count = len / sizeof(*n);
-- ge->event.notify[count].uin = 0;
--
-- for (i = 0; i < count; i++) {
-- ge->event.notify[i].uin = gg_fix32(ge->event.notify[i].uin);
-- ge->event.notify[i].status = gg_fix32(ge->event.notify[i].status);
-- ge->event.notify[i].remote_port = gg_fix16(ge->event.notify[i].remote_port);
-- ge->event.notify[i].version = gg_fix32(ge->event.notify[i].version);
-- }
-- }
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_STATUS80.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_status_80(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- struct gg_notify_reply80 *n = (void*) ptr;
-- size_t descr_len;
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a status change\n");
--
-- ge->type = GG_EVENT_STATUS60;
-- ge->event.status60.uin = gg_fix32(n->uin);
-- ge->event.status60.status = gg_fix32(n->status);
-- ge->event.status60.remote_ip = n->remote_ip;
-- ge->event.status60.remote_port = gg_fix16(n->remote_port);
-- ge->event.status60.version = 0;
-- ge->event.status60.image_size = n->image_size;
-- ge->event.status60.descr = NULL;
-- ge->event.status60.time = 0;
--
-- descr_len = gg_fix32(n->descr_len);
--
-- if (descr_len != 0 && sizeof(struct gg_notify_reply80) + descr_len <= len) {
-- ge->event.status60.descr = gg_encoding_convert((char*) n + sizeof(struct gg_notify_reply80), GG_ENCODING_UTF8, gs->encoding, descr_len, -1);
--
-- if (ge->event.status60.descr == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
-- return -1;
-- }
--
-- /* XXX czas */
-- }
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_NOTIFY_REPLY80.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_notify_reply_80(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- struct gg_notify_reply80 *n = (void*) ptr;
-- unsigned int length = len, i = 0;
--
-- // TODO: najpierw przeanalizować strukturę i określić
-- // liczbę rekordów, żeby obyć się bez realloc()
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a notify reply\n");
--
-- ge->type = GG_EVENT_NOTIFY60;
-- ge->event.notify60 = malloc(sizeof(*ge->event.notify60));
--
-- if (!ge->event.notify60) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
-- return -1;
-- }
--
-- ge->event.notify60[0].uin = 0;
--
-- while (length >= sizeof(struct gg_notify_reply80)) {
-- uin_t uin = gg_fix32(n->uin);
-- int descr_len;
-- char *tmp;
--
-- ge->event.notify60[i].uin = uin;
-- ge->event.notify60[i].status = gg_fix32(n->status);
-- ge->event.notify60[i].remote_ip = n->remote_ip;
-- ge->event.notify60[i].remote_port = gg_fix16(n->remote_port);
-- ge->event.notify60[i].version = 0;
-- ge->event.notify60[i].image_size = n->image_size;
-- ge->event.notify60[i].descr = NULL;
-- ge->event.notify60[i].time = 0;
--
-- descr_len = gg_fix32(n->descr_len);
--
-- if (descr_len != 0) {
-- if (sizeof(struct gg_notify_reply80) + descr_len <= length) {
-- ge->event.notify60[i].descr = gg_encoding_convert((char*) n + sizeof(struct gg_notify_reply80), GG_ENCODING_UTF8, gs->encoding, descr_len, -1);
--
-- if (ge->event.notify60[i].descr == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
-- return -1;
-- }
--
-- /* XXX czas */
--
-- length -= sizeof(struct gg_notify_reply80) + descr_len;
-- n = (void*) ((char*) n + sizeof(struct gg_notify_reply80) + descr_len);
-- } else {
-- length = 0;
-- }
--
-- } else {
-- length -= sizeof(struct gg_notify_reply80);
-- n = (void*) ((char*) n + sizeof(struct gg_notify_reply80));
-- }
--
-- if (!(tmp = realloc(ge->event.notify60, (i + 2) * sizeof(*ge->event.notify60)))) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
-- free(ge->event.notify60);
-- return -1;
-- }
--
-- ge->event.notify60 = (void*) tmp;
-- ge->event.notify60[++i].uin = 0;
-- }
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiety GG_NOTIFY_REPLY77 i GG_NOTIFY_REPLY80BETA.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_notify_reply_77_80beta(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- struct gg_notify_reply77 *n = (void*) ptr;
-- unsigned int length = len, i = 0;
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a notify reply\n");
--
-- ge->type = GG_EVENT_NOTIFY60;
-- ge->event.notify60 = malloc(sizeof(*ge->event.notify60));
--
-- if (ge->event.notify60 == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
-- return -1;
-- }
--
-- ge->event.notify60[0].uin = 0;
--
-- while (length >= sizeof(struct gg_notify_reply77)) {
-- uin_t uin = gg_fix32(n->uin);
-- char *tmp;
--
-- ge->event.notify60[i].uin = uin & 0x00ffffff;
-- ge->event.notify60[i].status = n->status;
-- ge->event.notify60[i].remote_ip = n->remote_ip;
-- ge->event.notify60[i].remote_port = gg_fix16(n->remote_port);
-- ge->event.notify60[i].version = n->version;
-- ge->event.notify60[i].image_size = n->image_size;
-- ge->event.notify60[i].descr = NULL;
-- ge->event.notify60[i].time = 0;
--
-- if (uin & 0x40000000)
-- ge->event.notify60[i].version |= GG_HAS_AUDIO_MASK;
-- if (uin & 0x20000000)
-- ge->event.notify60[i].version |= GG_HAS_AUDIO7_MASK;
-- if (uin & 0x08000000)
-- ge->event.notify60[i].version |= GG_ERA_OMNIX_MASK;
--
-- if (GG_S_D(n->status)) {
-- unsigned char descr_len = *((char*) n + sizeof(struct gg_notify_reply77));
--
-- if (sizeof(struct gg_notify_reply77) + descr_len <= length) {
-- ge->event.notify60[i].descr = gg_encoding_convert((char*) n + sizeof(struct gg_notify_reply77) + 1, (type == GG_NOTIFY_REPLY80BETA) ? GG_ENCODING_UTF8 : GG_ENCODING_CP1250, gs->encoding, descr_len, -1);
--
-- if (ge->event.notify60[i].descr == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
-- return -1;
-- }
--
-- /* XXX czas */
--
-- length -= sizeof(struct gg_notify_reply77) + descr_len + 1;
-- n = (void*) ((char*) n + sizeof(struct gg_notify_reply77) + descr_len + 1);
-- } else {
-- length = 0;
-- }
--
-- } else {
-- length -= sizeof(struct gg_notify_reply77);
-- n = (void*) ((char*) n + sizeof(struct gg_notify_reply77));
-- }
--
-- if (!(tmp = realloc(ge->event.notify60, (i + 2) * sizeof(*ge->event.notify60)))) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
-- free(ge->event.notify60);
-- return -1;
-- }
--
-- ge->event.notify60 = (void*) tmp;
-- ge->event.notify60[++i].uin = 0;
-- }
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_NOTIFY_REPLY60.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_notify_reply_60(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- struct gg_notify_reply60 *n = (void*) ptr;
-- unsigned int length = len, i = 0;
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a notify reply\n");
--
-- ge->type = GG_EVENT_NOTIFY60;
-- ge->event.notify60 = malloc(sizeof(*ge->event.notify60));
--
-- if (ge->event.notify60 == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
-- return -1;
-- }
--
-- ge->event.notify60[0].uin = 0;
--
-- while (length >= sizeof(struct gg_notify_reply60)) {
-- uin_t uin = gg_fix32(n->uin);
-- char *tmp;
--
-- ge->event.notify60[i].uin = uin & 0x00ffffff;
-- ge->event.notify60[i].status = n->status;
-- ge->event.notify60[i].remote_ip = n->remote_ip;
-- ge->event.notify60[i].remote_port = gg_fix16(n->remote_port);
-- ge->event.notify60[i].version = n->version;
-- ge->event.notify60[i].image_size = n->image_size;
-- ge->event.notify60[i].descr = NULL;
-- ge->event.notify60[i].time = 0;
--
-- if (uin & 0x40000000)
-- ge->event.notify60[i].version |= GG_HAS_AUDIO_MASK;
-- if (uin & 0x08000000)
-- ge->event.notify60[i].version |= GG_ERA_OMNIX_MASK;
--
-- if (GG_S_D(n->status)) {
-- unsigned char descr_len = *((char*) n + sizeof(struct gg_notify_reply60));
--
-- if (sizeof(struct gg_notify_reply60) + descr_len <= length) {
-- char *descr;
--
-- descr = gg_encoding_convert((char*) n + sizeof(struct gg_notify_reply60) + 1, GG_ENCODING_CP1250, gs->encoding, descr_len, -1);
--
-- if (descr == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
-- return -1;
-- }
--
-- ge->event.notify60[i].descr = descr;
--
-- /* XXX czas */
--
-- length -= sizeof(struct gg_notify_reply60) + descr_len + 1;
-- n = (void*) ((char*) n + sizeof(struct gg_notify_reply60) + descr_len + 1);
-- } else {
-- length = 0;
-- }
--
-- } else {
-- length -= sizeof(struct gg_notify_reply60);
-- n = (void*) ((char*) n + sizeof(struct gg_notify_reply60));
-- }
--
-- if (!(tmp = realloc(ge->event.notify60, (i + 2) * sizeof(*ge->event.notify60)))) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
-- free(ge->event.notify60);
-- return -1;
-- }
--
-- ge->event.notify60 = (void*) tmp;
-- ge->event.notify60[++i].uin = 0;
-- }
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_USER_DATA.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_user_data(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- struct gg_user_data d;
-- char *p = (char*) ptr;
-- char *packet_end = (char*) ptr + len;
-- struct gg_event_user_data_user *users;
-- int i, j;
-- int res = 0;
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received user data\n");
--
-- ge->event.user_data.user_count = 0;
-- ge->event.user_data.users = NULL;
--
-- if (ptr + sizeof(d) > packet_end)
-- goto malformed;
--
-- memcpy(&d, p, sizeof(d));
-- p += sizeof(d);
--
-- d.type = gg_fix32(d.type);
-- d.user_count = gg_fix32(d.user_count);
--
-- if (d.user_count > 0xffff) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() malformed packet (1)\n");
-- goto malformed;
-- }
--
-- if (d.user_count > 0) {
-- users = calloc(d.user_count, sizeof(struct gg_event_user_data_user));
--
-- if (users == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() out of memory (%d*%d)\n", d.user_count, sizeof(struct gg_event_user_data_user));
-- goto fail;
-- }
-- } else {
-- users = NULL;
-- }
--
-- ge->type = GG_EVENT_USER_DATA;
-- ge->event.user_data.type = d.type;
-- ge->event.user_data.user_count = d.user_count;
-- ge->event.user_data.users = users;
--
-- gg_debug_session(gs, GG_DEBUG_DUMP, "type=%d, count=%d\n", d.type, d.user_count);
--
-- for (i = 0; i < d.user_count; i++) {
-- struct gg_user_data_user u;
-- struct gg_event_user_data_attr *attrs;
--
-- if (p + sizeof(u) > packet_end) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() malformed packet (2)\n");
-- goto malformed;
-- }
--
-- memcpy(&u, p, sizeof(u));
-- p += sizeof(u);
--
-- u.uin = gg_fix32(u.uin);
-- u.attr_count = gg_fix32(u.attr_count);
--
-- if (u.attr_count > 0xffff) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() malformed packet (2)\n");
-- goto malformed;
-- }
--
-- if (u.attr_count > 0) {
-- attrs = calloc(u.attr_count, sizeof(struct gg_event_user_data_attr));
--
-- if (attrs == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() out of memory (%d*%d)\n", u.attr_count, sizeof(struct gg_event_user_data_attr));
-- goto fail;
-- }
-- } else {
-- attrs = NULL;
-- }
--
-- users[i].uin = u.uin;
-- users[i].attr_count = u.attr_count;
-- users[i].attrs = attrs;
--
-- gg_debug_session(gs, GG_DEBUG_DUMP, " uin=%d, count=%d\n", u.uin, u.attr_count);
--
-- for (j = 0; j < u.attr_count; j++) {
-- uint32_t key_size;
-- uint32_t attr_type;
-- uint32_t value_size;
-- char *key;
-- char *value;
--
-- if (p + sizeof(key_size) > packet_end) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() malformed packet (3)\n");
-- goto malformed;
-- }
--
-- memcpy(&key_size, p, sizeof(key_size));
-- p += sizeof(key_size);
--
-- key_size = gg_fix32(key_size);
--
-- if (key_size > 0xffff || p + key_size > packet_end) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() malformed packet (3)\n");
-- goto malformed;
-- }
--
-- key = malloc(key_size + 1);
--
-- if (key == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() out of memory (%d)\n", key_size + 1);
-- goto fail;
-- }
--
-- memcpy(key, p, key_size);
-- p += key_size;
--
-- key[key_size] = 0;
--
-- attrs[j].key = key;
--
-- if (p + sizeof(attr_type) + sizeof(value_size) > packet_end) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() malformed packet (4)\n");
-- goto malformed;
-- }
--
-- memcpy(&attr_type, p, sizeof(attr_type));
-- p += sizeof(attr_type);
-- memcpy(&value_size, p, sizeof(value_size));
-- p += sizeof(value_size);
--
-- attrs[j].type = gg_fix32(attr_type);
-- value_size = gg_fix32(value_size);
--
-- if (value_size > 0xffff || p + value_size > packet_end) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() malformed packet (5)\n");
-- goto malformed;
-- }
--
-- value = malloc(value_size + 1);
--
-- if (value == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() out of memory (%d)\n", value_size + 1);
-- goto fail;
-- }
--
-- memcpy(value, p, value_size);
-- p += value_size;
--
-- value[value_size] = 0;
--
-- attrs[j].value = value;
--
-- gg_debug_session(gs, GG_DEBUG_DUMP, " key=\"%s\", type=%d, value=\"%s\"\n", key, attr_type, value);
-- }
-- }
--
-- return 0;
--
--fail:
-- res = -1;
--
--malformed:
-- ge->type = GG_EVENT_NONE;
--
-- for (i = 0; i < ge->event.user_data.user_count; i++) {
-- for (j = 0; j < ge->event.user_data.users[i].attr_count; j++) {
-- free(ge->event.user_data.users[i].attrs[j].key);
-- free(ge->event.user_data.users[i].attrs[j].value);
-- }
--
-- free(ge->event.user_data.users[i].attrs);
-- }
--
-- free(ge->event.user_data.users);
--
-- return res;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_TYPING_NOTIFICATION.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_typing_notification(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- struct gg_typing_notification *n = (void*) ptr;
-- uin_t uin;
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received typing notification\n");
--
-- memcpy(&uin, &n->uin, sizeof(uin_t));
--
-- ge->type = GG_EVENT_TYPING_NOTIFICATION;
-- ge->event.typing_notification.uin = gg_fix32(uin);
-- ge->event.typing_notification.length = gg_fix16(n->length);
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_MULTILOGON_INFO.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_multilogon_info(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- char *packet_end = (char*) ptr + len;
-- struct gg_multilogon_info *info = (struct gg_multilogon_info*) ptr;
-- char *p = (char*) ptr + sizeof(*info);
-- struct gg_multilogon_session *sessions = NULL;
-- size_t count;
-- size_t i;
-- int res = 0;
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received multilogon info\n");
--
-- count = gg_fix32(info->count);
--
-- if (count > 0xffff) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_handle_multilogon_info() malformed packet (1)\n");
-- goto malformed;
-- }
--
-- sessions = calloc(count, sizeof(struct gg_multilogon_session));
--
-- if (sessions == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_handle_multilogon_info() out of memory (%d*%d)\n", count, sizeof(struct gg_multilogon_session));
-- return -1;
-- }
--
-- ge->type = GG_EVENT_MULTILOGON_INFO;
-- ge->event.multilogon_info.count = count;
-- ge->event.multilogon_info.sessions = sessions;
--
-- for (i = 0; i < count; i++) {
-- struct gg_multilogon_info_item item;
-- size_t name_size;
--
-- if (p + sizeof(item) > packet_end) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_handle_multilogon_info() malformed packet (2)\n");
-- goto malformed;
-- }
--
-- memcpy(&item, p, sizeof(item));
--
-- sessions[i].id = item.conn_id;
-- sessions[i].remote_addr = item.addr;
-- sessions[i].status_flags = gg_fix32(item.flags);
-- sessions[i].protocol_features = gg_fix32(item.features);
-- sessions[i].logon_time = gg_fix32(item.logon_time);
--
-- p += sizeof(item);
--
-- name_size = gg_fix32(item.name_size);
--
-- if (name_size > 0xffff || p + name_size > packet_end) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_handle_multilogon_info() malformed packet (3)\n");
-- goto malformed;
-- }
--
-- sessions[i].name = malloc(name_size + 1);
--
-- if (sessions[i].name == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_handle_multilogon_info() out of memory (%d)\n", name_size);
-- goto fail;
-- }
--
-- memcpy(sessions[i].name, p, name_size);
-- sessions[i].name[name_size] = 0;
--
-- p += name_size;
-- }
--
-- return 0;
--
--fail:
-- res = -1;
--
--malformed:
-- ge->type = GG_EVENT_NONE;
--
-- for (i = 0; i < ge->event.multilogon_info.count; i++)
-- free(ge->event.multilogon_info.sessions[i].name);
--
-- free(ge->event.multilogon_info.sessions);
--
-- return res;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_USERLIST100_VERSION.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_userlist_100_version(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- struct gg_userlist100_version *version = (struct gg_userlist100_version*) ptr;
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received userlist 100 version\n");
--
-- ge->type = GG_EVENT_USERLIST100_VERSION;
-- ge->event.userlist100_version.version = gg_fix32(version->version);
--
-- return 0;
--}
--
--/**
-- * \internal Obsługuje pakiet GG_USERLIST100_REPLY.
-- *
-- * Patrz gg_packet_handler_t
-- */
--static int gg_session_handle_userlist_100_reply(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- struct gg_userlist100_reply *reply = (struct gg_userlist100_reply*) ptr;
-- char *data = NULL;
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received userlist 100 reply\n");
--
-- if (len > sizeof(*reply)) {
-- data = gg_inflate((const unsigned char*) ptr + sizeof(*reply), len - sizeof(*reply));
--
-- if (data == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_handle_userlist_100_reply() gg_inflate() failed\n");
-- return -1;
-- }
-- }
--
-- ge->type = GG_EVENT_USERLIST100_REPLY;
-- ge->event.userlist100_reply.type = reply->type;
-- ge->event.userlist100_reply.version = gg_fix32(reply->version);
-- ge->event.userlist100_reply.format_type = reply->format_type;
-- ge->event.userlist100_reply.reply = data;
--
-- return 0;
--}
--
--/**
-- * \internal Tablica obsługiwanych pakietów
-- */
--static const gg_packet_handler_t handlers[] =
--{
-- { GG_WELCOME, GG_STATE_READING_KEY, 0, gg_session_handle_welcome },
-- { GG_LOGIN_OK, GG_STATE_READING_REPLY, 0, gg_session_handle_login_ok },
-- { GG_LOGIN80_OK, GG_STATE_READING_REPLY, 0, gg_session_handle_login_ok },
-- { GG_NEED_EMAIL, GG_STATE_READING_REPLY, 0, gg_session_handle_login_ok },
-- { GG_LOGIN_FAILED, GG_STATE_READING_REPLY, 0, gg_session_handle_login_failed },
-- { GG_LOGIN80_FAILED, GG_STATE_READING_REPLY, 0, gg_session_handle_login_failed },
-- { GG_SEND_MSG_ACK, GG_STATE_CONNECTED, sizeof(struct gg_send_msg_ack), gg_session_handle_send_msg_ack },
-- { GG_PONG, GG_STATE_CONNECTED, 0, gg_session_handle_pong },
-- { GG_DISCONNECTING, GG_STATE_CONNECTED, 0, gg_session_handle_disconnecting },
-- { GG_DISCONNECT_ACK, GG_STATE_DISCONNECTING, 0, gg_session_handle_disconnect_ack },
-- { GG_XML_EVENT, GG_STATE_CONNECTED, 0, gg_session_handle_xml_event },
-- { GG_PUBDIR50_REPLY, GG_STATE_CONNECTED, 0, gg_session_handle_pubdir50_reply },
-- { GG_USERLIST_REPLY, GG_STATE_CONNECTED, 0, gg_session_handle_userlist_reply },
-- { GG_DCC7_ID_REPLY, GG_STATE_CONNECTED, sizeof(struct gg_dcc7_id_reply), gg_session_handle_dcc7_id_reply },
-- { GG_DCC7_ACCEPT, GG_STATE_CONNECTED, sizeof(struct gg_dcc7_accept), gg_session_handle_dcc7_accept },
-- { GG_DCC7_NEW, GG_STATE_CONNECTED, sizeof(struct gg_dcc7_new), gg_session_handle_dcc7_new },
-- { GG_DCC7_REJECT, GG_STATE_CONNECTED, sizeof(struct gg_dcc7_reject), gg_session_handle_dcc7_reject },
-- { GG_DCC7_INFO, GG_STATE_CONNECTED, sizeof(struct gg_dcc7_info), gg_session_handle_dcc7_info },
-- { GG_RECV_MSG, GG_STATE_CONNECTED, sizeof(struct gg_recv_msg), gg_session_handle_recv_msg },
-- { GG_RECV_MSG80, GG_STATE_CONNECTED, sizeof(struct gg_recv_msg80), gg_session_handle_recv_msg_80 },
-- { GG_STATUS, GG_STATE_CONNECTED, sizeof(struct gg_status), gg_session_handle_status },
-- { GG_STATUS60, GG_STATE_CONNECTED, sizeof(struct gg_status60), gg_session_handle_status_60_77_80beta },
-- { GG_STATUS77, GG_STATE_CONNECTED, sizeof(struct gg_status77), gg_session_handle_status_60_77_80beta },
-- { GG_STATUS80BETA, GG_STATE_CONNECTED, sizeof(struct gg_status77), gg_session_handle_status_60_77_80beta },
-- { GG_STATUS80, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply80), gg_session_handle_status_80 },
-- { GG_NOTIFY_REPLY, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply), gg_session_handle_notify_reply },
-- { GG_NOTIFY_REPLY60, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply60), gg_session_handle_notify_reply_60 },
-- { GG_NOTIFY_REPLY77, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply77), gg_session_handle_notify_reply_77_80beta },
-- { GG_NOTIFY_REPLY80BETA, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply77), gg_session_handle_notify_reply_77_80beta },
-- { GG_NOTIFY_REPLY80, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply80), gg_session_handle_notify_reply_80 },
-- { GG_USER_DATA, GG_STATE_CONNECTED, sizeof(struct gg_user_data), gg_session_handle_user_data },
-- { GG_TYPING_NOTIFICATION, GG_STATE_CONNECTED, sizeof(struct gg_typing_notification), gg_session_handle_typing_notification },
-- { GG_MULTILOGON_INFO, GG_STATE_CONNECTED, sizeof(struct gg_multilogon_info), gg_session_handle_multilogon_info },
-- { GG_XML_ACTION, GG_STATE_CONNECTED, 0, gg_session_handle_xml_event },
-- { GG_RECV_OWN_MSG, GG_STATE_CONNECTED, sizeof(struct gg_recv_msg80), gg_session_handle_recv_msg_80 },
-- { GG_USERLIST100_VERSION, GG_STATE_CONNECTED, sizeof(struct gg_userlist100_version), gg_session_handle_userlist_100_version },
-- { GG_USERLIST100_REPLY, GG_STATE_CONNECTED, sizeof(struct gg_userlist100_reply), gg_session_handle_userlist_100_reply },
--};
--
--/**
-- * \internal Analizuje przychodzÄ…cy pakiet danych.
-- *
-- * \param gs Struktura sesji
-- * \param type Typ pakietu
-- * \param ptr Wskaźnik do bufora pakietu
-- * \param len Długość bufora pakietu
-- * \param[out] ge Struktura zdarzenia
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--int gg_session_handle_packet(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
--{
-- int i;
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_packet(%d, %p, %d)\n", type, ptr, len);
--
-- gs->last_event = time(NULL);
--
--#if 0
-- if ((gs->flags & (1 << GG_SESSION_FLAG_RAW_PACKET)) != 0) {
-- char *tmp;
--
-- tmp = malloc(len);
--
-- if (tmp == NULL) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_packet() out of memory (%d bytes)\n", len);
-- return -1;
-- }
--
-- memcpy(tmp, ptr, len);
--
-- ge->type = GG_EVENT_RAW_PACKET;
-- ge->event.raw_packet.type = type;
-- ge->event.raw_packet.length = len;
-- ge->event.raw_packet.data = tmp;
--
-- return 0;
-- }
--#endif
--
-- for (i = 0; i < sizeof(handlers) / sizeof(handlers[0]); i++) {
-- if (handlers[i].type != 0 && handlers[i].type != type)
-- continue;
--
-- if (handlers[i].state != 0 && handlers[i].state != gs->state) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_packet() packet 0x%02x unexpected in state %d\n", type, gs->state);
-- continue;
-- }
--
-- if (len < handlers[i].min_length) {
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_packet() packet 0x%02x too short (%d bytes)\n", type, len);
-- continue;
-- }
--
-- return (*handlers[i].handler)(gs, type, ptr, len, ge);
-- }
--
-- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_packet() unhandled packet 0x%02x, len %d, state %d\n", type, len, gs->state);
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/http.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/http.c
---- pidgin-2.10.7/libpurple/protocols/gg/lib/http.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/http.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,544 +0,0 @@
--/* $Id: http.c 1036 2010-12-15 00:02:28Z wojtekka $ */
--
--/*
-- * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--/**
-- * \file http.c
-- *
-- * \brief Obsługa połączeń HTTP
-- */
--
--#include <sys/types.h>
--#ifndef _WIN32
--# include <sys/socket.h>
--# include <netinet/in.h>
--# include <arpa/inet.h>
--#endif
--
--#include "compat.h"
--#include "libgadu.h"
--#include "resolver.h"
--
--#include <ctype.h>
--#include <errno.h>
--#ifndef _WIN32
--# include <netdb.h>
--#endif
--#include <signal.h>
--#include <stdarg.h>
--#include <stdio.h>
--#include <stdlib.h>
--#include <string.h>
--#include <unistd.h>
--
--/**
-- * Rozpoczyna połączenie HTTP.
-- *
-- * Funkcja przeprowadza połączenie HTTP przy połączeniu synchronicznym,
-- * zwracając wynik w polach struktury \c gg_http, lub błąd, gdy sesja się
-- * nie powiedzie.
-- *
-- * Przy połączeniu asynchronicznym, funkcja rozpoczyna połączenie, a dalsze
-- * etapy będą przeprowadzane po wykryciu zmian (\c watch) na obserwowanym
-- * deskryptorze (\c fd) i wywołaniu funkcji \c gg_http_watch_fd().
-- *
-- * Po zakończeniu, należy zwolnić strukturę za pomocą funkcji
-- * \c gg_http_free(). Połączenie asynchroniczne można zatrzymać w każdej
-- * chwili za pomocÄ… \c gg_http_stop().
-- *
-- * \param hostname Adres serwera
-- * \param port Port serwera
-- * \param async Flaga asynchronicznego połączenia
-- * \param method Metoda HTTP
-- * \param path Ścieżka do zasobu (musi być poprzedzona znakiem '/')
-- * \param header Nagłówek zapytania plus ewentualne dane dla POST
-- *
-- * \return Zaalokowana struktura \c gg_http lub NULL, jeśli wystąpił błąd.
-- *
-- * \ingroup http
-- */
--struct gg_http *gg_http_connect(const char *hostname, int port, int async, const char *method, const char *path, const char *header)
--{
-- struct gg_http *h;
--
-- if (!hostname || !port || !method || !path || !header) {
-- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() invalid arguments\n");
-- errno = EFAULT;
-- return NULL;
-- }
--
-- if (!(h = malloc(sizeof(*h))))
-- return NULL;
-- memset(h, 0, sizeof(*h));
--
-- h->async = async;
-- h->port = port;
-- h->fd = -1;
-- h->type = GG_SESSION_HTTP;
--
-- gg_http_set_resolver(h, GG_RESOLVER_DEFAULT);
--
-- if (gg_proxy_enabled) {
-- char *auth = gg_proxy_auth();
--
-- h->query = gg_saprintf("%s http://%s:%d%s HTTP/1.0\r\n%s%s",
-- method, hostname, port, path, (auth) ? auth :
-- "", header);
-- hostname = gg_proxy_host;
-- h->port = port = gg_proxy_port;
-- free(auth);
--
-- } else {
-- h->query = gg_saprintf("%s %s HTTP/1.0\r\n%s",
-- method, path, header);
-- }
--
-- if (!h->query) {
-- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() not enough memory for query\n");
-- free(h);
-- errno = ENOMEM;
-- return NULL;
-- }
--
-- gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-QUERY-----\n%s\n=> -----END-HTTP-QUERY-----\n", h->query);
--
-- if (async) {
-- if (h->resolver_start(&h->fd, &h->resolver, hostname) == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() resolver failed\n");
-- gg_http_free(h);
-- errno = ENOENT;
-- return NULL;
-- }
--
-- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() resolver = %p\n", h->resolver);
--
-- h->state = GG_STATE_RESOLVING;
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DEFAULT_TIMEOUT;
-- } else {
-- struct in_addr *addr_list = NULL;
-- int addr_count;
--
-- if (gg_gethostbyname_real(hostname, &addr_list, &addr_count, 0) == -1 || addr_count == 0) {
-- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() host not found\n");
-- gg_http_free(h);
-- free(addr_list);
-- errno = ENOENT;
-- return NULL;
-- }
--
-- if ((h->fd = gg_connect(&addr_list[0], port, 0)) == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() connection failed (errno=%d, %s)\n", errno, strerror(errno));
-- gg_http_free(h);
-- free(addr_list);
-- return NULL;
-- }
--
-- free(addr_list);
--
-- h->state = GG_STATE_CONNECTING;
--
-- while (h->state != GG_STATE_ERROR && h->state != GG_STATE_PARSING) {
-- if (gg_http_watch_fd(h) == -1)
-- break;
-- }
--
-- if (h->state != GG_STATE_PARSING) {
-- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() some strange error\n");
-- gg_http_free(h);
-- return NULL;
-- }
-- }
--
-- h->callback = gg_http_watch_fd;
-- h->destroy = gg_http_free;
--
-- return h;
--}
--
--#ifndef DOXYGEN
--
--#define gg_http_error(x) \
-- close(h->fd); \
-- h->fd = -1; \
-- h->state = GG_STATE_ERROR; \
-- h->error = x; \
-- return 0;
--
--#endif /* DOXYGEN */
--
--/**
-- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
-- *
-- * Operacja będzie zakończona, gdy pole \c state będzie równe
-- * \c GG_STATE_PARSING. W tym miejscu działanie przejmuje zwykle funkcja
-- * korzystająca z \c gg_http_watch_fd(). W przypadku błędu połączenia,
-- * pole \c state będzie równe \c GG_STATE_ERROR, a kod błędu znajdzie się
-- * w polu \c error.
-- *
-- * \param h Struktura połączenia
-- *
-- * \return \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup http
-- */
--int gg_http_watch_fd(struct gg_http *h)
--{
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_http_watch_fd(%p);\n", h);
--
-- if (!h) {
-- gg_debug(GG_DEBUG_MISC, "// gg_http_watch_fd() invalid arguments\n");
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (h->state == GG_STATE_RESOLVING) {
-- struct in_addr a;
--
-- gg_debug(GG_DEBUG_MISC, "=> http, resolving done\n");
--
-- if (read(h->fd, &a, sizeof(a)) < (signed)sizeof(a) || a.s_addr == INADDR_NONE) {
-- gg_debug(GG_DEBUG_MISC, "=> http, resolver thread failed\n");
-- gg_http_error(GG_ERROR_RESOLVING);
-- }
--
-- close(h->fd);
-- h->fd = -1;
--
-- h->resolver_cleanup(&h->resolver, 0);
--
-- gg_debug(GG_DEBUG_MISC, "=> http, connecting to %s:%d\n", inet_ntoa(a), h->port);
--
-- if ((h->fd = gg_connect(&a, h->port, h->async)) == -1) {
-- gg_debug(GG_DEBUG_MISC, "=> http, connection failed (errno=%d, %s)\n", errno, strerror(errno));
-- gg_http_error(GG_ERROR_CONNECTING);
-- }
--
-- h->state = GG_STATE_CONNECTING;
-- h->check = GG_CHECK_WRITE;
-- h->timeout = GG_DEFAULT_TIMEOUT;
--
-- return 0;
-- }
--
-- if (h->state == GG_STATE_CONNECTING) {
-- int res = 0;
-- socklen_t res_size = sizeof(res);
--
-- if (h->async && (getsockopt(h->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) {
-- gg_debug(GG_DEBUG_MISC, "=> http, async connection failed (errno=%d, %s)\n", (res) ? res : errno , strerror((res) ? res : errno));
-- close(h->fd);
-- h->fd = -1;
-- h->state = GG_STATE_ERROR;
-- h->error = GG_ERROR_CONNECTING;
-- if (res)
-- errno = res;
-- return 0;
-- }
--
-- gg_debug(GG_DEBUG_MISC, "=> http, connected, sending request\n");
--
-- h->state = GG_STATE_SENDING_QUERY;
-- }
--
-- if (h->state == GG_STATE_SENDING_QUERY) {
-- size_t res;
--
-- if ((res = write(h->fd, h->query, strlen(h->query))) < 1) {
-- gg_debug(GG_DEBUG_MISC, "=> http, write() failed (len=%d, res=%d, errno=%d)\n", strlen(h->query), res, errno);
-- gg_http_error(GG_ERROR_WRITING);
-- }
--
-- if (res < strlen(h->query)) {
-- gg_debug(GG_DEBUG_MISC, "=> http, partial header sent (led=%d, sent=%d)\n", strlen(h->query), res);
--
-- memmove(h->query, h->query + res, strlen(h->query) - res + 1);
-- h->state = GG_STATE_SENDING_QUERY;
-- h->check = GG_CHECK_WRITE;
-- h->timeout = GG_DEFAULT_TIMEOUT;
-- } else {
-- gg_debug(GG_DEBUG_MISC, "=> http, request sent (len=%d)\n", strlen(h->query));
-- free(h->query);
-- h->query = NULL;
--
-- h->state = GG_STATE_READING_HEADER;
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DEFAULT_TIMEOUT;
-- }
--
-- return 0;
-- }
--
-- if (h->state == GG_STATE_READING_HEADER) {
-- char buf[1024], *tmp;
-- int res;
--
-- if ((res = read(h->fd, buf, sizeof(buf))) == -1) {
-- gg_debug(GG_DEBUG_MISC, "=> http, reading header failed (errno=%d)\n", errno);
-- if (h->header) {
-- free(h->header);
-- h->header = NULL;
-- }
-- gg_http_error(GG_ERROR_READING);
-- }
--
-- if (!res) {
-- gg_debug(GG_DEBUG_MISC, "=> http, connection reset by peer\n");
-- if (h->header) {
-- free(h->header);
-- h->header = NULL;
-- }
-- gg_http_error(GG_ERROR_READING);
-- }
--
-- gg_debug(GG_DEBUG_MISC, "=> http, read %d bytes of header\n", res);
--
-- if (!(tmp = realloc(h->header, h->header_size + res + 1))) {
-- gg_debug(GG_DEBUG_MISC, "=> http, not enough memory for header\n");
-- free(h->header);
-- h->header = NULL;
-- gg_http_error(GG_ERROR_READING);
-- }
--
-- h->header = tmp;
--
-- memcpy(h->header + h->header_size, buf, res);
-- h->header_size += res;
--
-- gg_debug(GG_DEBUG_MISC, "=> http, header_buf=%p, header_size=%d\n", h->header, h->header_size);
--
-- h->header[h->header_size] = 0;
--
-- if ((tmp = strstr(h->header, "\r\n\r\n")) || (tmp = strstr(h->header, "\n\n"))) {
-- int sep_len = (*tmp == '\r') ? 4 : 2;
-- unsigned int left;
-- char *line;
--
-- left = h->header_size - ((long)(tmp) - (long)(h->header) + sep_len);
--
-- gg_debug(GG_DEBUG_MISC, "=> http, got all header (%d bytes, %d left)\n", h->header_size - left, left);
--
-- /* HTTP/1.1 200 OK */
-- if (strlen(h->header) < 16 || strncmp(h->header + 9, "200", 3)) {
-- gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-HEADER-----\n%s\n=> -----END-HTTP-HEADER-----\n", h->header);
--
-- gg_debug(GG_DEBUG_MISC, "=> http, didn't get 200 OK -- no results\n");
-- free(h->header);
-- h->header = NULL;
-- gg_http_error(GG_ERROR_CONNECTING);
-- }
--
-- h->body_size = 0;
-- line = h->header;
-- *tmp = 0;
--
-- gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-HEADER-----\n%s\n=> -----END-HTTP-HEADER-----\n", h->header);
--
-- while (line) {
-- if (!strncasecmp(line, "Content-length: ", 16)) {
-- h->body_size = atoi(line + 16);
-- }
-- line = strchr(line, '\n');
-- if (line)
-- line++;
-- }
--
-- if (h->body_size <= 0) {
-- gg_debug(GG_DEBUG_MISC, "=> http, content-length not found\n");
-- h->body_size = left;
-- }
--
-- if (left > h->body_size) {
-- gg_debug(GG_DEBUG_MISC, "=> http, oversized reply (%d bytes needed, %d bytes left)\n", h->body_size, left);
-- h->body_size = left;
-- }
--
-- gg_debug(GG_DEBUG_MISC, "=> http, body_size=%d\n", h->body_size);
--
-- if (!(h->body = malloc(h->body_size + 1))) {
-- gg_debug(GG_DEBUG_MISC, "=> http, not enough memory (%d bytes for body_buf)\n", h->body_size + 1);
-- free(h->header);
-- h->header = NULL;
-- gg_http_error(GG_ERROR_READING);
-- }
--
-- if (left) {
-- memcpy(h->body, tmp + sep_len, left);
-- h->body_done = left;
-- }
--
-- h->body[left] = 0;
--
-- h->state = GG_STATE_READING_DATA;
-- h->check = GG_CHECK_READ;
-- h->timeout = GG_DEFAULT_TIMEOUT;
-- }
--
-- return 0;
-- }
--
-- if (h->state == GG_STATE_READING_DATA) {
-- char buf[1024];
-- int res;
--
-- if ((res = read(h->fd, buf, sizeof(buf))) == -1) {
-- gg_debug(GG_DEBUG_MISC, "=> http, reading body failed (errno=%d)\n", errno);
-- if (h->body) {
-- free(h->body);
-- h->body = NULL;
-- }
-- gg_http_error(GG_ERROR_READING);
-- }
--
-- if (!res) {
-- if (h->body_done >= h->body_size) {
-- gg_debug(GG_DEBUG_MISC, "=> http, we're done, closing socket\n");
-- h->state = GG_STATE_PARSING;
-- close(h->fd);
-- h->fd = -1;
-- } else {
-- gg_debug(GG_DEBUG_MISC, "=> http, connection closed while reading (have %d, need %d)\n", h->body_done, h->body_size);
-- if (h->body) {
-- free(h->body);
-- h->body = NULL;
-- }
-- gg_http_error(GG_ERROR_READING);
-- }
--
-- return 0;
-- }
--
-- gg_debug(GG_DEBUG_MISC, "=> http, read %d bytes of body\n", res);
--
-- if (h->body_done + res > h->body_size) {
-- char *tmp;
--
-- gg_debug(GG_DEBUG_MISC, "=> http, too much data (%d bytes, %d needed), enlarging buffer\n", h->body_done + res, h->body_size);
--
-- if (!(tmp = realloc(h->body, h->body_done + res + 1))) {
-- gg_debug(GG_DEBUG_MISC, "=> http, not enough memory for data (%d needed)\n", h->body_done + res + 1);
-- free(h->body);
-- h->body = NULL;
-- gg_http_error(GG_ERROR_READING);
-- }
--
-- h->body = tmp;
-- h->body_size = h->body_done + res;
-- }
--
-- h->body[h->body_done + res] = 0;
-- memcpy(h->body + h->body_done, buf, res);
-- h->body_done += res;
--
-- gg_debug(GG_DEBUG_MISC, "=> body_done=%d, body_size=%d\n", h->body_done, h->body_size);
--
-- return 0;
-- }
--
-- if (h->fd != -1)
-- close(h->fd);
--
-- h->fd = -1;
-- h->state = GG_STATE_ERROR;
-- h->error = 0;
--
-- return -1;
--}
--
--/**
-- * Kończy asynchroniczne połączenie HTTP.
-- *
-- * Po zatrzymaniu należy zwolnić zasoby funkcją \c gg_http_free().
-- *
-- * \param h Struktura połączenia
-- *
-- * \ingroup http
-- */
--void gg_http_stop(struct gg_http *h)
--{
-- if (!h)
-- return;
--
-- if (h->state == GG_STATE_ERROR || h->state == GG_STATE_DONE)
-- return;
--
-- if (h->fd != -1) {
-- close(h->fd);
-- h->fd = -1;
-- }
--
-- h->resolver_cleanup(&h->resolver, 1);
--}
--
--/**
-- * \internal Zwalnia pola struktury \c gg_http.
-- *
-- * Funkcja zwalnia same pola, nie zwalnia struktury.
-- *
-- * \param h Struktura połączenia
-- */
--void gg_http_free_fields(struct gg_http *h)
--{
-- if (!h)
-- return;
--
-- if (h->body) {
-- free(h->body);
-- h->body = NULL;
-- }
--
-- if (h->query) {
-- free(h->query);
-- h->query = NULL;
-- }
--
-- if (h->header) {
-- free(h->header);
-- h->header = NULL;
-- }
--}
--
--/**
-- * Zwalnia zasoby po połączeniu HTTP.
-- *
-- * Jeśli połączenie nie zostało jeszcze zakończone, jest przerywane.
-- *
-- * \param h Struktura połączenia
-- *
-- * \ingroup http
-- */
--void gg_http_free(struct gg_http *h)
--{
-- if (!h)
-- return;
--
-- gg_http_stop(h);
-- gg_http_free_fields(h);
-- free(h);
--}
--
--/*
-- * Local variables:
-- * c-indentation-style: k&r
-- * c-basic-offset: 8
-- * indent-tabs-mode: notnil
-- * End:
-- *
-- * vim: shiftwidth=8:
-- */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu.c
---- pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,2320 +0,0 @@
--/* $Id: libgadu.c 1102 2011-05-05 21:17:57Z wojtekka $ */
--
--/*
-- * (C) Copyright 2001-2010 Wojtek Kaniewski <wojtekka@irc.pl>
-- * Robert J. Woźny <speedy@ziew.org>
-- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
-- * Tomasz Chiliński <chilek@chilan.com>
-- * Adam Wysocki <gophi@ekg.chmurka.net>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--/**
-- * \file libgadu.c
-- *
-- * \brief Główny moduł biblioteki
-- */
--
--#include <sys/types.h>
--#ifdef _WIN32
--# include <io.h>
--# include <fcntl.h>
--# include <errno.h>
--# define SHUT_RDWR SD_BOTH
--#else
--# include <sys/socket.h>
--# include <netinet/in.h>
--# include <arpa/inet.h>
--# ifdef sun
--# include <sys/filio.h>
--# endif
--#endif
--
--#include "compat.h"
--#include "libgadu.h"
--#include "libgadu-config.h"
--#include "protocol.h"
--#include "resolver.h"
--#include "libgadu-internal.h"
--#include "encoding.h"
--#include "libgadu-debug.h"
--#include "session.h"
--#include "message.h"
--#include "deflate.h"
--
--#ifndef _WIN32
--# include <errno.h> /* on Win32 this is included above */
--# include <netdb.h>
--#endif
--#include <stdarg.h>
--#include <stdio.h>
--#include <stdlib.h>
--#include <string.h>
--#include <signal.h>
--#include <time.h>
--#include <unistd.h>
--#ifdef GG_CONFIG_HAVE_GNUTLS
--# include <gnutls/gnutls.h>
--#endif
--#ifdef GG_CONFIG_HAVE_OPENSSL
--# include <openssl/err.h>
--# include <openssl/rand.h>
--#endif
--
--#define GG_LIBGADU_VERSION "1.11.0"
--
--/**
-- * Port gniazda nasłuchującego dla połączeń bezpośrednich.
-- *
-- * \ingroup ip
-- */
--int gg_dcc_port = 0;
--
--/**
-- * Adres IP gniazda nasłuchującego dla połączeń bezpośrednich.
-- *
-- * \ingroup ip
-- */
--unsigned long gg_dcc_ip = 0;
--
--/**
-- * Adres lokalnego interfejsu IP, z którego wywoływane są wszystkie połączenia.
-- *
-- * \ingroup ip
-- */
--unsigned long gg_local_ip = 0;
--
--/**
-- * Flaga włączenia połączeń przez serwer pośredniczący.
-- *
-- * \ingroup proxy
-- */
--int gg_proxy_enabled = 0;
--
--/**
-- * Adres serwera pośredniczącego.
-- *
-- * \ingroup proxy
-- */
--char *gg_proxy_host = NULL;
--
--/**
-- * Port serwera pośredniczącego.
-- *
-- * \ingroup proxy
-- */
--int gg_proxy_port = 0;
--
--/**
-- * Flaga używania serwera pośredniczącego jedynie dla usług HTTP.
-- *
-- * \ingroup proxy
-- */
--int gg_proxy_http_only = 0;
--
--/**
-- * Nazwa użytkownika do autoryzacji serwera pośredniczącego.
-- *
-- * \ingroup proxy
-- */
--char *gg_proxy_username = NULL;
--
--/**
-- * Hasło użytkownika do autoryzacji serwera pośredniczącego.
-- *
-- * \ingroup proxy
-- */
--char *gg_proxy_password = NULL;
--
--#ifndef DOXYGEN
--
--#ifndef lint
--static char rcsid[]
--#ifdef __GNUC__
--__attribute__ ((unused))
--#endif
--= "$Id: libgadu.c 1102 2011-05-05 21:17:57Z wojtekka $";
--#endif
--
--#endif /* DOXYGEN */
--
--/**
-- * Zwraca wersjÄ™ biblioteki.
-- *
-- * \return Wskaźnik na statyczny bufor z wersją biblioteki.
-- *
-- * \ingroup version
-- */
--const char *gg_libgadu_version()
--{
-- return GG_LIBGADU_VERSION;
--}
--
--#ifdef GG_CONFIG_HAVE_UINT64_T
--/**
-- * \internal Zamienia kolejność bajtów w 64-bitowym słowie.
-- *
-- * Ze względu na little-endianowość protokołu Gadu-Gadu, na maszynach
-- * big-endianowych odwraca kolejność bajtów w słowie.
-- *
-- * \param x Liczba do zamiany
-- *
-- * \return Liczba z odpowiednią kolejnością bajtów
-- *
-- * \ingroup helper
-- */
--uint64_t gg_fix64(uint64_t x)
--{
--#ifndef GG_CONFIG_BIGENDIAN
-- return x;
--#else
-- return (uint64_t)
-- (((x & (uint64_t) 0x00000000000000ffULL) << 56) |
-- ((x & (uint64_t) 0x000000000000ff00ULL) << 40) |
-- ((x & (uint64_t) 0x0000000000ff0000ULL) << 24) |
-- ((x & (uint64_t) 0x00000000ff000000ULL) << 8) |
-- ((x & (uint64_t) 0x000000ff00000000ULL) >> 8) |
-- ((x & (uint64_t) 0x0000ff0000000000ULL) >> 24) |
-- ((x & (uint64_t) 0x00ff000000000000ULL) >> 40) |
-- ((x & (uint64_t) 0xff00000000000000ULL) >> 56));
--#endif
--}
--#endif /* GG_CONFIG_HAVE_UINT64_T */
--
--/**
-- * \internal Zamienia kolejność bajtów w 32-bitowym słowie.
-- *
-- * Ze względu na little-endianowość protokołu Gadu-Gadu, na maszynach
-- * big-endianowych odwraca kolejność bajtów w słowie.
-- *
-- * \param x Liczba do zamiany
-- *
-- * \return Liczba z odpowiednią kolejnością bajtów
-- *
-- * \ingroup helper
-- */
--uint32_t gg_fix32(uint32_t x)
--{
--#ifndef GG_CONFIG_BIGENDIAN
-- return x;
--#else
-- return (uint32_t)
-- (((x & (uint32_t) 0x000000ffU) << 24) |
-- ((x & (uint32_t) 0x0000ff00U) << 8) |
-- ((x & (uint32_t) 0x00ff0000U) >> 8) |
-- ((x & (uint32_t) 0xff000000U) >> 24));
--#endif
--}
--
--/**
-- * \internal Zamienia kolejność bajtów w 16-bitowym słowie.
-- *
-- * Ze względu na little-endianowość protokołu Gadu-Gadu, na maszynach
-- * big-endianowych zamienia kolejność bajtów w słowie.
-- *
-- * \param x Liczba do zamiany
-- *
-- * \return Liczba z odpowiednią kolejnością bajtów
-- *
-- * \ingroup helper
-- */
--uint16_t gg_fix16(uint16_t x)
--{
--#ifndef GG_CONFIG_BIGENDIAN
-- return x;
--#else
-- return (uint16_t)
-- (((x & (uint16_t) 0x00ffU) << 8) |
-- ((x & (uint16_t) 0xff00U) >> 8));
--#endif
--}
--
--/**
-- * \internal Liczy skrót z hasła i ziarna.
-- *
-- * \param password Hasło
-- * \param seed Ziarno podane przez serwer
-- *
-- * \return Wartość skrótu
-- */
--unsigned int gg_login_hash(const unsigned char *password, unsigned int seed)
--{
-- unsigned int x, y, z;
--
-- y = seed;
--
-- for (x = 0; *password; password++) {
-- x = (x & 0xffffff00) | *password;
-- y ^= x;
-- y += x;
-- x <<= 8;
-- y ^= x;
-- x <<= 8;
-- y -= x;
-- x <<= 8;
-- y ^= x;
--
-- z = y & 0x1F;
-- y = (y << z) | (y >> (32 - z));
-- }
--
-- return y;
--}
--
--/**
-- * \internal Odbiera od serwera dane binarne.
-- *
-- * Funkcja odbiera dane od serwera zajmując się SSL/TLS w razie konieczności.
-- * Obsługuje EINTR, więc użytkownik nie musi się przejmować przerwanymi
-- * wywołaniami systemowymi.
-- *
-- * \param sess Struktura sesji
-- * \param buf Bufor na danymi
-- * \param length Długość bufora
-- *
-- * \return To samo co funkcja systemowa \c read
-- */
--int gg_read(struct gg_session *sess, char *buf, int length)
--{
-- int res;
--
--#ifdef GG_CONFIG_HAVE_GNUTLS
-- if (sess->ssl != NULL) {
-- for (;;) {
-- res = gnutls_record_recv(GG_SESSION_GNUTLS(sess), buf, length);
--
-- if (res < 0) {
-- if (!gnutls_error_is_fatal(res) || res == GNUTLS_E_INTERRUPTED)
-- continue;
--
-- if (res == GNUTLS_E_AGAIN)
-- errno = EAGAIN;
-- else
-- errno = EINVAL;
--
-- return -1;
-- }
--
-- return res;
-- }
-- }
--#endif
--
--#ifdef GG_CONFIG_HAVE_OPENSSL
-- if (sess->ssl != NULL) {
-- for (;;) {
-- int err;
--
-- res = SSL_read(sess->ssl, buf, length);
--
-- if (res < 0) {
-- err = SSL_get_error(sess->ssl, res);
--
-- if (err == SSL_ERROR_SYSCALL && errno == EINTR)
-- continue;
--
-- if (err == SSL_ERROR_WANT_READ)
-- errno = EAGAIN;
-- else if (err != SSL_ERROR_SYSCALL)
-- errno = EINVAL;
--
-- return -1;
-- }
--
-- return res;
-- }
-- }
--#endif
--
-- for (;;) {
-- res = read(sess->fd, buf, length);
--
-- if (res == -1 && errno == EINTR)
-- continue;
--
-- return res;
-- }
--}
--
--/**
-- * \internal Wysyła do serwera dane binarne.
-- *
-- * Funkcja wysyła dane do serwera zajmując się SSL/TLS w razie konieczności.
-- * Obsługuje EINTR, więc użytkownik nie musi się przejmować przerwanymi
-- * wywołaniami systemowymi.
-- *
-- * \note Funkcja nie zajmuje się buforowaniem wysyłanych danych (patrz
-- * gg_write()).
-- *
-- * \param sess Struktura sesji
-- * \param buf Bufor z danymi
-- * \param length Długość bufora
-- *
-- * \return To samo co funkcja systemowa \c write
-- */
--static int gg_write_common(struct gg_session *sess, const char *buf, int length)
--{
-- int res;
--
--#ifdef GG_CONFIG_HAVE_GNUTLS
-- if (sess->ssl != NULL) {
-- for (;;) {
-- res = gnutls_record_send(GG_SESSION_GNUTLS(sess), buf, length);
--
-- if (res < 0) {
-- if (!gnutls_error_is_fatal(res) || res == GNUTLS_E_INTERRUPTED)
-- continue;
--
-- if (res == GNUTLS_E_AGAIN)
-- errno = EAGAIN;
-- else
-- errno = EINVAL;
--
-- return -1;
-- }
--
-- return res;
-- }
-- }
--#endif
--
--#ifdef GG_CONFIG_HAVE_OPENSSL
-- if (sess->ssl != NULL) {
-- for (;;) {
-- int err;
--
-- res = SSL_write(sess->ssl, buf, length);
--
-- if (res < 0) {
-- err = SSL_get_error(sess->ssl, res);
--
-- if (err == SSL_ERROR_SYSCALL && errno == EINTR)
-- continue;
--
-- if (err == SSL_ERROR_WANT_WRITE)
-- errno = EAGAIN;
-- else if (err != SSL_ERROR_SYSCALL)
-- errno = EINVAL;
--
-- return -1;
-- }
--
-- return res;
-- }
-- }
--#endif
--
-- for (;;) {
-- res = write(sess->fd, buf, length);
--
-- if (res == -1 && errno == EINTR)
-- continue;
--
-- return res;
-- }
--}
--
--
--
--/**
-- * \internal Wysyła do serwera dane binarne.
-- *
-- * Funkcja wysyła dane do serwera zajmując się TLS w razie konieczności.
-- *
-- * \param sess Struktura sesji
-- * \param buf Bufor z danymi
-- * \param length Długość bufora
-- *
-- * \return To samo co funkcja systemowa \c write
-- */
--int gg_write(struct gg_session *sess, const char *buf, int length)
--{
-- int res = 0;
--
-- if (!sess->async) {
-- int written = 0;
--
-- while (written < length) {
-- res = gg_write_common(sess, buf + written, length - written);
--
-- if (res == -1)
-- return -1;
--
-- written += res;
-- res = written;
-- }
-- } else {
-- res = 0;
--
-- if (sess->send_buf == NULL) {
-- res = gg_write_common(sess, buf, length);
--
-- if (res == -1)
-- return -1;
-- }
--
-- if (res < length) {
-- char *tmp;
--
-- if (!(tmp = realloc(sess->send_buf, sess->send_left + length - res))) {
-- errno = ENOMEM;
-- return -1;
-- }
--
-- sess->send_buf = tmp;
--
-- memcpy(sess->send_buf + sess->send_left, buf + res, length - res);
--
-- sess->send_left += length - res;
-- }
-- }
--
-- return res;
--}
--
--/**
-- * \internal Odbiera pakiet od serwera.
-- *
-- * Funkcja odczytuje nagłówek pakietu, a następnie jego zawartość i zwraca
-- * w zaalokowanym buforze.
-- *
-- * Przy połączeniach asynchronicznych, funkcja może nie być w stanie
-- * skompletować całego pakietu -- w takim przypadku zwróci -1, a kodem błędu
-- * będzie \c EAGAIN.
-- *
-- * \param sess Struktura sesji
-- *
-- * \return Wskaźnik do zaalokowanego bufora
-- */
--void *gg_recv_packet(struct gg_session *sess)
--{
-- struct gg_header h;
-- char *packet;
-- int ret = 0;
-- unsigned int offset, size = 0;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_recv_packet(%p);\n", sess);
--
-- if (!sess) {
-- errno = EFAULT;
-- return NULL;
-- }
--
-- if (sess->recv_left < 1) {
-- if (sess->header_buf) {
-- memcpy(&h, sess->header_buf, sess->header_done);
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv: resuming last read (%d bytes left)\n", sizeof(h) - sess->header_done);
-- free(sess->header_buf);
-- sess->header_buf = NULL;
-- } else
-- sess->header_done = 0;
--
-- while (sess->header_done < sizeof(h)) {
-- ret = gg_read(sess, (char*) &h + sess->header_done, sizeof(h) - sess->header_done);
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv(%d,%p,%d) = %d\n", sess->fd, (char*)&h + sess->header_done, sizeof(h) - sess->header_done, ret);
--
-- if (!ret) {
-- errno = ECONNRESET;
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: connection broken\n");
-- return NULL;
-- }
--
-- if (ret == -1) {
-- if (errno == EAGAIN) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv() incomplete header received\n");
--
-- if (!(sess->header_buf = malloc(sess->header_done))) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv() not enough memory\n");
-- return NULL;
-- }
--
-- memcpy(sess->header_buf, &h, sess->header_done);
--
-- errno = EAGAIN;
--
-- return NULL;
-- }
--
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: errno=%d, %s\n", errno, strerror(errno));
--
-- return NULL;
-- }
--
-- sess->header_done += ret;
-- }
--
-- h.type = gg_fix32(h.type);
-- h.length = gg_fix32(h.length);
-- } else
-- memcpy(&h, sess->recv_buf, sizeof(h));
--
-- /* jakieÅ› sensowne limity na rozmiar pakietu */
-- if (h.length > 65535) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() invalid packet length (%d)\n", h.length);
-- errno = ERANGE;
-- return NULL;
-- }
--
-- if (sess->recv_left > 0) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() resuming last gg_recv_packet()\n");
-- size = sess->recv_left;
-- offset = sess->recv_done;
-- } else {
-- if (!(sess->recv_buf = malloc(sizeof(h) + h.length + 1))) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() not enough memory for packet data\n");
-- return NULL;
-- }
--
-- memcpy(sess->recv_buf, &h, sizeof(h));
--
-- offset = 0;
-- size = h.length;
-- }
--
-- while (size > 0) {
-- ret = gg_read(sess, sess->recv_buf + sizeof(h) + offset, size);
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() body recv(%d,%p,%d) = %d\n", sess->fd, sess->recv_buf + sizeof(h) + offset, size, ret);
-- if (!ret) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() body recv() failed: connection broken\n");
-- errno = ECONNRESET;
-- goto fail;
-- }
-- if (ret > -1 && ret <= size) {
-- offset += ret;
-- size -= ret;
-- } else if (ret == -1) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() body recv() failed (errno=%d, %s)\n", errno, strerror(errno));
--
-- if (errno == EAGAIN) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() %d bytes received, %d left\n", offset, size);
-- sess->recv_left = size;
-- sess->recv_done = offset;
-- return NULL;
-- }
--
-- goto fail;
-- }
-- }
--
-- packet = sess->recv_buf;
-- sess->recv_buf = NULL;
-- sess->recv_left = 0;
--
-- gg_debug_session(sess, GG_DEBUG_DUMP, "// gg_recv_packet(type=0x%.2x, length=%d)\n", h.type, h.length);
-- gg_debug_dump(sess, GG_DEBUG_DUMP, packet, sizeof(h) + h.length);
--
-- return packet;
--
--fail:
-- free(sess->recv_buf);
-- sess->recv_buf = NULL;
-- sess->recv_left = 0;
--
-- return NULL;
--}
--
--/**
-- * \internal Wysyła pakiet do serwera.
-- *
-- * Funkcja konstruuje pakiet do wysłania z dowolnej liczby fragmentów. Jeśli
-- * rozmiar pakietu jest za duży, by móc go wysłać za jednym razem, pozostała
-- * część zostanie zakolejkowana i wysłana, gdy będzie to możliwe.
-- *
-- * \param sess Struktura sesji
-- * \param type Rodzaj pakietu
-- * \param ... Lista kolejnych części pakietu (wskaźnik na bufor i długość
-- * typu \c int) zakończona \c NULL
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--int gg_send_packet(struct gg_session *sess, int type, ...)
--{
-- struct gg_header *h;
-- char *tmp;
-- unsigned int tmp_length;
-- void *payload;
-- unsigned int payload_length;
-- va_list ap;
-- int res;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_packet(%p, 0x%.2x, ...);\n", sess, type);
--
-- tmp_length = sizeof(struct gg_header);
--
-- if (!(tmp = malloc(tmp_length))) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_send_packet() not enough memory for packet header\n");
-- return -1;
-- }
--
-- va_start(ap, type);
--
-- payload = va_arg(ap, void *);
--
-- while (payload) {
-- char *tmp2;
--
-- payload_length = va_arg(ap, unsigned int);
--
-- if (!(tmp2 = realloc(tmp, tmp_length + payload_length))) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_send_packet() not enough memory for payload\n");
-- free(tmp);
-- va_end(ap);
-- return -1;
-- }
--
-- tmp = tmp2;
--
-- memcpy(tmp + tmp_length, payload, payload_length);
-- tmp_length += payload_length;
--
-- payload = va_arg(ap, void *);
-- }
--
-- va_end(ap);
--
-- h = (struct gg_header*) tmp;
-- h->type = gg_fix32(type);
-- h->length = gg_fix32(tmp_length - sizeof(struct gg_header));
--
-- gg_debug_session(sess, GG_DEBUG_DUMP, "// gg_send_packet(type=0x%.2x, length=%d)\n", gg_fix32(h->type), gg_fix32(h->length));
-- gg_debug_dump(sess, GG_DEBUG_DUMP, tmp, tmp_length);
--
-- res = gg_write(sess, tmp, tmp_length);
--
-- free(tmp);
--
-- if (res == -1) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_send_packet() write() failed. res = %d, errno = %d (%s)\n", res, errno, strerror(errno));
-- return -1;
-- }
--
-- if (sess->async)
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_send_packet() partial write(), %d sent, %d left, %d total left\n", res, tmp_length - res, sess->send_left);
--
-- if (sess->send_buf)
-- sess->check |= GG_CHECK_WRITE;
--
-- return 0;
--}
--
--/**
-- * \internal Funkcja zwrotna sesji.
-- *
-- * Pole \c callback struktury \c gg_session zawiera wskaźnik do tej funkcji.
-- * Wywołuje ona \c gg_watch_fd i zachowuje wynik w polu \c event.
-- *
-- * \note Korzystanie z tej funkcjonalności nie jest już zalecane.
-- *
-- * \param sess Struktura sesji
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--static int gg_session_callback(struct gg_session *sess)
--{
-- if (!sess) {
-- errno = EFAULT;
-- return -1;
-- }
--
-- return ((sess->event = gg_watch_fd(sess)) != NULL) ? 0 : -1;
--}
--
--/**
-- * ÅÄ…czy siÄ™ z serwerem Gadu-Gadu.
-- *
-- * Przy połączeniu synchronicznym funkcja zakończy działanie po nawiązaniu
-- * połączenia lub gdy wystąpi błąd. Po udanym połączeniu należy wywoływać
-- * funkcję \c gg_watch_fd(), która odbiera informacje od serwera i zwraca
-- * informacje o zdarzeniach.
-- *
-- * Przy połączeniu asynchronicznym funkcja rozpocznie procedurę połączenia
-- * i zwróci zaalokowaną strukturę. Pole \c fd struktury \c gg_session zawiera
-- * deskryptor, który należy obserwować funkcją \c select, \c poll lub za
-- * pomocą mechanizmów użytej pętli zdarzeń (Glib, Qt itp.). Pole \c check
-- * jest maską bitową mówiącą, czy biblioteka chce być informowana o możliwości
-- * odczytu danych (\c GG_CHECK_READ) czy zapisu danych (\c GG_CHECK_WRITE).
-- * Po zaobserwowaniu zmian na deskryptorze należy wywołać funkcję
-- * \c gg_watch_fd(). Podczas korzystania z połączeń asynchronicznych, w trakcie
-- * połączenia może zostać stworzony dodatkowy proces rozwiązujący nazwę
-- * serwera -- z tego powodu program musi poprawnie obsłużyć sygnał SIGCHLD.
-- *
-- * \note Po nawiązaniu połączenia z serwerem należy wysłać listę kontaktów
-- * za pomocÄ… funkcji \c gg_notify() lub \c gg_notify_ex().
-- *
-- * \note Funkcja zwróci błąd ENOSYS jeśli połączenie SSL było wymagane, ale
-- * obsługa SSL nie jest wkompilowana.
-- *
-- * \param p Struktura opisująca parametry połączenia. Wymagane pola: uin,
-- * password, async.
-- *
-- * \return Wskaźnik do zaalokowanej struktury sesji \c gg_session lub NULL
-- * w przypadku błędu.
-- *
-- * \ingroup login
-- */
--struct gg_session *gg_login(const struct gg_login_params *p)
--{
-- struct gg_session *sess = NULL;
-- char *hostname;
-- int port;
--
-- if (!p) {
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%p);\n", p);
-- errno = EFAULT;
-- return NULL;
-- }
--
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%p: [uin=%u, async=%d, ...]);\n", p, p->uin, p->async);
--
-- if (!(sess = malloc(sizeof(struct gg_session)))) {
-- gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for session data\n");
-- goto fail;
-- }
--
-- memset(sess, 0, sizeof(struct gg_session));
--
-- if (!p->password || !p->uin) {
-- gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. uin and password needed\n");
-- errno = EFAULT;
-- goto fail;
-- }
--
-- if (!(sess->password = strdup(p->password))) {
-- gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for password\n");
-- goto fail;
-- }
--
-- if (p->hash_type < 0 || p->hash_type > GG_LOGIN_HASH_SHA1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. unknown hash type (%d)\n", p->hash_type);
-- errno = EFAULT;
-- goto fail;
-- }
--
-- sess->uin = p->uin;
-- sess->state = GG_STATE_RESOLVING;
-- sess->check = GG_CHECK_READ;
-- sess->timeout = GG_DEFAULT_TIMEOUT;
-- sess->async = p->async;
-- sess->type = GG_SESSION_GG;
-- sess->initial_status = p->status;
-- sess->callback = gg_session_callback;
-- sess->destroy = gg_free_session;
-- sess->port = (p->server_port) ? p->server_port : ((gg_proxy_enabled) ? GG_HTTPS_PORT : GG_DEFAULT_PORT);
-- sess->server_addr = p->server_addr;
-- sess->external_port = p->external_port;
-- sess->external_addr = p->external_addr;
-- sess->client_addr = p->client_addr;
-- sess->client_port = p->client_port;
--
-- if (p->protocol_features == 0) {
-- sess->protocol_features = GG_FEATURE_MSG80 | GG_FEATURE_STATUS80 | GG_FEATURE_DND_FFC | GG_FEATURE_IMAGE_DESCR | GG_FEATURE_UNKNOWN_100 | GG_FEATURE_USER_DATA | GG_FEATURE_MSG_ACK | GG_FEATURE_TYPING_NOTIFICATION;
-- } else {
-- sess->protocol_features = (p->protocol_features & ~(GG_FEATURE_STATUS77 | GG_FEATURE_MSG77));
--
-- if (!(p->protocol_features & GG_FEATURE_STATUS77))
-- sess->protocol_features |= GG_FEATURE_STATUS80;
--
-- if (!(p->protocol_features & GG_FEATURE_MSG77))
-- sess->protocol_features |= GG_FEATURE_MSG80;
-- }
--
-- if (!(sess->status_flags = p->status_flags))
-- sess->status_flags = GG_STATUS_FLAG_UNKNOWN | GG_STATUS_FLAG_SPAM;
--
-- sess->protocol_version = (p->protocol_version) ? p->protocol_version : GG_DEFAULT_PROTOCOL_VERSION;
--
-- if (p->era_omnix)
-- sess->protocol_flags |= GG_ERA_OMNIX_MASK;
-- if (p->has_audio)
-- sess->protocol_flags |= GG_HAS_AUDIO_MASK;
-- sess->client_version = (p->client_version) ? strdup(p->client_version) : NULL;
-- sess->last_sysmsg = p->last_sysmsg;
-- sess->image_size = p->image_size;
-- sess->pid = -1;
-- sess->encoding = p->encoding;
--
-- if (gg_session_set_resolver(sess, p->resolver) == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. unsupported resolver type (%d)\n", p->resolver);
-- errno = EFAULT;
-- goto fail;
-- }
--
-- if (p->status_descr) {
-- int max_length;
--
-- if (sess->protocol_version >= 0x2d)
-- max_length = GG_STATUS_DESCR_MAXSIZE;
-- else
-- max_length = GG_STATUS_DESCR_MAXSIZE_PRE_8_0;
--
-- if (sess->protocol_version >= 0x2d)
-- sess->initial_descr = gg_encoding_convert(p->status_descr, p->encoding, GG_ENCODING_UTF8, -1, -1);
-- else
-- sess->initial_descr = strdup(p->status_descr);
--
-- if (!sess->initial_descr) {
-- gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for status\n");
-- goto fail;
-- }
--
-- // XXX pamiętać, żeby nie ciąć w środku znaku utf-8
--
-- if (strlen(sess->initial_descr) > max_length)
-- sess->initial_descr[max_length] = 0;
-- }
--
-- if (p->tls != GG_SSL_DISABLED) {
--#ifdef GG_CONFIG_HAVE_GNUTLS
-- gg_session_gnutls_t *tmp;
--
-- tmp = malloc(sizeof(gg_session_gnutls_t));
--
-- if (tmp == NULL) {
-- gg_debug(GG_DEBUG_MISC, "// gg_login() out of memory for GnuTLS session\n");
-- goto fail;
-- }
--
-- sess->ssl = tmp;
--
-- gnutls_global_init();
-- gnutls_certificate_allocate_credentials(&tmp->xcred);
-- gnutls_init(&tmp->session, GNUTLS_CLIENT);
-- gnutls_set_default_priority(tmp->session);
-- gnutls_credentials_set(tmp->session, GNUTLS_CRD_CERTIFICATE, tmp->xcred);
--#elif defined(GG_CONFIG_HAVE_OPENSSL)
-- char buf[1024];
--
-- OpenSSL_add_ssl_algorithms();
--
-- if (!RAND_status()) {
-- char rdata[1024];
-- struct {
-- time_t time;
-- void *ptr;
-- } rstruct;
--
-- time(&rstruct.time);
-- rstruct.ptr = (void *) &rstruct;
--
-- RAND_seed((void *) rdata, sizeof(rdata));
-- RAND_seed((void *) &rstruct, sizeof(rstruct));
-- }
--
-- sess->ssl_ctx = SSL_CTX_new(SSLv3_client_method());
--
-- if (!sess->ssl_ctx) {
-- ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
-- gg_debug(GG_DEBUG_MISC, "// gg_login() SSL_CTX_new() failed: %s\n", buf);
-- goto fail;
-- }
--
-- SSL_CTX_set_verify(sess->ssl_ctx, SSL_VERIFY_NONE, NULL);
--
-- sess->ssl = SSL_new(sess->ssl_ctx);
--
-- if (!sess->ssl) {
-- ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
-- gg_debug(GG_DEBUG_MISC, "// gg_login() SSL_new() failed: %s\n", buf);
-- goto fail;
-- }
--#else
-- gg_debug(GG_DEBUG_MISC, "// gg_login() client requested TLS but no support compiled in\n");
--
-- if (p->tls == GG_SSL_REQUIRED) {
-- errno = ENOSYS;
-- goto fail;
-- }
--#endif
-- }
--
-- if (gg_proxy_enabled) {
-- hostname = gg_proxy_host;
-- sess->proxy_port = port = gg_proxy_port;
-- } else {
-- hostname = GG_APPMSG_HOST;
-- port = GG_APPMSG_PORT;
-- }
--
-- if (p->hash_type)
-- sess->hash_type = p->hash_type;
-- else
-- sess->hash_type = GG_LOGIN_HASH_SHA1;
--
-- if (!p->async) {
-- struct in_addr addr;
--
-- if (!sess->server_addr) {
-- if ((addr.s_addr = inet_addr(hostname)) == INADDR_NONE) {
-- struct in_addr *addr_list = NULL;
-- int addr_count;
--
-- if (gg_gethostbyname_real(hostname, &addr_list, &addr_count, 0) == -1 || addr_count == 0) {
-- gg_debug(GG_DEBUG_MISC, "// gg_login() host \"%s\" not found\n", hostname);
-- free(addr_list);
-- goto fail;
-- }
--
-- addr = addr_list[0];
--
-- free(addr_list);
-- }
-- } else {
-- addr.s_addr = sess->server_addr;
-- port = sess->port;
-- }
--
-- sess->hub_addr = addr.s_addr;
--
-- if (gg_proxy_enabled)
-- sess->proxy_addr = addr.s_addr;
--
-- if ((sess->fd = gg_connect(&addr, port, 0)) == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_login() connection failed (errno=%d, %s)\n", errno, strerror(errno));
--
-- /* nie wyszło? próbujemy portu 443. */
-- if (sess->server_addr) {
-- sess->port = GG_HTTPS_PORT;
--
-- if ((sess->fd = gg_connect(&addr, GG_HTTPS_PORT, 0)) == -1) {
-- /* ostatnia deska ratunku zawiodła?
-- * w takim razie zwijamy manatki. */
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_login() connection failed (errno=%d, %s)\n", errno, strerror(errno));
-- goto fail;
-- }
-- } else {
-- goto fail;
-- }
-- }
--
-- if (sess->server_addr)
-- sess->state = GG_STATE_CONNECTING_GG;
-- else
-- sess->state = GG_STATE_CONNECTING_HUB;
--
-- while (sess->state != GG_STATE_CONNECTED) {
-- struct gg_event *e;
--
-- if (!(e = gg_watch_fd(sess))) {
-- gg_debug(GG_DEBUG_MISC, "// gg_login() critical error in gg_watch_fd()\n");
-- goto fail;
-- }
--
-- if (e->type == GG_EVENT_CONN_FAILED) {
-- errno = EACCES;
-- gg_debug(GG_DEBUG_MISC, "// gg_login() could not login\n");
-- gg_event_free(e);
-- goto fail;
-- }
--
-- gg_event_free(e);
-- }
--
-- return sess;
-- }
--
-- if (!sess->server_addr || gg_proxy_enabled) {
-- if (sess->resolver_start(&sess->fd, &sess->resolver, hostname) == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_login() resolving failed (errno=%d, %s)\n", errno, strerror(errno));
-- goto fail;
-- }
-- } else {
-- if ((sess->fd = gg_connect(&sess->server_addr, sess->port, sess->async)) == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_login() direct connection failed (errno=%d, %s)\n", errno, strerror(errno));
-- goto fail;
-- }
-- sess->state = GG_STATE_CONNECTING_GG;
-- sess->check = GG_CHECK_WRITE;
-- sess->soft_timeout = 1;
-- }
--
-- return sess;
--
--fail:
-- if (sess) {
-- free(sess->password);
-- free(sess->initial_descr);
-- free(sess);
-- }
--
-- return NULL;
--}
--
--/**
-- * Wysyła do serwera pakiet utrzymania połączenia.
-- *
-- * Klient powinien regularnie co minutę wysyłać pakiet utrzymania połączenia,
-- * inaczej serwer uzna, że klient stracił łączność z siecią i zerwie
-- * połączenie.
-- *
-- * \param sess Struktura sesji
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup login
-- */
--int gg_ping(struct gg_session *sess)
--{
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_ping(%p);\n", sess);
--
-- if (!sess) {
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (sess->state != GG_STATE_CONNECTED) {
-- errno = ENOTCONN;
-- return -1;
-- }
--
-- return gg_send_packet(sess, GG_PING, NULL);
--}
--
--/**
-- * Kończy połączenie z serwerem.
-- *
-- * Funkcja nie zwalnia zasobów, więc po jej wywołaniu należy użyć
-- * \c gg_free_session(). Jeśli chce się ustawić opis niedostępności, należy
-- * wcześniej wywołać funkcję \c gg_change_status_descr() lub
-- * \c gg_change_status_descr_time().
-- *
-- * \note Jeśli w buforze nadawczym połączenia z serwerem znajdują się jeszcze
-- * dane (np. z powodu strat pakietów na łączu), prawdopodobnie zostaną one
-- * utracone przy zrywaniu połączenia. Aby mieć pewność, że opis statusu
-- * zostanie zachowany, należy ustawić stan \c GG_STATUS_NOT_AVAIL_DESCR
-- * za pomocą funkcji \c gg_change_status_descr() i poczekać na zdarzenie
-- * \c GG_EVENT_DISCONNECT_ACK.
-- *
-- * \param sess Struktura sesji
-- *
-- * \ingroup login
-- */
--void gg_logoff(struct gg_session *sess)
--{
-- if (!sess)
-- return;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_logoff(%p);\n", sess);
--
--#ifdef GG_CONFIG_HAVE_GNUTLS
-- if (sess->ssl != NULL)
-- gnutls_bye(GG_SESSION_GNUTLS(sess), GNUTLS_SHUT_RDWR);
--#endif
--
--#ifdef GG_CONFIG_HAVE_OPENSSL
-- if (sess->ssl != NULL)
-- SSL_shutdown(sess->ssl);
--#endif
--
-- sess->resolver_cleanup(&sess->resolver, 1);
--
-- if (sess->fd != -1) {
-- shutdown(sess->fd, SHUT_RDWR);
-- close(sess->fd);
-- sess->fd = -1;
-- }
--
--#ifdef GG_CONFIG_HAVE_GNUTLS
-- if (sess->ssl != NULL) {
-- gg_session_gnutls_t *tmp;
--
-- tmp = (gg_session_gnutls_t*) sess->ssl;
-- gnutls_deinit(tmp->session);
-- gnutls_certificate_free_credentials(tmp->xcred);
-- gnutls_global_deinit();
-- free(sess->ssl);
-- }
--#endif
--
-- if (sess->send_buf) {
-- free(sess->send_buf);
-- sess->send_buf = NULL;
-- sess->send_left = 0;
-- }
--}
--
--/**
-- * Zwalnia zasoby używane przez połączenie z serwerem. Funkcję należy wywołać
-- * po zamknięciu połączenia z serwerem, by nie doprowadzić do wycieku zasobów
-- * systemowych.
-- *
-- * \param sess Struktura sesji
-- *
-- * \ingroup login
-- */
--void gg_free_session(struct gg_session *sess)
--{
-- struct gg_dcc7 *dcc;
--
-- if (!sess)
-- return;
--
-- /* XXX dopisać zwalnianie i zamykanie wszystkiego, co mogło zostać */
--
-- free(sess->password);
-- free(sess->initial_descr);
-- free(sess->client_version);
-- free(sess->recv_buf);
-- free(sess->header_buf);
--
--#ifdef GG_CONFIG_HAVE_OPENSSL
-- if (sess->ssl)
-- SSL_free(sess->ssl);
--
-- if (sess->ssl_ctx)
-- SSL_CTX_free(sess->ssl_ctx);
--#endif
--
-- sess->resolver_cleanup(&sess->resolver, 1);
--
-- if (sess->fd != -1)
-- close(sess->fd);
--
-- while (sess->images)
-- gg_image_queue_remove(sess, sess->images, 1);
--
-- free(sess->send_buf);
--
-- for (dcc = sess->dcc7_list; dcc; dcc = dcc->next)
-- dcc->sess = NULL;
--
-- free(sess);
--}
--
--#ifndef DOXYGEN
--
--/**
-- * \internal Funkcja wysyłająca pakiet zmiany statusu użytkownika.
-- *
-- * \param sess Struktura sesji
-- * \param status Nowy status użytkownika
-- * \param descr Opis statusu użytkownika (lub \c NULL)
-- * \param time Czas powrotu w postaci uniksowego znacznika czasu (lub 0)
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup status
-- */
--static int gg_change_status_common(struct gg_session *sess, int status, const char *descr, int time)
--{
-- char *new_descr = NULL;
-- uint32_t new_time;
-- int descr_len = 0;
-- int descr_len_max;
-- int packet_type;
-- int append_null = 0;
-- int res;
--
-- if (!sess) {
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (sess->state != GG_STATE_CONNECTED) {
-- errno = ENOTCONN;
-- return -1;
-- }
--
-- /* XXX, obcinać stany których stary protokół niezna (czyt. dnd->aw; ffc->av) */
--
-- /* dodaj flagę obsługi połączeń głosowych zgodną z GG 7.x */
-- if ((sess->protocol_version >= 0x2a) && (sess->protocol_version < 0x2d /* ? */ ) && (sess->protocol_flags & GG_HAS_AUDIO_MASK) && !GG_S_I(status))
-- status |= GG_STATUS_VOICE_MASK;
--
-- sess->status = status;
--
-- if (sess->protocol_version >= 0x2d) {
-- if (descr != NULL && sess->encoding != GG_ENCODING_UTF8) {
-- new_descr = gg_encoding_convert(descr, GG_ENCODING_CP1250, GG_ENCODING_UTF8, -1, -1);
--
-- if (!new_descr)
-- return -1;
-- }
--
-- if (sess->protocol_version >= 0x2e)
-- packet_type = GG_NEW_STATUS80;
-- else /* sess->protocol_version == 0x2d */
-- packet_type = GG_NEW_STATUS80BETA;
-- descr_len_max = GG_STATUS_DESCR_MAXSIZE;
-- append_null = 1;
--
-- } else {
-- packet_type = GG_NEW_STATUS;
-- descr_len_max = GG_STATUS_DESCR_MAXSIZE_PRE_8_0;
--
-- if (time != 0)
-- append_null = 1;
-- }
--
-- if (descr) {
-- descr_len = strlen((new_descr) ? new_descr : descr);
--
-- if (descr_len > descr_len_max)
-- descr_len = descr_len_max;
--
-- // XXX pamiętać o tym, żeby nie ucinać w środku znaku utf-8
-- }
--
-- if (time)
-- new_time = gg_fix32(time);
--
-- if (packet_type == GG_NEW_STATUS80) {
-- struct gg_new_status80 p;
--
-- p.status = gg_fix32(status);
-- p.flags = gg_fix32(sess->status_flags);
-- p.description_size = gg_fix32(descr_len);
-- res = gg_send_packet(sess,
-- packet_type,
-- &p,
-- sizeof(p),
-- (new_descr) ? new_descr : descr,
-- descr_len,
-- NULL);
--
-- } else {
-- struct gg_new_status p;
--
-- p.status = gg_fix32(status);
-- res = gg_send_packet(sess,
-- packet_type,
-- &p,
-- sizeof(p),
-- (new_descr) ? new_descr : descr,
-- descr_len,
-- (append_null) ? "\0" : NULL,
-- (append_null) ? 1 : 0,
-- (time) ? &new_time : NULL,
-- (time) ? sizeof(new_time) : 0,
-- NULL);
-- }
--
-- free(new_descr);
--
-- if (GG_S_NA(status)) {
-- sess->state = GG_STATE_DISCONNECTING;
-- sess->timeout = GG_TIMEOUT_DISCONNECT;
-- }
--
-- return res;
--}
--
--#endif /* DOXYGEN */
--
--/**
-- * Zmienia status użytkownika.
-- *
-- * \param sess Struktura sesji
-- * \param status Nowy status użytkownika
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup status
-- */
--int gg_change_status(struct gg_session *sess, int status)
--{
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_change_status(%p, %d);\n", sess, status);
--
-- return gg_change_status_common(sess, status, NULL, 0);
--}
--
--/**
-- * Zmienia status użytkownika na status opisowy.
-- *
-- * \param sess Struktura sesji
-- * \param status Nowy status użytkownika
-- * \param descr Opis statusu użytkownika
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup status
-- */
--int gg_change_status_descr(struct gg_session *sess, int status, const char *descr)
--{
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_change_status_descr(%p, %d, \"%s\");\n", sess, status, descr);
--
-- return gg_change_status_common(sess, status, descr, 0);
--}
--
--/**
-- * Zmienia status użytkownika na status opisowy z podanym czasem powrotu.
-- *
-- * \param sess Struktura sesji
-- * \param status Nowy status użytkownika
-- * \param descr Opis statusu użytkownika
-- * \param time Czas powrotu w postaci uniksowego znacznika czasu
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup status
-- */
--int gg_change_status_descr_time(struct gg_session *sess, int status, const char *descr, int time)
--{
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_change_status_descr_time(%p, %d, \"%s\", %d);\n", sess, status, descr, time);
--
-- return gg_change_status_common(sess, status, descr, time);
--}
--
--/**
-- * Funkcja zmieniajÄ…ca flagi statusu.
-- *
-- * \param sess Struktura sesji
-- * \param flags Nowe flagi statusu
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \note Aby zmiany weszły w życie, należy ponownie ustawić status za pomocą
-- * funkcji z rodziny \c gg_change_status().
-- *
-- * \ingroup status
-- */
--int gg_change_status_flags(struct gg_session *sess, int flags)
--{
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_change_status_flags(%p, 0x%08x);\n", sess, flags);
--
-- if (sess == NULL) {
-- errno = EFAULT;
-- return -1;
-- }
--
-- sess->status_flags = flags;
--
-- return 0;
--}
--
--/**
-- * Wysyła wiadomość do użytkownika.
-- *
-- * Zwraca losowy numer sekwencyjny, który można zignorować albo wykorzystać
-- * do potwierdzenia.
-- *
-- * \param sess Struktura sesji
-- * \param msgclass Klasa wiadomości
-- * \param recipient Numer adresata
-- * \param message Treść wiadomości
-- *
-- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
-- *
-- * \ingroup messages
-- */
--int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message)
--{
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message(%p, %d, %u, %p)\n", sess, msgclass, recipient, message);
--
-- return gg_send_message_confer_richtext(sess, msgclass, 1, &recipient, message, NULL, 0);
--}
--
--/**
-- * Wysyła wiadomość formatowaną.
-- *
-- * Zwraca losowy numer sekwencyjny, który można zignorować albo wykorzystać
-- * do potwierdzenia.
-- *
-- * \param sess Struktura sesji
-- * \param msgclass Klasa wiadomości
-- * \param recipient Numer adresata
-- * \param message Treść wiadomości
-- * \param format Informacje o formatowaniu
-- * \param formatlen Długość informacji o formatowaniu
-- *
-- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
-- *
-- * \ingroup messages
-- */
--int gg_send_message_richtext(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, const unsigned char *format, int formatlen)
--{
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_richtext(%p, %d, %u, %p, %p, %d);\n", sess, msgclass, recipient, message, format, formatlen);
--
-- return gg_send_message_confer_richtext(sess, msgclass, 1, &recipient, message, format, formatlen);
--}
--
--/**
-- * Wysyła wiadomość w ramach konferencji.
-- *
-- * Zwraca losowy numer sekwencyjny, który można zignorować albo wykorzystać
-- * do potwierdzenia.
-- *
-- * \param sess Struktura sesji
-- * \param msgclass Klasa wiadomości
-- * \param recipients_count Liczba adresatów
-- * \param recipients Wskaźnik do tablicy z numerami adresatów
-- * \param message Treść wiadomości
-- *
-- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
-- *
-- * \ingroup messages
-- */
--int gg_send_message_confer(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message)
--{
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_confer(%p, %d, %d, %p, %p);\n", sess, msgclass, recipients_count, recipients, message);
--
-- return gg_send_message_confer_richtext(sess, msgclass, recipients_count, recipients, message, NULL, 0);
--}
--
--/**
-- * Wysyła wiadomość formatowaną w ramach konferencji.
-- *
-- * Zwraca losowy numer sekwencyjny, który można zignorować albo wykorzystać
-- * do potwierdzenia.
-- *
-- * \param sess Struktura sesji
-- * \param msgclass Klasa wiadomości
-- * \param recipients_count Liczba adresatów
-- * \param recipients Wskaźnik do tablicy z numerami adresatów
-- * \param message Treść wiadomości
-- * \param format Informacje o formatowaniu
-- * \param formatlen Długość informacji o formatowaniu
-- *
-- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
-- *
-- * \ingroup messages
-- */
--int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message, const unsigned char *format, int formatlen)
--{
-- struct gg_send_msg s;
-- struct gg_send_msg80 s80;
-- struct gg_msg_recipients r;
-- char *cp_msg = NULL;
-- char *utf_msg = NULL;
-- char *html_msg = NULL;
-- int seq_no;
-- int i, j, k;
-- uin_t *recps;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_confer_richtext(%p, %d, %d, %p, %p, %p, %d);\n", sess, msgclass, recipients_count, recipients, message, format, formatlen);
--
-- if (!sess) {
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (sess->state != GG_STATE_CONNECTED) {
-- errno = ENOTCONN;
-- return -1;
-- }
--
-- if (message == NULL || recipients_count <= 0 || recipients_count > 0xffff || (recipients_count != 1 && recipients == NULL)) {
-- errno = EINVAL;
-- return -1;
-- }
--
-- if (sess->encoding == GG_ENCODING_UTF8) {
-- if (!(cp_msg = gg_encoding_convert((const char *) message, GG_ENCODING_UTF8, GG_ENCODING_CP1250, -1, -1)))
-- return -1;
--
-- utf_msg = (char*) message;
-- } else {
-- if (sess->protocol_version >= 0x2d) {
-- if (!(utf_msg = gg_encoding_convert((const char *) message, GG_ENCODING_CP1250, GG_ENCODING_UTF8, -1, -1)))
-- return -1;
-- }
--
-- cp_msg = (char*) message;
-- }
--
-- if (sess->protocol_version < 0x2d) {
-- if (!sess->seq)
-- sess->seq = 0x01740000 | (rand() & 0xffff);
-- seq_no = sess->seq;
-- sess->seq += (rand() % 0x300) + 0x300;
--
-- s.msgclass = gg_fix32(msgclass);
-- s.seq = gg_fix32(seq_no);
-- } else {
-- int len;
--
-- // Drobne odchylenie od protokołu. Jeśli wysyłamy kilka
-- // wiadomości w ciągu jednej sekundy, zwiększamy poprzednią
-- // wartość, żeby każda wiadomość miała unikalny numer.
--
-- seq_no = time(NULL);
--
-- if (seq_no <= sess->seq)
-- seq_no = sess->seq + 1;
--
-- sess->seq = seq_no;
--
-- if (format == NULL || formatlen < 3) {
-- format = (unsigned char*) "\x02\x06\x00\x00\x00\x08\x00\x00\x00";
-- formatlen = 9;
-- }
--
-- len = gg_message_text_to_html(NULL, utf_msg, (char*) format + 3, formatlen - 3);
--
-- html_msg = malloc(len + 1);
--
-- if (html_msg == NULL) {
-- seq_no = -1;
-- goto cleanup;
-- }
--
-- gg_message_text_to_html(html_msg, utf_msg, (char*) format + 3, formatlen - 3);
--
-- s80.seq = gg_fix32(seq_no);
-- s80.msgclass = gg_fix32(msgclass);
-- s80.offset_plain = gg_fix32(sizeof(s80) + strlen(html_msg) + 1);
-- s80.offset_attr = gg_fix32(sizeof(s80) + strlen(html_msg) + 1 + strlen(cp_msg) + 1);
-- }
--
-- if (recipients_count > 1) {
-- r.flag = 0x01;
-- r.count = gg_fix32(recipients_count - 1);
--
-- recps = malloc(sizeof(uin_t) * recipients_count);
--
-- if (!recps) {
-- seq_no = -1;
-- goto cleanup;
-- }
--
-- for (i = 0; i < recipients_count; i++) {
-- for (j = 0, k = 0; j < recipients_count; j++) {
-- if (recipients[j] != recipients[i]) {
-- recps[k] = gg_fix32(recipients[j]);
-- k++;
-- }
-- }
--
-- if (sess->protocol_version < 0x2d) {
-- s.recipient = gg_fix32(recipients[i]);
--
-- if (gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), cp_msg, strlen(cp_msg) + 1, &r, sizeof(r), recps, (recipients_count - 1) * sizeof(uin_t), format, formatlen, NULL) == -1)
-- seq_no = -1;
-- } else {
-- s80.recipient = gg_fix32(recipients[i]);
--
-- if (gg_send_packet(sess, GG_SEND_MSG80, &s80, sizeof(s80), html_msg, strlen(html_msg) + 1, cp_msg, strlen(cp_msg) + 1, &r, sizeof(r), recps, (recipients_count - 1) * sizeof(uin_t), format, formatlen, NULL) == -1)
-- seq_no = -1;
-- }
-- }
--
-- free(recps);
-- } else {
-- if (sess->protocol_version < 0x2d) {
-- s.recipient = gg_fix32(recipients[0]);
--
-- if (gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), cp_msg, strlen(cp_msg) + 1, format, formatlen, NULL) == -1)
-- seq_no = -1;
-- } else {
-- s80.recipient = gg_fix32(recipients[0]);
--
-- if (gg_send_packet(sess, GG_SEND_MSG80, &s80, sizeof(s80), html_msg, strlen(html_msg) + 1, cp_msg, strlen(cp_msg) + 1, format, formatlen, NULL) == -1)
-- seq_no = -1;
-- }
-- }
--
--cleanup:
-- if (cp_msg != (char*) message)
-- free(cp_msg);
--
-- if (utf_msg != (char*) message)
-- free(utf_msg);
--
-- free(html_msg);
--
-- return seq_no;
--}
--
--/**
-- * Wysyła wiadomość binarną przeznaczoną dla klienta.
-- *
-- * Wiadomości między klientami przesyła się np. w celu wywołania zwrotnego
-- * połączenia bezpośredniego. Funkcja zwraca losowy numer sekwencyjny,
-- * który można zignorować albo wykorzystać do potwierdzenia.
-- *
-- * \param sess Struktura sesji
-- * \param msgclass Klasa wiadomości
-- * \param recipient Numer adresata
-- * \param message Treść wiadomości
-- * \param message_len Długość wiadomości
-- *
-- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
-- *
-- * \ingroup messages
-- */
--int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, int message_len)
--{
-- struct gg_send_msg s;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_ctcp(%p, %d, %u, ...);\n", sess, msgclass, recipient);
--
-- if (!sess) {
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (sess->state != GG_STATE_CONNECTED) {
-- errno = ENOTCONN;
-- return -1;
-- }
--
-- s.recipient = gg_fix32(recipient);
-- s.seq = gg_fix32(0);
-- s.msgclass = gg_fix32(msgclass);
--
-- return gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, message_len, NULL);
--}
--
--/**
-- * Wysyła żądanie obrazka o podanych parametrach.
-- *
-- * Wiadomości obrazkowe nie zawierają samych obrazków, a tylko ich rozmiary
-- * i sumy kontrolne. Odbiorca najpierw szuka obrazków w swojej pamięci
-- * podręcznej i dopiero gdy ich nie znajdzie, wysyła żądanie do nadawcy.
-- * Wynik zostanie przekazany zdarzeniem \c GG_EVENT_IMAGE_REPLY.
-- *
-- * \param sess Struktura sesji
-- * \param recipient Numer adresata
-- * \param size Rozmiar obrazka w bajtach
-- * \param crc32 Suma kontrola obrazka
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup messages
-- */
--int gg_image_request(struct gg_session *sess, uin_t recipient, int size, uint32_t crc32)
--{
-- struct gg_send_msg s;
-- struct gg_msg_image_request r;
-- char dummy = 0;
-- int res;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_image_request(%p, %d, %u, 0x%.4x);\n", sess, recipient, size, crc32);
--
-- if (!sess) {
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (sess->state != GG_STATE_CONNECTED) {
-- errno = ENOTCONN;
-- return -1;
-- }
--
-- if (size < 0) {
-- errno = EINVAL;
-- return -1;
-- }
--
-- s.recipient = gg_fix32(recipient);
-- s.seq = gg_fix32(0);
-- s.msgclass = gg_fix32(GG_CLASS_MSG);
--
-- r.flag = 0x04;
-- r.size = gg_fix32(size);
-- r.crc32 = gg_fix32(crc32);
--
-- res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), &dummy, 1, &r, sizeof(r), NULL);
--
-- if (!res) {
-- struct gg_image_queue *q = malloc(sizeof(*q));
-- char *buf;
--
-- if (!q) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_image_request() not enough memory for image queue\n");
-- return -1;
-- }
--
-- buf = malloc(size);
-- if (size && !buf)
-- {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_image_request() not enough memory for image\n");
-- free(q);
-- return -1;
-- }
--
-- memset(q, 0, sizeof(*q));
--
-- q->sender = recipient;
-- q->size = size;
-- q->crc32 = crc32;
-- q->image = buf;
--
-- if (!sess->images)
-- sess->images = q;
-- else {
-- struct gg_image_queue *qq;
--
-- for (qq = sess->images; qq->next; qq = qq->next)
-- ;
--
-- qq->next = q;
-- }
-- }
--
-- return res;
--}
--
--/**
-- * Wysyła żądany obrazek.
-- *
-- * \param sess Struktura sesji
-- * \param recipient Numer adresata
-- * \param filename Nazwa pliku
-- * \param image Bufor z obrazkiem
-- * \param size Rozmiar obrazka
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup messages
-- */
--int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filename, const char *image, int size)
--{
-- struct gg_msg_image_reply *r;
-- struct gg_send_msg s;
-- const char *tmp;
-- char buf[1910];
-- int res = -1;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_image_reply(%p, %d, \"%s\", %p, %d);\n", sess, recipient, filename, image, size);
--
-- if (!sess || !filename || !image) {
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (sess->state != GG_STATE_CONNECTED) {
-- errno = ENOTCONN;
-- return -1;
-- }
--
-- if (size < 0) {
-- errno = EINVAL;
-- return -1;
-- }
--
-- /* wytnij ścieżki, zostaw tylko nazwę pliku */
-- while ((tmp = strrchr(filename, '/')) || (tmp = strrchr(filename, '\\')))
-- filename = tmp + 1;
--
-- if (strlen(filename) < 1 || strlen(filename) > 1024) {
-- errno = EINVAL;
-- return -1;
-- }
--
-- s.recipient = gg_fix32(recipient);
-- s.seq = gg_fix32(0);
-- s.msgclass = gg_fix32(GG_CLASS_MSG);
--
-- buf[0] = 0;
-- r = (void*) &buf[1];
--
-- r->flag = 0x05;
-- r->size = gg_fix32(size);
-- r->crc32 = gg_fix32(gg_crc32(0, (unsigned char*) image, size));
--
-- while (size > 0) {
-- int buflen, chunklen;
--
-- /* \0 + struct gg_msg_image_reply */
-- buflen = sizeof(struct gg_msg_image_reply) + 1;
--
-- /* w pierwszym kawałku jest nazwa pliku */
-- if (r->flag == 0x05) {
-- strcpy(buf + buflen, filename);
-- buflen += strlen(filename) + 1;
-- }
--
-- chunklen = (size >= sizeof(buf) - buflen) ? (sizeof(buf) - buflen) : size;
--
-- memcpy(buf + buflen, image, chunklen);
-- size -= chunklen;
-- image += chunklen;
--
-- res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), buf, buflen + chunklen, NULL);
--
-- if (res == -1)
-- break;
--
-- r->flag = 0x06;
-- }
--
-- return res;
--}
--
--/**
-- * Wysyła do serwera listę kontaktów.
-- *
-- * Funkcja informuje serwer o liście kontaktów, których statusy będą
-- * obserwowane lub kontaktów, które bedą blokowane. Dla każdego z \c count
-- * kontaktów tablica \c userlist zawiera numer, a tablica \c types rodzaj
-- * kontaktu (\c GG_USER_NORMAL, \c GG_USER_OFFLINE, \c GG_USER_BLOCKED).
-- *
-- * Listę kontaktów należy \b zawsze wysyłać po połączeniu, nawet jeśli
-- * jest pusta.
-- *
-- * \param sess Struktura sesji
-- * \param userlist Wskaźnik do tablicy numerów kontaktów
-- * \param types Wskaźnik do tablicy rodzajów kontaktów
-- * \param count Liczba kontaktów
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup contacts
-- */
--int gg_notify_ex(struct gg_session *sess, uin_t *userlist, char *types, int count)
--{
-- struct gg_notify *n;
-- uin_t *u;
-- char *t;
-- int i, res = 0;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_notify_ex(%p, %p, %p, %d);\n", sess, userlist, types, count);
--
-- if (!sess) {
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (sess->state != GG_STATE_CONNECTED) {
-- errno = ENOTCONN;
-- return -1;
-- }
--
-- if (!userlist || !count)
-- return gg_send_packet(sess, GG_LIST_EMPTY, NULL);
--
-- while (count > 0) {
-- int part_count, packet_type;
--
-- if (count > 400) {
-- part_count = 400;
-- packet_type = GG_NOTIFY_FIRST;
-- } else {
-- part_count = count;
-- packet_type = GG_NOTIFY_LAST;
-- }
--
-- if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count)))
-- return -1;
--
-- for (u = userlist, t = types, i = 0; i < part_count; u++, t++, i++) {
-- n[i].uin = gg_fix32(*u);
-- n[i].dunno1 = *t;
-- }
--
-- if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) {
-- free(n);
-- res = -1;
-- break;
-- }
--
-- count -= part_count;
-- userlist += part_count;
-- types += part_count;
--
-- free(n);
-- }
--
-- return res;
--}
--
--/**
-- * Wysyła do serwera listę kontaktów.
-- *
-- * Funkcja jest odpowiednikiem \c gg_notify_ex(), gdzie wszystkie kontakty
-- * sÄ… rodzaju \c GG_USER_NORMAL.
-- *
-- * \param sess Struktura sesji
-- * \param userlist Wskaźnik do tablicy numerów kontaktów
-- * \param count Liczba kontaktów
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup contacts
-- */
--int gg_notify(struct gg_session *sess, uin_t *userlist, int count)
--{
-- struct gg_notify *n;
-- uin_t *u;
-- int i, res = 0;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_notify(%p, %p, %d);\n", sess, userlist, count);
--
-- if (!sess) {
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (sess->state != GG_STATE_CONNECTED) {
-- errno = ENOTCONN;
-- return -1;
-- }
--
-- if (!userlist || !count)
-- return gg_send_packet(sess, GG_LIST_EMPTY, NULL);
--
-- while (count > 0) {
-- int part_count, packet_type;
--
-- if (count > 400) {
-- part_count = 400;
-- packet_type = GG_NOTIFY_FIRST;
-- } else {
-- part_count = count;
-- packet_type = GG_NOTIFY_LAST;
-- }
--
-- if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count)))
-- return -1;
--
-- for (u = userlist, i = 0; i < part_count; u++, i++) {
-- n[i].uin = gg_fix32(*u);
-- n[i].dunno1 = GG_USER_NORMAL;
-- }
--
-- if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) {
-- res = -1;
-- free(n);
-- break;
-- }
--
-- free(n);
--
-- userlist += part_count;
-- count -= part_count;
-- }
--
-- return res;
--}
--
--/**
-- * Dodaje kontakt.
-- *
-- * Dodaje do listy kontaktów dany numer w trakcie połączenia. Aby zmienić
-- * rodzaj kontaktu (np. z normalnego na zablokowany), należy najpierw usunąć
-- * poprzedni rodzaj, ponieważ serwer operuje na maskach bitowych.
-- *
-- * \param sess Struktura sesji
-- * \param uin Numer kontaktu
-- * \param type Rodzaj kontaktu
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup contacts
-- */
--int gg_add_notify_ex(struct gg_session *sess, uin_t uin, char type)
--{
-- struct gg_add_remove a;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_add_notify_ex(%p, %u, %d);\n", sess, uin, type);
--
-- if (!sess) {
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (sess->state != GG_STATE_CONNECTED) {
-- errno = ENOTCONN;
-- return -1;
-- }
--
-- a.uin = gg_fix32(uin);
-- a.dunno1 = type;
--
-- return gg_send_packet(sess, GG_ADD_NOTIFY, &a, sizeof(a), NULL);
--}
--
--/**
-- * Dodaje kontakt.
-- *
-- * Funkcja jest odpowiednikiem \c gg_add_notify_ex(), gdzie rodzaj wszystkich
-- * kontaktów to \c GG_USER_NORMAL.
-- *
-- * \param sess Struktura sesji
-- * \param uin Numer kontaktu
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup contacts
-- */
--int gg_add_notify(struct gg_session *sess, uin_t uin)
--{
-- return gg_add_notify_ex(sess, uin, GG_USER_NORMAL);
--}
--
--/**
-- * Usuwa kontakt.
-- *
-- * Usuwa z listy kontaktów dany numer w trakcie połączenia.
-- *
-- * \param sess Struktura sesji
-- * \param uin Numer kontaktu
-- * \param type Rodzaj kontaktu
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup contacts
-- */
--int gg_remove_notify_ex(struct gg_session *sess, uin_t uin, char type)
--{
-- struct gg_add_remove a;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_remove_notify_ex(%p, %u, %d);\n", sess, uin, type);
--
-- if (!sess) {
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (sess->state != GG_STATE_CONNECTED) {
-- errno = ENOTCONN;
-- return -1;
-- }
--
-- a.uin = gg_fix32(uin);
-- a.dunno1 = type;
--
-- return gg_send_packet(sess, GG_REMOVE_NOTIFY, &a, sizeof(a), NULL);
--}
--
--/**
-- * Usuwa kontakt.
-- *
-- * Funkcja jest odpowiednikiem \c gg_add_notify_ex(), gdzie rodzaj wszystkich
-- * kontaktów to \c GG_USER_NORMAL.
-- *
-- * \param sess Struktura sesji
-- * \param uin Numer kontaktu
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup contacts
-- */
--int gg_remove_notify(struct gg_session *sess, uin_t uin)
--{
-- return gg_remove_notify_ex(sess, uin, GG_USER_NORMAL);
--}
--
--/**
-- * Wysyła do serwera zapytanie dotyczące listy kontaktów.
-- *
-- * Funkcja służy do importu lub eksportu listy kontaktów do serwera.
-- * W odróżnieniu od funkcji \c gg_notify(), ta lista kontaktów jest przez
-- * serwer jedynie przechowywana i nie ma wpływu na połączenie. Format
-- * listy kontaktów jest ignorowany przez serwer, ale ze względu na
-- * kompatybilność z innymi klientami, należy przechowywać dane w tym samym
-- * formacie co oryginalny klient Gadu-Gadu.
-- *
-- * Program nie musi się przejmować fragmentacją listy kontaktów wynikającą
-- * z protokołu -- wysyła i odbiera kompletną listę.
-- *
-- * \param sess Struktura sesji
-- * \param type Rodzaj zapytania
-- * \param request Treść zapytania (może być równe NULL)
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup importexport
-- */
--int gg_userlist_request(struct gg_session *sess, char type, const char *request)
--{
-- int len;
--
-- if (!sess) {
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (sess->state != GG_STATE_CONNECTED) {
-- errno = ENOTCONN;
-- return -1;
-- }
--
-- if (!request) {
-- sess->userlist_blocks = 1;
-- return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), NULL);
-- }
--
-- len = strlen(request);
--
-- sess->userlist_blocks = 0;
--
-- while (len > 2047) {
-- sess->userlist_blocks++;
--
-- if (gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), request, 2047, NULL) == -1)
-- return -1;
--
-- if (type == GG_USERLIST_PUT)
-- type = GG_USERLIST_PUT_MORE;
--
-- request += 2047;
-- len -= 2047;
-- }
--
-- sess->userlist_blocks++;
--
-- return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), request, len, NULL);
--}
--
--/**
-- * Wysyła do serwera zapytanie dotyczące listy kontaktów (10.0).
-- *
-- * Funkcja służy do importu lub eksportu listy kontaktów do serwera.
-- * W odróżnieniu od funkcji \c gg_notify(), ta lista kontaktów jest przez
-- * serwer jedynie przechowywana i nie ma wpływu na połączenie. Format
-- * listy kontaktów jest jednak weryfikowany przez serwer, który stara się
-- * synchronizować listę kontaktów zapisaną w formatach GG 7.0 oraz GG 10.0.
-- * Serwer przyjmuje listy kontaktów przysłane w formacie niezgodnym z podanym
-- * jako \c format_type, ale nie zachowuje ich, a przesłanie takiej listy jest
-- * równoznaczne z usunięciem listy kontaktów.
-- *
-- * Program nie musi się przejmować kompresją listy kontaktów zgodną
-- * z protokołem -- wysyła i odbiera kompletną listę zapisaną czystym tekstem.
-- *
-- * \param sess Struktura sesji
-- * \param type Rodzaj zapytania
-- * \param version Numer ostatniej znanej programowi wersji listy kontaktów lub 0
-- * \param format_type Typ formatu listy kontaktów
-- * \param request Treść zapytania (może być równe NULL)
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup importexport
-- */
--int gg_userlist100_request(struct gg_session *sess, char type, unsigned int version, char format_type, const char *request)
--{
-- struct gg_userlist100_request pkt;
-- unsigned char *zrequest;
-- size_t zrequest_len;
-- int ret;
--
-- if (!sess) {
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (sess->state != GG_STATE_CONNECTED) {
-- errno = ENOTCONN;
-- return -1;
-- }
--
-- pkt.type = type;
-- pkt.version = gg_fix32(version);
-- pkt.format_type = format_type;
-- pkt.unknown1 = 0x01;
--
-- if (request == NULL)
-- return gg_send_packet(sess, GG_USERLIST100_REQUEST, &pkt, sizeof(pkt), NULL);
--
-- zrequest = gg_deflate(request, &zrequest_len);
--
-- if (zrequest == NULL) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_userlist100_request() gg_deflate() failed");
-- return -1;
-- }
--
-- ret = gg_send_packet(sess, GG_USERLIST100_REQUEST, &pkt, sizeof(pkt), zrequest, zrequest_len, NULL);
--
-- free(zrequest);
--
-- return ret;
--}
--
--/**
-- * Informuje rozmówcę o pisaniu wiadomości.
-- *
-- * \param sess Struktura sesji
-- * \param recipient Numer adresata
-- * \param length Długość wiadomości lub 0 jeśli jest pusta
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup messages
-- */
--int gg_typing_notification(struct gg_session *sess, uin_t recipient, int length){
-- struct gg_typing_notification pkt;
-- uin_t uin;
--
-- pkt.length = gg_fix16(length);
-- uin = gg_fix32(recipient);
-- memcpy(&pkt.uin, &uin, sizeof(uin_t));
--
-- return gg_send_packet(sess, GG_TYPING_NOTIFICATION, &pkt, sizeof(pkt), NULL);
--}
--
--/**
-- * Rozłącza inną sesję multilogowania.
-- *
-- * \param gs Struktura sesji
-- * \param conn_id Sesja do rozłączenia
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup login
-- */
--int gg_multilogon_disconnect(struct gg_session *gs, gg_multilogon_id_t conn_id)
--{
-- struct gg_multilogon_disconnect pkt;
--
-- pkt.conn_id = conn_id;
--
-- return gg_send_packet(gs, GG_MULTILOGON_DISCONNECT, &pkt, sizeof(pkt), NULL);
--}
--
--/* @} */
--
--/**
-- * Sprawdza czy biblioteka obsługuje daną funkcję.
-- *
-- * \param feature Identyfikator funkcji.
-- *
-- * \return Wartość niezerowa jeśli funkcja jest obsłgiwana.
-- *
-- * \ingroup version
-- */
--int gg_libgadu_check_feature(gg_libgadu_feature_t feature)
--{
-- switch (feature)
-- {
-- case GG_LIBGADU_FEATURE_SSL:
--#if defined(GG_CONFIG_HAVE_OPENSSL) || defined(GG_CONFIG_HAVE_GNUTLS)
-- return 1;
--#else
-- return 0;
--#endif
--
-- case GG_LIBGADU_FEATURE_PTHREAD:
--#ifdef GG_CONFIG_HAVE_PTHREAD
-- return 1;
--#else
-- return 0;
--#endif
--
-- case GG_LIBGADU_FEATURE_USERLIST100:
--#ifdef GG_CONFIG_HAVE_ZLIB
-- return 1;
--#else
-- return 0;
--#endif
--
-- /* Celowo nie ma default, żeby kompilator wyłapał brakujące funkcje */
--
-- }
--
-- return 0;
--}
--
--/*
-- * Local variables:
-- * c-indentation-style: k&r
-- * c-basic-offset: 8
-- * indent-tabs-mode: notnil
-- * End:
-- *
-- * vim: shiftwidth=8:
-- */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu-config.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu-config.h
---- pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu-config.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu-config.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,59 +0,0 @@
--/* Local libgadu configuration. */
--
--#include "config.h"
--
--#ifndef __GG_LIBGADU_CONFIG_H
--#define __GG_LIBGADU_CONFIG_H
--
--/* Defined if libgadu was compiled for bigendian machine. */
--#undef __GG_LIBGADU_BIGENDIAN
--#ifdef WORDS_BIGENDIAN
--#define __GG_LIBGADU_BIGENDIAN
--#endif /* WORDS_BIGENDIAN */
--
--/* Defined if this machine has va_copy(). */
--#define __GG_LIBGADU_HAVE_VA_COPY
--
--/* Defined if this machine has __va_copy(). */
--#define __GG_LIBGADU_HAVE___VA_COPY
--
--/* Defined if this machine supports long long. */
--#undef __GG_LIBGADU_HAVE_LONG_LONG
--#ifdef HAVE_LONG_LONG
--#define __GG_LIBGADU_HAVE_LONG_LONG
--#endif /* HAVE_LONG_LONG */
--
--/* Defined if libgadu was compiled and linked with pthread support. */
--/* We don't like pthreads. */
--#undef __GG_LIBGADU_HAVE_PTHREAD
--
--/* Defined if libgadu was compiled and linked with GnuTLS encryption support. */
--#ifdef HAVE_GNUTLS
--# define GG_CONFIG_HAVE_GNUTLS
--#else
--# undef GG_CONFIG_HAVE_GNUTLS
--#endif
--
--/* Defined if libgadu was compiled and linked with TLS support. */
--/* Always undefined in Purple. */
--#undef __GG_LIBGADU_HAVE_OPENSSL
--
--/* Include file containing uintXX_t declarations. */
--#if HAVE_STDINT_H
--#include <stdint.h>
--#endif
--
--/* Defined if this machine has C99-compiliant vsnprintf(). */
--#ifndef _WIN32
--#define __GG_LIBGADU_HAVE_C99_VSNPRINTF
--#else
--#undef __GG_LIBGADU_HAVE_C99_VSNPRINTF
--#endif
--
--#define vnsprintf g_vnsprintf
--
--#ifdef _WIN32
--#define random (long) rand
--#endif
--
--#endif /* __GG_LIBGADU_CONFIG_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu-debug.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu-debug.h
---- pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu-debug.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu-debug.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,29 +0,0 @@
--/*
-- * (C) Copyright 2009 Wojtek Kaniewski <wojtekka@irc.pl>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--#ifndef LIBGADU_DEBUG_H
--#define LIBGADU_DEBUG_H
--
--#include "libgadu.h"
--
--const char *gg_debug_state(enum gg_state_t state);
--const char *gg_debug_event(enum gg_event_t event);
--void gg_debug_dump(struct gg_session *sess, int level, const char *buf, size_t len);
--void gg_debug_common(struct gg_session *sess, int level, const char *format, va_list ap);
--
--#endif /* LIBGADU_DEBUG_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu.h
---- pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,2319 +0,0 @@
--/* $Id: libgadu.h.in 1105 2011-05-25 21:34:50Z wojtekka $ */
--
--/*
-- * (C) Copyright 2001-2009 Wojtek Kaniewski <wojtekka@irc.pl>
-- * Robert J. Woźny <speedy@ziew.org>
-- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
-- * Tomasz Chiliński <chilek@chilan.com>
-- * Piotr Wysocki <wysek@linux.bydg.org>
-- * Dawid Jarosz <dawjar@poczta.onet.pl>
-- * Jakub Zawadzki <darkjames@darkjames.ath.cx>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--/**
-- * \file libgadu.h
-- *
-- * \brief Główny plik nagłówkowy biblioteki
-- */
--
--#ifndef __GG_LIBGADU_H
--#define __GG_LIBGADU_H
--
--#ifdef _WIN32
--#pragma pack(push, 1)
--#endif
--
--#ifdef __cplusplus
--extern "C" {
--#endif
--
--#include <sys/types.h>
--#include <stdio.h>
--#include <stdarg.h>
--
--/** \cond ignore */
--
--/* Defined if libgadu was compiled for bigendian machine. */
--#undef GG_CONFIG_BIGENDIAN
--
--/* Defined if this machine has gethostbyname_r(). */
--#undef GG_CONFIG_HAVE_GETHOSTBYNAME_R
--
--/* Defined if libgadu was compiled and linked with pthread support. */
--#undef GG_CONFIG_HAVE_PTHREAD
--
--/* Defined if pthread resolver is the default one. */
--#undef GG_CONFIG_PTHREAD_DEFAULT
--
--/* Defined if this machine has C99-compiliant vsnprintf(). */
--#undef GG_CONFIG_HAVE_C99_VSNPRINTF
--
--/* Defined if this machine has va_copy(). */
--#undef GG_CONFIG_HAVE_VA_COPY
--
--/* Defined if this machine has __va_copy(). */
--#undef GG_CONFIG_HAVE___VA_COPY
--
--/* Defined if this machine supports long long. */
--#undef GG_CONFIG_HAVE_LONG_LONG
--
--/* Defined if libgadu was compiled and linked with GnuTLS support. */
--#undef GG_CONFIG_HAVE_GNUTLS
--
--/* Defined if libgadu was compiled and linked with OpenSSL support. */
--#undef GG_CONFIG_HAVE_OPENSSL
--
--/* Defined if libgadu was compiled and linked with zlib support. */
--#undef GG_CONFIG_HAVE_ZLIB
--
--/* Defined if uintX_t types are defined in <stdint.h>. */
--#undef GG_CONFIG_HAVE_STDINT_H
--
--/* Defined if uintX_t types are defined in <inttypes.h>. */
--#undef GG_CONFIG_HAVE_INTTYPES_H
--
--/* Defined if uintX_t types are defined in <sys/inttypes.h>. */
--#undef GG_CONFIG_HAVE_SYS_INTTYPES_H
--
--/* Defined if uintX_t types are defined in <sys/int_types.h>. */
--#undef GG_CONFIG_HAVE_SYS_INT_TYPES_H
--
--/* Defined if uintX_t types are defined in <sys/types.h>. */
--#undef GG_CONFIG_HAVE_SYS_TYPES_H
--
--#ifdef GG_CONFIG_HAVE_OPENSSL
--#include <openssl/ssl.h>
--#endif
--
--#ifdef GG_CONFIG_HAVE_STDINT_H
--#include <stdint.h>
--#else
--# ifdef GG_CONFIG_HAVE_INTTYPES_H
--# include <inttypes.h>
--# else
--# ifdef GG_CONFIG_HAVE_SYS_INTTYPES_H
--# include <sys/inttypes.h>
--# else
--# ifdef GG_CONFIG_HAVE_SYS_INT_TYPES_H
--# include <sys/int_types.h>
--# else
--# ifdef GG_CONFIG_HAVE_SYS_TYPES_H
--# include <sys/types.h>
--# else
--
--#ifndef __AC_STDINT_H
--#define __AC_STDINT_H
--
--/* ISO C 9X: 7.18 Integer types <stdint.h> */
--
--typedef unsigned char uint8_t;
--typedef unsigned short uint16_t;
--typedef unsigned int uint32_t;
--
--#if !defined(__CYGWIN__) && !defined(__SunOS) && !defined(_INCLUDE_HPUX_SOURCE)
--#define __int8_t_defined
--typedef signed char int8_t;
--typedef signed short int16_t;
--typedef signed int int32_t;
--#endif
--
--#endif /* __AC_STDINT_H */
--
--# endif
--# endif
--# endif
--# endif
--#endif
--
--/** \endcond */
--
--/**
-- * Numer Gadu-Gadu.
-- */
--typedef uint32_t uin_t;
--
--/**
-- * Identyfikator połączenia bezpośredniego Gadu-Gadu 7.x.
-- */
--typedef struct {
-- uint8_t id[8];
--} gg_dcc7_id_t;
--
--/**
-- * Identyfikator sesji multilogowania.
-- */
--typedef struct {
-- uint8_t id[8];
--} gg_multilogon_id_t;
--
--/**
-- * Makro deklarujące pola wspólne dla struktur sesji.
-- */
--#define gg_common_head(x) \
-- int fd; /**< Obserwowany deskryptor */ \
-- int check; /**< Informacja o żądaniu odczytu/zapisu (patrz \ref gg_check_t) */ \
-- int state; /**< Aktualny stan połączenia (patrz \ref gg_state_t) */ \
-- int error; /**< Kod błędu dla \c GG_STATE_ERROR (patrz \ref gg_error_t) */ \
-- int type; /**< Rodzaj sesji (patrz \ref gg_session_t) */ \
-- int id; /**< Identyfikator sesji */ \
-- int timeout; /**< Czas pozostały do zakończenia stanu */ \
-- int (*callback)(x*); /**< Funkcja zwrotna */ \
-- void (*destroy)(x*); /**< Funkcja zwalniania zasobów */
--
--/**
-- * Struktura wspólna dla wszystkich sesji i połączeń. Pozwala na proste
-- * rzutowanie niezależne od rodzaju połączenia.
-- */
--struct gg_common {
-- gg_common_head(struct gg_common)
--};
--
--struct gg_image_queue;
--
--struct gg_dcc7;
--
--struct gg_dcc7_relay;
--
--/**
-- * Sposób rozwiązywania nazw serwerów.
-- */
--typedef enum {
-- GG_RESOLVER_DEFAULT = 0, /**< Domyślny sposób rozwiązywania nazw (jeden z poniższych) */
-- GG_RESOLVER_FORK, /**< RozwiÄ…zywanie nazw bazujÄ…ce na procesach */
-- GG_RESOLVER_PTHREAD, /**< RozwiÄ…zywanie nazw bazujÄ…ce na wÄ…tkach */
-- GG_RESOLVER_WIN32,
-- GG_RESOLVER_CUSTOM, /**< Funkcje rozwiÄ…zywania nazw dostarczone przed aplikacjÄ™ */
-- GG_RESOLVER_INVALID = -1 /**< Nieprawidłowy sposób rozwiązywania nazw (wynik \c gg_session_get_resolver) */
--} gg_resolver_t;
--
--/**
-- * Rodzaj kodowania znaków.
-- */
--typedef enum {
-- GG_ENCODING_CP1250 = 0, /**< Kodowanie CP1250 */
-- GG_ENCODING_UTF8, /**< Kodowanie UTF-8 */
-- GG_ENCODING_INVALID = -1 /**< Nieprawidłowe kodowanie */
--} gg_encoding_t;
--
--/**
-- * Sesja Gadu-Gadu.
-- *
-- * Tworzona przez funkcjÄ™ \c gg_login(), zwalniana przez \c gg_free_session().
-- *
-- * \ingroup login
-- */
--struct gg_session {
-- gg_common_head(struct gg_session)
--
-- int async; /**< Flaga połączenia asynchronicznego */
-- int pid; /**< Numer procesu rozwiÄ…zujÄ…cego nazwÄ™ serwera */
-- int port; /**< Port serwera */
-- int seq; /**< Numer sekwencyjny ostatniej wiadomości */
-- int last_pong; /**< Czas otrzymania ostatniej ramki utrzymaniowej */
-- int last_event; /**< Czas otrzymania ostatniego pakietu */
--
-- struct gg_event *event; /**< Zdarzenie po wywołaniu \c callback */
--
-- uint32_t proxy_addr; /**< Adres serwera pośredniczącego */
-- uint16_t proxy_port; /**< Port serwera pośredniczącego */
--
-- uint32_t hub_addr; /**< Adres huba po rozwiÄ…zaniu nazwy */
-- uint32_t server_addr; /**< Adres serwera otrzymany od huba */
--
-- uint32_t client_addr; /**< Adres gniazda dla połączeń bezpośrednich */
-- uint16_t client_port; /**< Port gniazda dla połączeń bezpośrednich */
--
-- uint32_t external_addr; /**< Publiczny adres dla połączeń bezpośrednich */
-- uint16_t external_port; /**< Publiczny port dla połączeń bezpośrednich */
--
-- uin_t uin; /**< WÅ‚asny numer Gadu-Gadu */
-- char *password; /**< Hasło (zwalniane po użyciu) */
--
-- int initial_status; /**< PoczÄ…tkowy status */
-- int status; /**< Aktualny status */
--
-- char *recv_buf; /**< Bufor na odbierany pakiety */
-- int recv_done; /**< Liczba wczytanych bajtów pakietu */
-- int recv_left; /**< Liczba pozostałych do wczytania bajtów pakietu */
--
-- int protocol_version; /**< Wersja protokołu (bez flag) */
-- char *client_version; /**< Wersja klienta */
-- int last_sysmsg; /**< Numer ostatniej wiadomości systemowej */
--
-- char *initial_descr; /**< PoczÄ…tkowy opis statusu */
--
-- void *resolver; /**< Dane prywatne procesu lub wÄ…tku rozwiÄ…zujÄ…cego nazwÄ™ serwera */
--
-- char *header_buf; /**< Bufor na początek nagłówka pakietu */
-- unsigned int header_done; /**< Liczba wczytanych bajtów nagłówka pakietu */
--
--#ifdef GG_CONFIG_HAVE_OPENSSL
-- SSL *ssl; /**< Struktura TLS */
-- SSL_CTX *ssl_ctx; /**< Kontekst sesji TLS */
--#else
-- void *ssl; /**< Struktura TLS */
-- void *ssl_ctx; /**< Kontekst sesji TLS */
--#endif
--
-- int image_size; /**< Maksymalny rozmiar obsługiwanych obrazków w KiB */
--
-- char *userlist_reply; /**< Bufor z odbieraną listą kontaktów */
--
-- int userlist_blocks; /**< Liczba części listy kontaktów */
--
-- struct gg_image_queue *images; /**< Lista wczytywanych obrazków */
--
-- int hash_type; /**< Rodzaj funkcji skrótu hasła (\c GG_LOGIN_HASH_GG32 lub \c GG_LOGIN_HASH_SHA1) */
--
-- char *send_buf; /**< Bufor z danymi do wysłania */
-- int send_left; /**< Liczba bajtów do wysłania */
--
-- struct gg_dcc7 *dcc7_list; /**< Lista połączeń bezpośrednich skojarzonych z sesją */
--
-- int soft_timeout; /**< Flaga mówiąca, że po przekroczeniu \c timeout należy wywołać \c gg_watch_fd() */
--
-- int protocol_flags; /**< Flagi protokołu */
--
-- gg_encoding_t encoding; /**< Rodzaj kodowania znaków */
--
-- gg_resolver_t resolver_type; /**< Sposób rozwiązywania nazw serwerów */
-- int (*resolver_start)(int *fd, void **private_data, const char *hostname); /**< Funkcja rozpoczynajÄ…ca rozwiÄ…zywanie nazwy */
-- void (*resolver_cleanup)(void **private_data, int force); /**< Funkcja zwalniajÄ…ca zasoby po rozwiÄ…zaniu nazwy */
--
-- int protocol_features; /**< Opcje protokołu */
-- int status_flags; /**< Flagi statusu */
-- int recv_msg_count; /**< Liczba odebranych wiadomości */
--};
--
--/**
-- * Połączenie HTTP.
-- *
-- * Tworzone przez \c gg_http_connect(), zwalniane przez \c gg_http_free().
-- *
-- * \ingroup http
-- */
--struct gg_http {
-- gg_common_head(struct gg_http)
--
-- int async; /**< Flaga połączenia asynchronicznego */
-- int pid; /**< Identyfikator procesu rozwiÄ…zujÄ…cego nazwÄ™ serwera */
-- int port; /**< Port */
--
-- char *query; /**< Zapytanie HTTP */
-- char *header; /**< Odebrany nagłówek */
-- int header_size; /**< Rozmiar wczytanego nagłówka */
-- char *body; /**< Odebrana strona */
-- unsigned int body_size; /**< Rozmiar strony */
--
-- void *data; /**< Dane prywatne usługi HTTP */
--
-- char *user_data; /**< Dane prywatne użytkownika (nie są zwalniane) */
--
-- void *resolver; /**< Dane prywatne procesu lub wÄ…tku rozwiÄ…zujÄ…cego nazwÄ™ */
--
-- unsigned int body_done; /**< Liczba odebranych bajtów strony */
--
-- gg_resolver_t resolver_type; /**< Sposób rozwiązywania nazw serwerów */
-- int (*resolver_start)(int *fd, void **private_data, const char *hostname); /**< Funkcja rozpoczynajÄ…ca rozwiÄ…zywanie nazwy */
-- void (*resolver_cleanup)(void **private_data, int force); /**< Funkcja zwalniajÄ…ca zasoby po rozwiÄ…zaniu nazwy */
--};
--
--/** \cond ignore */
--
--#ifdef __GNUC__
--#define GG_PACKED __attribute__ ((packed))
--#ifndef GG_IGNORE_DEPRECATED
--#define GG_DEPRECATED __attribute__ ((deprecated))
--#else
--#define GG_DEPRECATED
--#endif
--#else
--#define GG_PACKED
--#define GG_DEPRECATED
--#endif
--
--/** \endcond */
--
--#define GG_MAX_PATH 276 /**< Maksymalny rozmiar nazwy pliku w strukturze \c gg_file_info */
--
--/**
-- * Odpowiednik struktury WIN32_FIND_DATA z API WIN32.
-- *
-- * Wykorzystywana przy połączeniach bezpośrednich do wersji Gadu-Gadu 6.x.
-- */
--struct gg_file_info {
-- uint32_t mode; /**< dwFileAttributes */
-- uint32_t ctime[2]; /**< ftCreationTime */
-- uint32_t atime[2]; /**< ftLastAccessTime */
-- uint32_t mtime[2]; /**< ftLastWriteTime */
-- uint32_t size_hi; /**< nFileSizeHigh */
-- uint32_t size; /**< nFileSizeLow */
-- uint32_t reserved0; /**< dwReserved0 */
-- uint32_t reserved1; /**< dwReserved1 */
-- unsigned char filename[GG_MAX_PATH - 14]; /**< cFileName */
-- unsigned char short_filename[14]; /**< cAlternateFileName */
--} /** \cond ignore */ GG_PACKED /** \endcond */;
--
--/**
-- * Połączenie bezpośrednie do wersji Gadu-Gadu 6.x.
-- *
-- * Tworzone przez \c gg_dcc_socket_create(), \c gg_dcc_get_file(),
-- * \c gg_dcc_send_file() lub \c gg_dcc_voice_chat(), zwalniane przez
-- * \c gg_dcc_free().
-- *
-- * \ingroup dcc6
-- */
--struct gg_dcc {
-- gg_common_head(struct gg_dcc)
--
-- struct gg_event *event; /**< Zdarzenie po wywołaniu \c callback */
--
-- int active; /**< Flaga połączenia aktywnego (nieużywana) */
-- int port; /**< Port gniazda nasłuchującego */
-- uin_t uin; /**< WÅ‚asny numer Gadu-Gadu */
-- uin_t peer_uin; /**< Numer Gadu-Gadu drugiej strony połączenia */
-- int file_fd; /**< deskryptor pliku */
-- unsigned int offset; /**< Położenie w pliku */
-- unsigned int chunk_size;
-- /**< Rozmiar kawałka pliku */
-- unsigned int chunk_offset;
-- /**< Położenie w aktualnym kawałku pliku */
-- struct gg_file_info file_info;
-- /**< Informacje o pliku */
-- int established; /**< Flaga ustanowienia połączenia */
-- char *voice_buf; /**< Bufor na pakiet połączenia głosowego */
-- int incoming; /**< Flaga połączenia przychodzącego */
-- char *chunk_buf; /**< Bufor na fragment danych */
-- uint32_t remote_addr; /**< Adres drugiej strony */
-- uint16_t remote_port; /**< Port drugiej strony */
--};
--
--#define GG_DCC7_HASH_LEN 20 /**< Maksymalny rozmiar skrótu pliku w połączeniach bezpośrenich */
--#define GG_DCC7_FILENAME_LEN 255 /**< Maksymalny rozmiar nazwy pliku w połączeniach bezpośrednich */
--#define GG_DCC7_INFO_LEN 32 /**< Maksymalny rozmiar informacji o połączeniach bezpośrednich */
--#define GG_DCC7_INFO_HASH_LEN 32 /**< Maksymalny rozmiar skrótu ip informacji o połączeniach bezpośrednich */
--
--/**
-- * Połączenie bezpośrednie od wersji Gadu-Gadu 7.x.
-- *
-- * \ingroup dcc7
-- */
--struct gg_dcc7 {
-- gg_common_head(struct gg_dcc7)
--
-- gg_dcc7_id_t cid; /**< Identyfikator połączenia */
--
-- struct gg_event *event; /**< Struktura zdarzenia */
--
-- uin_t uin; /**< WÅ‚asny numer Gadu-Gadu */
-- uin_t peer_uin; /**< Numer Gadu-Gadu drugiej strony połączenia */
--
-- int file_fd; /**< Deskryptor przesyłanego pliku */
-- unsigned int offset; /**< Aktualne położenie w przesyłanym pliku */
-- unsigned int size; /**< Rozmiar przesyłanego pliku */
-- unsigned char filename[GG_DCC7_FILENAME_LEN + 1];
-- /**< Nazwa przesyłanego pliku */
-- unsigned char hash[GG_DCC7_HASH_LEN];
-- /**< Skrót SHA1 przesyłanego pliku */
--
-- int dcc_type; /**< Rodzaj połączenia bezpośredniego */
-- int established; /**< Flaga ustanowienia połączenia */
-- int incoming; /**< Flaga połączenia przychodzącego */
-- int reverse; /**< Flaga połączenia zwrotnego */
--
-- uint32_t local_addr; /**< Adres lokalny */
-- uint16_t local_port; /**< Port lokalny */
--
-- uint32_t remote_addr; /**< Adres drugiej strony */
-- uint16_t remote_port; /**< Port drugiej strony */
--
-- struct gg_session *sess;
-- /**< Sesja do której przypisano połączenie */
-- struct gg_dcc7 *next; /**< Następne połączenie w liście */
--
-- int soft_timeout; /**< Flaga mówiąca, że po przekroczeniu \c timeout należy wywołać \c gg_dcc7_watch_fd() */
-- int seek; /**< Flaga mówiąca, że można zmieniać położenie w wysyłanym pliku */
--
-- void *resolver; /**< Dane prywatne procesu lub wÄ…tku rozwiÄ…zujÄ…cego nazwÄ™ serwera */
--
-- int relay; /**< Flaga mówiąca, że laczymy sie przez serwer */
-- int relay_index; /**< Numer serwera pośredniczącego, do którego się łączymy */
-- int relay_count; /**< Rozmiar listy serwerów pośredniczących */
-- struct gg_dcc7_relay *relay_list; /**< Lista serwerów pośredniczących */
--};
--
--/**
-- * Rodzaj sesji.
-- */
--enum gg_session_t {
-- GG_SESSION_GG = 1, /**< Połączenie z serwerem Gadu-Gadu */
-- GG_SESSION_HTTP, /**< Połączenie HTTP */
-- GG_SESSION_SEARCH, /**< Wyszukiwanie w katalogu publicznym (nieaktualne) */
-- GG_SESSION_REGISTER, /**< Rejestracja nowego konta */
-- GG_SESSION_REMIND, /**< Przypominanie hasła */
-- GG_SESSION_PASSWD, /**< Zmiana hasła */
-- GG_SESSION_CHANGE, /**< Zmiana informacji w katalogu publicznym (nieaktualne) */
-- GG_SESSION_DCC, /**< Połączenie bezpośrednie (do wersji 6.x) */
-- GG_SESSION_DCC_SOCKET, /**< Gniazdo nasłuchujące (do wersji 6.x) */
-- GG_SESSION_DCC_SEND, /**< Wysyłanie pliku (do wersji 6.x) */
-- GG_SESSION_DCC_GET, /**< Odbieranie pliku (do wersji 6.x) */
-- GG_SESSION_DCC_VOICE, /**< Rozmowa głosowa (do wersji 6.x) */
-- GG_SESSION_USERLIST_GET, /**< Import listy kontaktów z serwera (nieaktualne) */
-- GG_SESSION_USERLIST_PUT, /**< Eksport listy kontaktów do serwera (nieaktualne) */
-- GG_SESSION_UNREGISTER, /**< Usuwanie konta */
-- GG_SESSION_USERLIST_REMOVE, /**< Usuwanie listy kontaktów z serwera (nieaktualne) */
-- GG_SESSION_TOKEN, /**< Pobieranie tokenu */
-- GG_SESSION_DCC7_SOCKET, /**< Gniazdo nasłuchujące (od wersji 7.x) */
-- GG_SESSION_DCC7_SEND, /**< Wysyłanie pliku (od wersji 7.x) */
-- GG_SESSION_DCC7_GET, /**< Odbieranie pliku (od wersji 7.x) */
-- GG_SESSION_DCC7_VOICE, /**< Rozmowa głosowa (od wersji 7.x) */
--
-- GG_SESSION_USER0 = 256, /**< Rodzaj zadeklarowany dla użytkownika */
-- GG_SESSION_USER1, /**< Rodzaj zadeklarowany dla użytkownika */
-- GG_SESSION_USER2, /**< Rodzaj zadeklarowany dla użytkownika */
-- GG_SESSION_USER3, /**< Rodzaj zadeklarowany dla użytkownika */
-- GG_SESSION_USER4, /**< Rodzaj zadeklarowany dla użytkownika */
-- GG_SESSION_USER5, /**< Rodzaj zadeklarowany dla użytkownika */
-- GG_SESSION_USER6, /**< Rodzaj zadeklarowany dla użytkownika */
-- GG_SESSION_USER7 /**< Rodzaj zadeklarowany dla użytkownika */
--};
--
--/**
-- * Aktualny stan sesji.
-- */
--enum gg_state_t {
-- /* wspólne */
-- GG_STATE_IDLE = 0, /**< Nie dzieje siÄ™ nic */
-- GG_STATE_RESOLVING, /**< Oczekiwanie na rozwiÄ…zanie nazwy serwera */
-- GG_STATE_CONNECTING, /**< Oczekiwanie na połączenie */
-- GG_STATE_READING_DATA, /**< Oczekiwanie na dane */
-- GG_STATE_ERROR, /**< Kod błędu w polu \c error */
--
-- /* gg_session */
-- GG_STATE_CONNECTING_HUB, /**< Oczekiwanie na połączenie z hubem */
-- GG_STATE_CONNECTING_GG, /**< Oczekiwanie na połączenie z serwerem */
-- GG_STATE_READING_KEY, /**< Oczekiwanie na klucz */
-- GG_STATE_READING_REPLY, /**< Oczekiwanie na odpowiedź serwera */
-- GG_STATE_CONNECTED, /**< Połączono z serwerem */
--
-- /* gg_http */
-- GG_STATE_SENDING_QUERY, /**< Wysłano zapytanie HTTP */
-- GG_STATE_READING_HEADER, /**< Oczekiwanie na nagłówek HTTP */
-- GG_STATE_PARSING, /**< Przetwarzanie danych */
-- GG_STATE_DONE, /**< Połączenie zakończone */
--
-- /* gg_dcc */
-- GG_STATE_LISTENING, /* czeka na połączenia */
-- GG_STATE_READING_UIN_1, /* czeka na uin peera */
-- GG_STATE_READING_UIN_2, /* czeka na swój uin */
-- GG_STATE_SENDING_ACK, /* wysyła potwierdzenie dcc */
-- GG_STATE_READING_ACK, /* czeka na potwierdzenie dcc */
-- GG_STATE_READING_REQUEST, /* czeka na komendÄ™ */
-- GG_STATE_SENDING_REQUEST, /* wysyła komendę */
-- GG_STATE_SENDING_FILE_INFO, /* wysyła informacje o pliku */
-- GG_STATE_READING_PRE_FILE_INFO, /* czeka na pakiet przed file_info */
-- GG_STATE_READING_FILE_INFO, /* czeka na informacje o pliku */
-- GG_STATE_SENDING_FILE_ACK, /* wysyła potwierdzenie pliku */
-- GG_STATE_READING_FILE_ACK, /* czeka na potwierdzenie pliku */
-- GG_STATE_SENDING_FILE_HEADER, /* wysyła nagłówek pliku */
-- GG_STATE_READING_FILE_HEADER, /* czeka na nagłówek */
-- GG_STATE_GETTING_FILE, /* odbiera plik */
-- GG_STATE_SENDING_FILE, /* wysyła plik */
-- GG_STATE_READING_VOICE_ACK, /* czeka na potwierdzenie voip */
-- GG_STATE_READING_VOICE_HEADER, /* czeka na rodzaj bloku voip */
-- GG_STATE_READING_VOICE_SIZE, /* czeka na rozmiar bloku voip */
-- GG_STATE_READING_VOICE_DATA, /* czeka na dane voip */
-- GG_STATE_SENDING_VOICE_ACK, /* wysyła potwierdzenie voip */
-- GG_STATE_SENDING_VOICE_REQUEST, /* wysyła żądanie voip */
-- GG_STATE_READING_TYPE, /* czeka na typ połączenia */
--
-- /* nowe. bez sensu jest to API. */
-- GG_STATE_TLS_NEGOTIATION, /**< Negocjacja połączenia szyfrowanego */
--
-- GG_STATE_REQUESTING_ID, /**< Oczekiwanie na nadanie identyfikatora połączenia bezpośredniego */
-- GG_STATE_WAITING_FOR_ACCEPT, /**< Oczekiwanie na potwierdzenie lub odrzucenie połączenia bezpośredniego */
-- GG_STATE_WAITING_FOR_INFO, /**< Oczekiwanie na informacje o połączeniu bezpośrednim */
--
-- GG_STATE_READING_ID, /**< Odebranie identyfikatora połączenia bezpośredniego */
-- GG_STATE_SENDING_ID, /**< Wysłano identyfikator połączenia bezpośredniego */
-- GG_STATE_RESOLVING_GG, /**< Oczekiwanie na rozwiÄ…zanie nazwy serwera Gadu-Gadu */
--
-- GG_STATE_RESOLVING_RELAY, /**< Oczekiwanie na rozwiązanie nazwy serwera pośredniczącego */
-- GG_STATE_CONNECTING_RELAY, /**< Oczekiwanie na połączenie z serwerem pośredniczącym */
-- GG_STATE_READING_RELAY, /**< Odbieranie danych */
--
-- GG_STATE_DISCONNECTING, /**< Oczekiwanie na potwierdzenie rozłączenia */
--};
--
--/**
-- * Informacja o tym, czy biblioteka chce zapisywać i/lub czytać
-- * z deskryptora. Maska bitowa.
-- *
-- * \ingroup events
-- */
--enum gg_check_t {
-- GG_CHECK_NONE = 0, /**< Nie sprawdzaj niczego */
-- GG_CHECK_WRITE = 1, /**< Sprawdź możliwość zapisu */
-- GG_CHECK_READ = 2 /**< Sprawdź możliwość odczytu */
--};
--
--/**
-- * Flaga połączenia szyfrowanego.
-- *
-- * \ingroup login
-- */
--typedef enum {
-- GG_SSL_DISABLED = 0, /**< Połączenie SSL wyłączone */
-- GG_SSL_ENABLED, /**< Połączenie SSL włączone gdy dostępne */
-- GG_SSL_REQUIRED /**< Połączenie SSL wymagane */
--} gg_ssl_t;
--
--/**
-- * Parametry połączenia z serwerem Gadu-Gadu. Parametry zostały przeniesione
-- * do struktury, by uniknąć zmian API po rozszerzeniu protokołu i dodaniu
-- * kolejnych opcji połączenia. Część parametrów, które nie są już aktualne
-- * lub nie mają znaczenia, została usunięta z dokumentacji.
-- *
-- * \ingroup login
-- */
--struct gg_login_params {
-- uin_t uin; /**< Numer Gadu-Gadu */
-- char *password; /**< Hasło */
-- int async; /**< Flaga asynchronicznego połączenia (domyślnie nie) */
-- int status; /**< Początkowy status użytkownika (domyślnie \c GG_STATUS_AVAIL) */
-- char *status_descr; /**< Początkowy opis użytkownika (domyślnie brak) */
-- uint32_t server_addr; /**< Adres serwera Gadu-Gadu (domyślnie pobierany automatycznie) */
-- uint16_t server_port; /**< Port serwera Gadu-Gadu (domyślnie pobierany automatycznie) */
-- uint32_t client_addr; /**< Adres połączeń bezpośrednich (domyślnie dobierany automatycznie) */
-- uint16_t client_port; /**< Port połączeń bezpośrednich (domyślnie dobierany automatycznie) */
-- int protocol_version; /**< Wersja protokołu wysyłana do serwera (domyślnie najnowsza obsługiwana) */
-- char *client_version; /**< Wersja klienta wysyłana do serwera (domyślnie najnowsza znana) */
-- int has_audio; /**< Flaga obsługi połączeń głosowych */
-- int last_sysmsg; /**< Numer ostatnio odebranej wiadomości systemowej */
-- uint32_t external_addr; /**< Adres publiczny dla połączeń bezpośrednich (domyślnie dobierany automatycznie) */
-- uint16_t external_port; /**< Port publiczny dla połączeń bezpośrednich (domyślnie dobierany automatycznie) */
-- int tls; /**< Flaga połączenia szyfrowanego (patrz \ref gg_ssl_t) */
-- int image_size; /**< Maksymalny rozmiar obsługiwanych obrazków w kilobajtach */
--#ifndef DOXYGEN
-- int era_omnix; /**< Flaga udawania klienta Era Omnix (nieaktualna) */
--#endif
-- int hash_type; /**< Rodzaj skrótu hasła (\c GG_LOGIN_HASH_GG32 lub \c GG_LOGIN_HASH_SHA1, domyślnie SHA1) */
-- gg_encoding_t encoding; /**< Rodzaj kodowania używanego w sesji (domyślnie CP1250) */
-- gg_resolver_t resolver; /**< Sposób rozwiązywania nazw (patrz \ref build-resolver) */
-- int protocol_features; /**< Opcje protokołu (flagi GG_FEATURE_*). */
-- int status_flags; /**< Flagi statusu (flagi GG_STATUS_FLAG_*, patrz \ref status). */
--
--#ifndef DOXYGEN
-- char dummy[1 * sizeof(int)]; /**< \internal Miejsce na kilka kolejnych
-- parametrów, żeby wraz z dodawaniem kolejnych
-- parametrów nie zmieniał się rozmiar struktury */
--#endif
--
--};
--
--struct gg_session *gg_login(const struct gg_login_params *p);
--void gg_free_session(struct gg_session *sess);
--void gg_logoff(struct gg_session *sess);
--int gg_change_status(struct gg_session *sess, int status);
--int gg_change_status_descr(struct gg_session *sess, int status, const char *descr);
--int gg_change_status_descr_time(struct gg_session *sess, int status, const char *descr, int time);
--int gg_change_status_flags(struct gg_session *sess, int flags);
--int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message);
--int gg_send_message_richtext(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, const unsigned char *format, int formatlen);
--int gg_send_message_confer(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message);
--int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message, const unsigned char *format, int formatlen);
--int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, int message_len);
--int gg_ping(struct gg_session *sess);
--int gg_userlist_request(struct gg_session *sess, char type, const char *request);
--int gg_userlist100_request(struct gg_session *sess, char type, unsigned int version, char format_type, const char *request);
--int gg_image_request(struct gg_session *sess, uin_t recipient, int size, uint32_t crc32);
--int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filename, const char *image, int size);
--int gg_typing_notification(struct gg_session *sess, uin_t recipient, int length);
--
--uint32_t gg_crc32(uint32_t crc, const unsigned char *buf, int len);
--
--int gg_session_set_resolver(struct gg_session *gs, gg_resolver_t type);
--gg_resolver_t gg_session_get_resolver(struct gg_session *gs);
--int gg_session_set_custom_resolver(struct gg_session *gs, int (*resolver_start)(int*, void**, const char*), void (*resolver_cleanup)(void**, int));
--
--int gg_http_set_resolver(struct gg_http *gh, gg_resolver_t type);
--gg_resolver_t gg_http_get_resolver(struct gg_http *gh);
--int gg_http_set_custom_resolver(struct gg_http *gh, int (*resolver_start)(int*, void**, const char*), void (*resolver_cleanup)(void**, int));
--
--int gg_global_set_resolver(gg_resolver_t type);
--gg_resolver_t gg_global_get_resolver(void);
--int gg_global_set_custom_resolver(int (*resolver_start)(int*, void**, const char*), void (*resolver_cleanup)(void**, int));
--
--int gg_multilogon_disconnect(struct gg_session *gs, gg_multilogon_id_t conn_id);
--
--/**
-- * Rodzaj zdarzenia.
-- *
-- * \ingroup events
-- */
--enum gg_event_t {
-- GG_EVENT_NONE = 0, /**< Nie wydarzyło się nic wartego uwagi */
-- GG_EVENT_MSG, /**< \brief Otrzymano wiadomość. Przekazuje również wiadomości systemowe od numeru 0. */
-- GG_EVENT_NOTIFY, /**< \brief Informacja o statusach osób z listy kontaktów (przed 6.0). Zdarzenie należy obsługiwać, jeśli planuje się używać protokołu w wersji starszej niż domyślna. Ostatni element tablicy zawiera uin równy 0, a pozostałe pola są niezainicjowane. */
-- GG_EVENT_NOTIFY_DESCR, /**< \brief Informacja o statusie opisowym osoby z listy kontaktów (przed 6.0). Zdarzenie należy obsługiwać, jeśli planuje się używać protokołu w wersji starszej niż domyślna. */
-- GG_EVENT_STATUS, /**< \brief Zmiana statusu osoby z listy kontaktów (przed 6.0). Zdarzenie należy obsługiwać, jeśli planuje się używać protokołu w wersji starszej niż domyślna. */
-- GG_EVENT_ACK, /**< Potwierdzenie doręczenia wiadomości */
-- GG_EVENT_PONG, /**< \brief Utrzymanie połączenia. Obecnie serwer nie wysyła już do klienta ramek utrzymania połączenia, polega wyłącznie na wysyłaniu ramek przez klienta. */
-- GG_EVENT_CONN_FAILED, /**< \brief Nie udało się połączyć */
-- GG_EVENT_CONN_SUCCESS, /**< \brief Połączono z serwerem. Pierwszą rzeczą, jaką należy zrobić jest wysłanie listy kontaktów. */
-- GG_EVENT_DISCONNECT, /**< \brief Serwer zrywa połączenie. Zdarza się, gdy równolegle do serwera podłączy się druga sesja i trzeba zerwać połączenie z pierwszą. */
--
-- GG_EVENT_DCC_NEW, /**< Nowe połączenie bezpośrednie (6.x) */
-- GG_EVENT_DCC_ERROR, /**< Błąd połączenia bezpośredniego (6.x) */
-- GG_EVENT_DCC_DONE, /**< Zakończono połączenie bezpośrednie (6.x) */
-- GG_EVENT_DCC_CLIENT_ACCEPT, /**< Moment akceptacji klienta w połączeniu bezpośrednim (6.x) */
-- GG_EVENT_DCC_CALLBACK, /**< Zwrotne połączenie bezpośrednie (6.x) */
-- GG_EVENT_DCC_NEED_FILE_INFO, /**< Należy wypełnić \c file_info dla połączenia bezpośredniego (6.x) */
-- GG_EVENT_DCC_NEED_FILE_ACK, /**< Czeka na potwierdzenie pliku w połączeniu bezpośrednim (6.x) */
-- GG_EVENT_DCC_NEED_VOICE_ACK, /**< Czeka na potwierdzenie rozmowy w połączeniu bezpośrednim (6.x) */
-- GG_EVENT_DCC_VOICE_DATA, /**< Dane bezpośredniego połączenia głosowego (6.x) */
--
-- GG_EVENT_PUBDIR50_SEARCH_REPLY, /**< Odpowiedź katalogu publicznego */
-- GG_EVENT_PUBDIR50_READ, /**< Odczytano własne dane z katalogu publicznego */
-- GG_EVENT_PUBDIR50_WRITE, /**< Zmieniono własne dane w katalogu publicznym */
--
-- GG_EVENT_STATUS60, /**< Zmiana statusu osoby z listy kontaktów */
-- GG_EVENT_NOTIFY60, /**< Informacja o statusach osób z listy kontaktów. Ostatni element tablicy zawiera uin równy 0, a pozostałe pola są niezainicjowane. */
-- GG_EVENT_USERLIST, /**< Wynik importu lub eksportu listy kontaktów */
-- GG_EVENT_IMAGE_REQUEST, /**< Żądanie przesłania obrazka z wiadomości */
-- GG_EVENT_IMAGE_REPLY, /**< Przysłano obrazek z wiadomości */
-- GG_EVENT_DCC_ACK, /**< Potwierdzenie transmisji w połączeniu bezpośrednim (6.x) */
--
-- GG_EVENT_DCC7_NEW, /**< Nowe połączenie bezpośrednie (7.x) */
-- GG_EVENT_DCC7_ACCEPT, /**< Zaakceptowano połączenie bezpośrednie (7.x), nowy deskryptor */
-- GG_EVENT_DCC7_REJECT, /**< Odrzucono połączenie bezpośrednie (7.x) */
-- GG_EVENT_DCC7_CONNECTED, /**< Zestawiono połączenie bezpośrednie (7.x), nowy deskryptor */
-- GG_EVENT_DCC7_ERROR, /**< Błąd połączenia bezpośredniego (7.x) */
-- GG_EVENT_DCC7_DONE, /**< Zakończono połączenie bezpośrednie (7.x) */
-- GG_EVENT_DCC7_PENDING, /**< Trwa próba połączenia bezpośredniego (7.x), nowy deskryptor */
--
-- GG_EVENT_XML_EVENT, /**< Otrzymano komunikat systemowy (7.7) */
-- GG_EVENT_DISCONNECT_ACK, /**< \brief Potwierdzenie zakończenia sesji. Informuje o tym, że zmiana stanu na niedostępny z opisem dotarła do serwera i można zakończyć połączenie TCP. */
-- GG_EVENT_TYPING_NOTIFICATION, /**< Powiadomienie o pisaniu */
-- GG_EVENT_USER_DATA, /**< Informacja o kontaktach */
-- GG_EVENT_MULTILOGON_MSG, /**< Wiadomość wysłana z innej sesji multilogowania */
-- GG_EVENT_MULTILOGON_INFO, /**< Informacja o innych sesjach multilogowania */
--
-- GG_EVENT_USERLIST100_VERSION, /**< Otrzymano numer wersji listy kontaktów na serwerze (10.0) */
-- GG_EVENT_USERLIST100_REPLY, /**< Wynik importu lub eksportu listy kontaktów (10.0) */
--};
--
--#define GG_EVENT_SEARCH50_REPLY GG_EVENT_PUBDIR50_SEARCH_REPLY
--
--/**
-- * Powód nieudanego połączenia.
-- */
--enum gg_failure_t {
-- GG_FAILURE_RESOLVING = 1, /**< Nie znaleziono serwera */
-- GG_FAILURE_CONNECTING, /**< Błąd połączenia */
-- GG_FAILURE_INVALID, /**< Serwer zwrócił nieprawidłowe dane */
-- GG_FAILURE_READING, /**< Zerwano połączenie podczas odczytu */
-- GG_FAILURE_WRITING, /**< Zerwano połączenie podczas zapisu */
-- GG_FAILURE_PASSWORD, /**< Nieprawidłowe hasło */
-- GG_FAILURE_404, /**< Nieużywane */
-- GG_FAILURE_TLS, /**< Błąd negocjacji szyfrowanego połączenia */
-- GG_FAILURE_NEED_EMAIL, /**< Serwer rozłączył nas z prośbą o zmianę adresu e-mail */
-- GG_FAILURE_INTRUDER, /**< Zbyt wiele prób połączenia z nieprawidłowym hasłem */
-- GG_FAILURE_UNAVAILABLE, /**< Serwery są wyłączone */
-- GG_FAILURE_PROXY, /**< Błąd serwera pośredniczącego */
-- GG_FAILURE_HUB, /**< Błąd połączenia z hubem */
--};
--
--/**
-- * Kod błędu danej operacji.
-- *
-- * Nie zawiera przesadnie szczegółowych informacji o powodach błędów, by nie
-- * komplikować ich obsługi. Jeśli wymagana jest większa dokładność, należy
-- * sprawdzić zawartość zmiennej systemowej \c errno.
-- */
--enum gg_error_t {
-- GG_ERROR_RESOLVING = 1, /**< Nie znaleziono hosta */
-- GG_ERROR_CONNECTING, /**< Błąd połączenia */
-- GG_ERROR_READING, /**< BÅ‚Ä…d odczytu/odbierania */
-- GG_ERROR_WRITING, /**< Błąd zapisu/wysyłania */
--
-- GG_ERROR_DCC_HANDSHAKE, /**< BÅ‚Ä…d negocjacji */
-- GG_ERROR_DCC_FILE, /**< BÅ‚Ä…d odczytu/zapisu pliku */
-- GG_ERROR_DCC_EOF, /**< Przedwczesny koniec pliku */
-- GG_ERROR_DCC_NET, /**< Błąd wysyłania/odbierania */
-- GG_ERROR_DCC_REFUSED, /**< Połączenie odrzucone */
--
-- GG_ERROR_DCC7_HANDSHAKE, /**< BÅ‚Ä…d negocjacji */
-- GG_ERROR_DCC7_FILE, /**< BÅ‚Ä…d odczytu/zapisu pliku */
-- GG_ERROR_DCC7_EOF, /**< Przedwczesny koniec pliku */
-- GG_ERROR_DCC7_NET, /**< Błąd wysyłania/odbierania */
-- GG_ERROR_DCC7_REFUSED, /**< Połączenie odrzucone */
-- GG_ERROR_DCC7_RELAY, /**< Problem z serwerem pośredniczącym */
--};
--
--/**
-- * Pole zapytania lub odpowiedzi katalogu publicznego.
-- */
--struct gg_pubdir50_entry {
-- int num; /**< Numer wyniku */
-- char *field; /**< Nazwa pola */
-- char *value; /**< Wartość pola */
--} /* GG_DEPRECATED */;
--
--/**
-- * Zapytanie lub odpowiedź katalogu publicznego.
-- *
-- * Patrz \c gg_pubdir50_t.
-- */
--struct gg_pubdir50_s {
-- int count; /**< Liczba wyników odpowiedzi */
-- uin_t next; /**< Numer początkowy następnego zapytania */
-- int type; /**< Rodzaj zapytania */
-- uint32_t seq; /**< Numer sekwencyjny */
-- struct gg_pubdir50_entry *entries; /**< Pola zapytania lub odpowiedzi */
-- int entries_count; /**< Liczba pól */
--} /* GG_DEPRECATED */;
--
--/**
-- * Zapytanie lub odpowiedź katalogu publicznego.
-- *
-- * Do pól nie należy się odwoływać bezpośrednio -- wszystkie niezbędne
-- * informacje są dostępne za pomocą funkcji \c gg_pubdir50_*
-- */
--typedef struct gg_pubdir50_s *gg_pubdir50_t;
--
--/**
-- * Opis zdarzeń \c GG_EVENT_MSG i \c GG_EVENT_MULTILOGON_MSG.
-- */
--struct gg_event_msg {
-- uin_t sender; /**< Numer nadawcy/odbiorcy */
-- int msgclass; /**< Klasa wiadomości */
-- time_t time; /**< Czas nadania */
-- unsigned char *message; /**< Treść wiadomości */
--
-- int recipients_count; /**< Liczba odbiorców konferencji */
-- uin_t *recipients; /**< Odbiorcy konferencji */
--
-- int formats_length; /**< Długość informacji o formatowaniu tekstu */
-- void *formats; /**< Informacje o formatowaniu tekstu */
-- uint32_t seq; /**< Numer sekwencyjny wiadomości */
--
-- char *xhtml_message; /**< Treść wiadomości w formacie XHTML (może być równe \c NULL, jeśli wiadomość nie zawiera treści XHTML) */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_NOTIFY_DESCR.
-- */
--struct gg_event_notify_descr {
-- struct gg_notify_reply *notify; /**< Informacje o liście kontaktów */
-- char *descr; /**< Opis status */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_STATUS.
-- */
--struct gg_event_status {
-- uin_t uin; /**< Numer Gadu-Gadu */
-- uint32_t status; /**< Nowy status */
-- char *descr; /**< Opis */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_STATUS60.
-- */
--struct gg_event_status60 {
-- uin_t uin; /**< Numer Gadu-Gadu */
-- int status; /**< Nowy status */
-- uint32_t remote_ip; /**< Adres IP dla połączeń bezpośrednich */
-- uint16_t remote_port; /**< Port dla połączeń bezpośrednich */
-- int version; /**< Wersja protokołu */
-- int image_size; /**< Maksymalny rozmiar obsługiwanych obrazków w KiB */
-- char *descr; /**< Opis statusu */
-- time_t time; /**< Czas powrotu */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_NOTIFY_REPLY60.
-- */
--struct gg_event_notify60 {
-- uin_t uin; /**< Numer Gadu-Gadu. W ostatnim elemencie jest równy 0, a pozostałe pola są niezainicjowane. */
-- int status; /**< Nowy status */
-- uint32_t remote_ip; /**< Adres IP dla połączeń bezpośrednich */
-- uint16_t remote_port; /**< Port dla połączeń bezpośrednich */
-- int version; /**< Wersja protokołu */
-- int image_size; /**< Maksymalny rozmiar obsługiwanych obrazków w KiB */
-- char *descr; /**< Opis statusu */
-- time_t time; /**< Czas powrotu */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_ACK.
-- */
--struct gg_event_ack {
-- uin_t recipient; /**< Numer odbiorcy */
-- int status; /**< Status doręczenia */
-- int seq; /**< Numer sekwencyjny wiadomości */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_USERLIST.
-- */
--struct gg_event_userlist {
-- char type; /**< Rodzaj odpowiedzi */
-- char *reply; /**< Treść odpowiedzi */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_DCC_VOICE_DATA.
-- */
--struct gg_event_dcc_voice_data {
-- uint8_t *data; /**< Dane dźwiękowe */
-- int length; /**< Rozmiar danych dźwiękowych */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_IMAGE_REQUEST.
-- */
--struct gg_event_image_request {
-- uin_t sender; /**< Nadawca żądania */
-- uint32_t size; /**< Rozmiar obrazka */
-- uint32_t crc32; /**< Suma kontrolna CRC32 */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_IMAGE_REPLY.
-- */
--struct gg_event_image_reply {
-- uin_t sender; /**< Nadawca obrazka */
-- uint32_t size; /**< Rozmiar obrazka */
-- uint32_t crc32; /**< Suma kontrolna CRC32 */
-- char *filename; /**< Nazwa pliku */
-- char *image; /**< Bufor z obrazkiem */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_XML_EVENT.
-- */
--struct gg_event_xml_event {
-- char *data; /**< Bufor z komunikatem */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_DCC7_CONNECTED.
-- */
--struct gg_event_dcc7_connected {
-- struct gg_dcc7 *dcc7; /**< Struktura połączenia */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_DCC7_PENDING.
-- */
--struct gg_event_dcc7_pending {
-- struct gg_dcc7 *dcc7; /**< Struktura połączenia */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_DCC7_REJECT.
-- */
--struct gg_event_dcc7_reject {
-- struct gg_dcc7 *dcc7; /**< Struktura połączenia */
-- int reason; /**< powód odrzucenia */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_DCC7_ACCEPT.
-- */
--struct gg_event_dcc7_accept {
-- struct gg_dcc7 *dcc7; /**< Struktura połączenia */
-- int type; /**< Sposób połączenia (P2P, przez serwer) */
-- uint32_t remote_ip; /**< Adres zdalnego klienta */
-- uint16_t remote_port; /**< Port zdalnego klienta */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_DCC7_DONE.
-- */
--struct gg_event_dcc7_done {
-- struct gg_dcc7 *dcc7; /**< Struktura połączenia */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_TYPING_NOTIFICATION.
-- */
--struct gg_event_typing_notification {
-- uin_t uin; /**< Numer rozmówcy */
-- int length; /**< Długość tekstu */
--};
--
--/**
-- * Atrybut użytkownika.
-- */
--struct gg_event_user_data_attr {
-- int type; /**< Typ atrybutu */
-- char *key; /**< Klucz */
-- char *value; /**< Wartość */
--};
--
--/**
-- * Struktura opisujÄ…ca kontakt w zdarzeniu GG_EVENT_USER_DATA.
-- */
--struct gg_event_user_data_user {
-- uin_t uin; /**< Numer kontaktu */
-- size_t attr_count; /**< Liczba atrybutów */
-- struct gg_event_user_data_attr *attrs; /**< Lista atrybutów */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_USER_DATA.
-- */
--struct gg_event_user_data {
-- int type; /**< Rodzaj informacji o kontaktach */
-- size_t user_count; /**< Liczba kontaktów */
-- struct gg_event_user_data_user *users; /**< Lista kontaktów */
--};
--
--/**
-- * Struktura opisujÄ…ca sesjÄ™ multilogowania.
-- */
--struct gg_multilogon_session {
-- gg_multilogon_id_t id; /**< Identyfikator sesji */
-- char *name; /**< Nazwa sesji (podana w \c gg_login_params.client_version) */
-- uint32_t remote_addr; /**< Adres sesji */
-- int status_flags; /**< Flagi statusu sesji */
-- int protocol_features; /**< Opcje protokolu sesji */
-- time_t logon_time; /**< Czas zalogowania */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_MULTILOGON_INFO.
-- */
--struct gg_event_multilogon_info {
-- int count; /**< Liczba sesji */
-- struct gg_multilogon_session *sessions; /** Lista sesji */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_USERLIST100_VERSION.
-- */
--struct gg_event_userlist100_version {
-- uint32_t version; /**< Numer wersji listy kontaktów na serwerze */
--};
--
--/**
-- * Opis zdarzenia \c GG_EVENT_USERLIST100_REPLY.
-- */
--struct gg_event_userlist100_reply {
-- char type; /**< Rodzaj odpowiedzi */
-- uint32_t version; /**< Aktualna wersja listy kontaktów na serwerze */
-- char format_type; /**< Typ formatu listy kontaktów (żądany w \c gg_userlist100_request.format_type) */
-- char *reply; /**< Treść listy kontaktów w przesyłanej wersji i formacie */
--};
--
--/**
-- * Unia wszystkich zdarzeń zwracanych przez funkcje \c gg_watch_fd(),
-- * \c gg_dcc_watch_fd() i \c gg_dcc7_watch_fd().
-- *
-- * \ingroup events
-- */
--union gg_event_union {
-- enum gg_failure_t failure; /**< Błąd połączenia (\c GG_EVENT_CONN_FAILED) */
-- struct gg_notify_reply *notify; /**< Zmiana statusu kontaktów (\c GG_EVENT_NOTIFY) */
-- struct gg_event_notify_descr notify_descr; /**< Zmiana statusu kontaktów (\c GG_EVENT_NOTIFY_DESCR) */
-- struct gg_event_status status; /**< Zmiana statusu kontaktów (\c GG_EVENT_STATUS) */
-- struct gg_event_status60 status60; /**< Zmiana statusu kontaktów (\c GG_EVENT_STATUS60) */
-- struct gg_event_notify60 *notify60; /**< Zmiana statusu kontaktów (\c GG_EVENT_NOTIFY60) */
-- struct gg_event_msg msg; /**< Otrzymano wiadomość (\c GG_EVENT_MSG) */
-- struct gg_event_ack ack; /**< Potwierdzenie wiadomości (\c GG_EVENT_ACK) */
-- struct gg_event_image_request image_request; /**< Żądanie wysłania obrazka (\c GG_EVENT_IMAGE_REQUEST) */
-- struct gg_event_image_reply image_reply; /**< Odpowiedź z obrazkiem (\c GG_EVENT_IMAGE_REPLY) */
-- struct gg_event_userlist userlist; /**< Odpowiedź listy kontaktów (\c GG_EVENT_USERLIST) */
-- gg_pubdir50_t pubdir50; /**< Odpowiedź katalogu publicznego (\c GG_EVENT_PUBDIR50_*) */
-- struct gg_event_xml_event xml_event; /**< Zdarzenie systemowe (\c GG_EVENT_XML_EVENT) */
-- struct gg_dcc *dcc_new; /**< Nowe połączenie bezpośrednie (\c GG_EVENT_DCC_NEW) */
-- enum gg_error_t dcc_error; /**< Błąd połączenia bezpośredniego (\c GG_EVENT_DCC_ERROR) */
-- struct gg_event_dcc_voice_data dcc_voice_data; /**< Dane połączenia głosowego (\c GG_EVENT_DCC_VOICE_DATA) */
-- struct gg_dcc7 *dcc7_new; /**< Nowe połączenie bezpośrednie (\c GG_EVENT_DCC7_NEW) */
-- enum gg_error_t dcc7_error; /**< Błąd połączenia bezpośredniego (\c GG_EVENT_DCC7_ERROR) */
-- struct gg_event_dcc7_connected dcc7_connected; /**< Informacja o zestawieniu połączenia bezpośredniego (\c GG_EVENT_DCC7_CONNECTED) */
-- struct gg_event_dcc7_pending dcc7_pending; /**< Trwa próba połączenia bezpośredniego (\c GG_EVENT_DCC7_PENDING) */
-- struct gg_event_dcc7_reject dcc7_reject; /**< Odrzucono połączenia bezpośredniego (\c GG_EVENT_DCC7_REJECT) */
-- struct gg_event_dcc7_accept dcc7_accept; /**< Zaakceptowano połączenie bezpośrednie (\c GG_EVENT_DCC7_ACCEPT) */
-- struct gg_event_dcc7_done dcc7_done; /**< Zakończono połączenie bezpośrednie (\c GG_EVENT_DCC7_DONE) */
-- struct gg_event_typing_notification typing_notification; /**< Powiadomienie o pisaniu */
-- struct gg_event_user_data user_data; /**< Informacje o kontaktach */
-- struct gg_event_msg multilogon_msg; /**< Inna sesja wysłała wiadomość (\c GG_EVENT_MULTILOGON_MSG) */
-- struct gg_event_multilogon_info multilogon_info; /**< Informacja o innych sesjach multilogowania (\c GG_EVENT_MULTILOGON_INFO) */
-- struct gg_event_userlist100_version userlist100_version; /**< Informacja o numerze wersji listy kontaktów na serwerze (\c GG_EVENT_USERLIST100_VERSION) */
-- struct gg_event_userlist100_reply userlist100_reply; /**< Odpowiedź listy kontaktów (10.0) (\c GG_EVENT_USERLIST100_REPLY) */
--};
--
--/**
-- * Opis zdarzenia.
-- *
-- * Zwracany przez funkcje \c gg_watch_fd(), \c gg_dcc_watch_fd()
-- * i \c gg_dcc7_watch_fd(). Po przeanalizowaniu należy zwolnić
-- * za pomocÄ… \c gg_event_free().
-- *
-- * \ingroup events
-- */
--struct gg_event {
-- int type; /**< Rodzaj zdarzenia */
-- union gg_event_union event; /**< Informacja o zdarzeniu */
--};
--
--struct gg_event *gg_watch_fd(struct gg_session *sess);
--void gg_event_free(struct gg_event *e);
--
--int gg_notify_ex(struct gg_session *sess, uin_t *userlist, char *types, int count);
--int gg_notify(struct gg_session *sess, uin_t *userlist, int count);
--int gg_add_notify_ex(struct gg_session *sess, uin_t uin, char type);
--int gg_add_notify(struct gg_session *sess, uin_t uin);
--int gg_remove_notify_ex(struct gg_session *sess, uin_t uin, char type);
--int gg_remove_notify(struct gg_session *sess, uin_t uin);
--
--struct gg_http *gg_http_connect(const char *hostname, int port, int async, const char *method, const char *path, const char *header);
--int gg_http_watch_fd(struct gg_http *h);
--void gg_http_stop(struct gg_http *h);
--void gg_http_free(struct gg_http *h);
--
--uint32_t gg_pubdir50(struct gg_session *sess, gg_pubdir50_t req);
--gg_pubdir50_t gg_pubdir50_new(int type);
--int gg_pubdir50_add(gg_pubdir50_t req, const char *field, const char *value);
--int gg_pubdir50_seq_set(gg_pubdir50_t req, uint32_t seq);
--const char *gg_pubdir50_get(gg_pubdir50_t res, int num, const char *field);
--int gg_pubdir50_type(gg_pubdir50_t res);
--int gg_pubdir50_count(gg_pubdir50_t res);
--uin_t gg_pubdir50_next(gg_pubdir50_t res);
--uint32_t gg_pubdir50_seq(gg_pubdir50_t res);
--void gg_pubdir50_free(gg_pubdir50_t res);
--
--#ifndef DOXYGEN
--
--#define GG_PUBDIR50_UIN "FmNumber"
--#define GG_PUBDIR50_STATUS "FmStatus"
--#define GG_PUBDIR50_FIRSTNAME "firstname"
--#define GG_PUBDIR50_LASTNAME "lastname"
--#define GG_PUBDIR50_NICKNAME "nickname"
--#define GG_PUBDIR50_BIRTHYEAR "birthyear"
--#define GG_PUBDIR50_CITY "city"
--#define GG_PUBDIR50_GENDER "gender"
--#define GG_PUBDIR50_GENDER_FEMALE "1"
--#define GG_PUBDIR50_GENDER_MALE "2"
--#define GG_PUBDIR50_GENDER_SET_FEMALE "2"
--#define GG_PUBDIR50_GENDER_SET_MALE "1"
--#define GG_PUBDIR50_ACTIVE "ActiveOnly"
--#define GG_PUBDIR50_ACTIVE_TRUE "1"
--#define GG_PUBDIR50_START "fmstart"
--#define GG_PUBDIR50_FAMILYNAME "familyname"
--#define GG_PUBDIR50_FAMILYCITY "familycity"
--
--#else
--
--/**
-- * \ingroup pubdir50
-- *
-- * Rodzaj pola zapytania.
-- */
--enum {
-- GG_PUBDIR50_UIN, /**< Numer Gadu-Gadu */
-- GG_PUBDIR50_STATUS, /**< Status (tylko wynik wyszukiwania) */
-- GG_PUBDIR50_FIRSTNAME, /**< ImiÄ™ */
-- GG_PUBDIR50_LASTNAME, /**< Nazwisko */
-- GG_PUBDIR50_NICKNAME, /**< Pseudonim */
-- GG_PUBDIR50_BIRTHYEAR, /**< Rok urodzenia lub przedział lat oddzielony spacją */
-- GG_PUBDIR50_CITY, /**< Miejscowość */
-- GG_PUBDIR50_GENDER, /**< Płeć */
-- GG_PUBDIR50_ACTIVE, /**< Osoba dostępna (tylko wyszukiwanie) */
-- GG_PUBDIR50_START, /**< Numer poczÄ…tkowy wyszukiwania (tylko wyszukiwanie) */
-- GG_PUBDIR50_FAMILYNAME, /**< Nazwisko rodowe (tylko wysyłanie informacji o sobie) */
-- GG_PUBDIR50_FAMILYCITY, /**< Miejscowość pochodzenia (tylko wysyłanie informacji o sobie) */
--};
--
--/**
-- * \ingroup pubdir50
-- *
-- * Wartość pola GG_PUBDIR50_GENDER przy wyszukiwaniu. Brak pola oznacza dowolną płeć.
-- */
--enum {
-- GG_PUBDIR50_GENDER_FEMALE, /**< Kobieta */
-- GG_PUBDIR50_GENDER_MALE, /**< Mężczyzna */
--};
--
--/**
-- * \ingroup pubdir50
-- *
-- * Wartość pola GG_PUBDIR50_GENDER przy wysyłaniu informacji o sobie.
-- */
--enum {
-- GG_PUBDIR50_GENDER_SET_FEMALE, /**< Kobieta */
-- GG_PUBDIR50_GENDER_SET_MALE, /**< Mężczyzna */
--};
--
--/**
-- * \ingroup pubdir50
-- *
-- * Wartość pola GG_PUBDIR50_ACTIVE.
-- */
--enum {
-- GG_PUBDIR50_ACTIVE_TRUE, /**< Wyszukaj tylko osoby dostępne */
--};
--
--#endif /* DOXYGEN */
--
--/**
-- * Wynik operacji na katalogu publicznym.
-- *
-- * \ingroup http
-- */
--struct gg_pubdir {
-- int success; /**< Flaga powodzenia operacji */
-- uin_t uin; /**< Otrzymany numer lub 0 w przypadku błędu */
--};
--
--int gg_pubdir_watch_fd(struct gg_http *f);
--void gg_pubdir_free(struct gg_http *f);
--
--/**
-- * Token autoryzacji niektórych operacji HTTP.
-- *
-- * \ingroup token
-- */
--struct gg_token {
-- int width; /**< Szerokość obrazka */
-- int height; /**< Wysokość obrazka */
-- int length; /**< Liczba znaków w tokenie */
-- char *tokenid; /**< Identyfikator tokenu */
--};
--
--struct gg_http *gg_token(int async);
--int gg_token_watch_fd(struct gg_http *h);
--void gg_token_free(struct gg_http *h);
--
--struct gg_http *gg_register3(const char *email, const char *password, const char *tokenid, const char *tokenval, int async);
--#ifndef DOXYGEN
--#define gg_register_watch_fd gg_pubdir_watch_fd
--#define gg_register_free gg_pubdir_free
--#endif
--
--struct gg_http *gg_unregister3(uin_t uin, const char *password, const char *tokenid, const char *tokenval, int async);
--#ifndef DOXYGEN
--#define gg_unregister_watch_fd gg_pubdir_watch_fd
--#define gg_unregister_free gg_pubdir_free
--#endif
--
--struct gg_http *gg_remind_passwd3(uin_t uin, const char *email, const char *tokenid, const char *tokenval, int async);
--#ifndef DOXYGEN
--#define gg_remind_passwd_watch_fd gg_pubdir_watch_fd
--#define gg_remind_passwd_free gg_pubdir_free
--#endif
--
--struct gg_http *gg_change_passwd4(uin_t uin, const char *email, const char *passwd, const char *newpasswd, const char *tokenid, const char *tokenval, int async);
--#ifndef DOXYGEN
--#define gg_change_passwd_watch_fd gg_pubdir_watch_fd
--#define gg_change_passwd_free gg_pubdir_free
--#endif
--
--extern int gg_dcc_port;
--extern unsigned long gg_dcc_ip;
--
--int gg_dcc_request(struct gg_session *sess, uin_t uin);
--
--struct gg_dcc *gg_dcc_send_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin);
--struct gg_dcc *gg_dcc_get_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin);
--struct gg_dcc *gg_dcc_voice_chat(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin);
--void gg_dcc_set_type(struct gg_dcc *d, int type);
--int gg_dcc_fill_file_info(struct gg_dcc *d, const char *filename);
--int gg_dcc_fill_file_info2(struct gg_dcc *d, const char *filename, const char *local_filename);
--int gg_dcc_voice_send(struct gg_dcc *d, char *buf, int length);
--
--#define GG_DCC_VOICE_FRAME_LENGTH 195 /**< Rozmiar pakietu głosowego przed wersją Gadu-Gadu 5.0.5 */
--#define GG_DCC_VOICE_FRAME_LENGTH_505 326 /**< Rozmiar pakietu głosowego od wersji Gadu-Gadu 5.0.5 */
--
--struct gg_dcc *gg_dcc_socket_create(uin_t uin, uint16_t port);
--#ifndef DOXYGEN
--#define gg_dcc_socket_free gg_dcc_free
--#define gg_dcc_socket_watch_fd gg_dcc_watch_fd
--#endif
--
--struct gg_event *gg_dcc_watch_fd(struct gg_dcc *d);
--
--void gg_dcc_free(struct gg_dcc *c);
--
--struct gg_event *gg_dcc7_watch_fd(struct gg_dcc7 *d);
--struct gg_dcc7 *gg_dcc7_send_file(struct gg_session *sess, uin_t rcpt, const char *filename, const char *filename1250, const char *hash);
--struct gg_dcc7 *gg_dcc7_send_file_fd(struct gg_session *sess, uin_t rcpt, int fd, size_t size, const char *filename1250, const char *hash);
--int gg_dcc7_accept(struct gg_dcc7 *dcc, unsigned int offset);
--int gg_dcc7_reject(struct gg_dcc7 *dcc, int reason);
--void gg_dcc7_free(struct gg_dcc7 *d);
--
--extern int gg_debug_level;
--
--extern void (*gg_debug_handler)(int level, const char *format, va_list ap);
--extern void (*gg_debug_handler_session)(struct gg_session *sess, int level, const char *format, va_list ap);
--
--extern FILE *gg_debug_file;
--
--/**
-- * \ingroup debug
-- * @{
-- */
--#define GG_DEBUG_NET 1 /**< Rejestracja zdarzeń związanych z siecią */
--#define GG_DEBUG_TRAFFIC 2 /**< Rejestracja ruchu sieciowego */
--#define GG_DEBUG_DUMP 4 /**< Rejestracja zawartości pakietów */
--#define GG_DEBUG_FUNCTION 8 /**< Rejestracja wywołań funkcji */
--#define GG_DEBUG_MISC 16 /**< Rejestracja różnych informacji */
--/** @} */
--
--#ifdef GG_DEBUG_DISABLE
--#define gg_debug(x, y...) do { } while(0)
--#define gg_debug_session(z, x, y...) do { } while(0)
--#else
--void gg_debug(int level, const char *format, ...);
--void gg_debug_session(struct gg_session *sess, int level, const char *format, ...);
--#endif
--
--const char *gg_libgadu_version(void);
--
--/**
-- * Lista funkcji biblioteki, które zależą od zewnętrznych bibliotek.
-- *
-- * \ingroup version
-- */
--typedef enum {
-- GG_LIBGADU_FEATURE_SSL, /**< Biblioteka obsługuje połączenia szyfrowane */
-- GG_LIBGADU_FEATURE_PTHREAD, /**< Biblioteka obsługuje rozwiązywanie nazw za pomocą wątków */
-- GG_LIBGADU_FEATURE_USERLIST100, /**< Biblioteka obsługuje listę kontaktów zgodną z Gadu-Gadu 10 */
--} gg_libgadu_feature_t;
--
--int gg_libgadu_check_feature(gg_libgadu_feature_t feature);
--
--extern int gg_proxy_enabled;
--extern char *gg_proxy_host;
--extern int gg_proxy_port;
--extern char *gg_proxy_username;
--extern char *gg_proxy_password;
--extern int gg_proxy_http_only;
--
--extern unsigned long gg_local_ip;
--
--#define GG_LOGIN_HASH_GG32 0x01 /**< Algorytm Gadu-Gadu */
--#define GG_LOGIN_HASH_SHA1 0x02 /**< Algorytm SHA1 */
--
--#ifndef DOXYGEN
--
--#define GG_PUBDIR50_WRITE 0x01
--#define GG_PUBDIR50_READ 0x02
--#define GG_PUBDIR50_SEARCH 0x03
--#define GG_PUBDIR50_SEARCH_REQUEST GG_PUBDIR50_SEARCH
--#define GG_PUBDIR50_SEARCH_REPLY 0x05
--
--#else
--
--/**
-- * \ingroup pubdir50
-- *
-- * Rodzaj zapytania lub odpowiedzi katalogu publicznego.
-- */
--enum {
-- GG_PUBDIR50_WRITE, /**< Wysłanie do serwera informacji o sobie */
-- GG_PUBDIR50_READ, /**< Pobranie z serwera informacji o sobie */
-- GG_PUBDIR50_SEARCH, /**< Wyszukiwanie w katalogu publicznym */
-- GG_PUBDIR50_SEARCH_REPLY, /**< Wynik wyszukiwania w katalogu publicznym */
--};
--
--#endif /* DOXYGEN */
--
--/** \cond obsolete */
--
--#define gg_free_event gg_event_free
--#define gg_free_http gg_http_free
--#define gg_free_pubdir gg_pubdir_free
--#define gg_free_register gg_pubdir_free
--#define gg_free_remind_passwd gg_pubdir_free
--#define gg_free_dcc gg_dcc_free
--#define gg_free_change_passwd gg_pubdir_free
--
--struct gg_search_request {
-- int active;
-- unsigned int start;
-- char *nickname;
-- char *first_name;
-- char *last_name;
-- char *city;
-- int gender;
-- int min_birth;
-- int max_birth;
-- char *email;
-- char *phone;
-- uin_t uin;
--} /* GG_DEPRECATED */;
--
--struct gg_search {
-- int count;
-- struct gg_search_result *results;
--} GG_DEPRECATED;
--
--struct gg_search_result {
-- uin_t uin;
-- char *first_name;
-- char *last_name;
-- char *nickname;
-- int born;
-- int gender;
-- char *city;
-- int active;
--} GG_DEPRECATED;
--
--#define GG_GENDER_NONE 0
--#define GG_GENDER_FEMALE 1
--#define GG_GENDER_MALE 2
--
--struct gg_http *gg_search(const struct gg_search_request *r, int async) GG_DEPRECATED;
--int gg_search_watch_fd(struct gg_http *f) GG_DEPRECATED;
--void gg_free_search(struct gg_http *f) GG_DEPRECATED;
--#define gg_search_free gg_free_search
--
--const struct gg_search_request *gg_search_request_mode_0(char *nickname, char *first_name, char *last_name, char *city, int gender, int min_birth, int max_birth, int active, int start) GG_DEPRECATED;
--const struct gg_search_request *gg_search_request_mode_1(char *email, int active, int start) GG_DEPRECATED;
--const struct gg_search_request *gg_search_request_mode_2(char *phone, int active, int start) GG_DEPRECATED;
--const struct gg_search_request *gg_search_request_mode_3(uin_t uin, int active, int start) GG_DEPRECATED;
--void gg_search_request_free(struct gg_search_request *r) GG_DEPRECATED;
--
--struct gg_http *gg_register(const char *email, const char *password, int async) GG_DEPRECATED;
--struct gg_http *gg_register2(const char *email, const char *password, const char *qa, int async) GG_DEPRECATED;
--
--struct gg_http *gg_unregister(uin_t uin, const char *password, const char *email, int async) GG_DEPRECATED;
--struct gg_http *gg_unregister2(uin_t uin, const char *password, const char *qa, int async) GG_DEPRECATED;
--
--struct gg_http *gg_remind_passwd(uin_t uin, int async) GG_DEPRECATED;
--struct gg_http *gg_remind_passwd2(uin_t uin, const char *tokenid, const char *tokenval, int async) GG_DEPRECATED;
--
--struct gg_http *gg_change_passwd(uin_t uin, const char *passwd, const char *newpasswd, const char *newemail, int async) GG_DEPRECATED;
--struct gg_http *gg_change_passwd2(uin_t uin, const char *passwd, const char *newpasswd, const char *email, const char *newemail, int async) GG_DEPRECATED;
--struct gg_http *gg_change_passwd3(uin_t uin, const char *passwd, const char *newpasswd, const char *qa, int async) GG_DEPRECATED;
--
--struct gg_change_info_request {
-- char *first_name;
-- char *last_name;
-- char *nickname;
-- char *email;
-- int born;
-- int gender;
-- char *city;
--} /* GG_DEPRECATED */;
--
--struct gg_change_info_request *gg_change_info_request_new(const char *first_name, const char *last_name, const char *nickname, const char *email, int born, int gender, const char *city) GG_DEPRECATED;
--void gg_change_info_request_free(struct gg_change_info_request *r) GG_DEPRECATED;
--
--struct gg_http *gg_change_info(uin_t uin, const char *passwd, const struct gg_change_info_request *request, int async) GG_DEPRECATED;
--#define gg_change_pubdir_watch_fd gg_pubdir_watch_fd
--#define gg_change_pubdir_free gg_pubdir_free
--#define gg_free_change_pubdir gg_pubdir_free
--
--struct gg_http *gg_userlist_get(uin_t uin, const char *password, int async) GG_DEPRECATED;
--int gg_userlist_get_watch_fd(struct gg_http *f) GG_DEPRECATED;
--void gg_userlist_get_free(struct gg_http *f) GG_DEPRECATED;
--
--struct gg_http *gg_userlist_put(uin_t uin, const char *password, const char *contacts, int async) GG_DEPRECATED;
--int gg_userlist_put_watch_fd(struct gg_http *f) GG_DEPRECATED;
--void gg_userlist_put_free(struct gg_http *f) GG_DEPRECATED;
--
--struct gg_http *gg_userlist_remove(uin_t uin, const char *password, int async) GG_DEPRECATED;
--int gg_userlist_remove_watch_fd(struct gg_http *f) GG_DEPRECATED;
--void gg_userlist_remove_free(struct gg_http *f) GG_DEPRECATED;
--
--int gg_pubdir50_handle_reply(struct gg_event *e, const char *packet, int length) GG_DEPRECATED;
--
--/** \endcond */
--
--int gg_file_hash_sha1(int fd, uint8_t *result) GG_DEPRECATED;
--
--#undef printf
--#ifdef __GNUC__
--char *gg_saprintf(const char *format, ...) __attribute__ ((format (printf, 1, 2))) GG_DEPRECATED;
--#else
--char *gg_saprintf(const char *format, ...) GG_DEPRECATED;
--#endif
--
--char *gg_vsaprintf(const char *format, va_list ap) GG_DEPRECATED;
--
--#define gg_alloc_sprintf gg_saprintf
--
--char *gg_get_line(char **ptr) GG_DEPRECATED;
--
--int gg_connect(void *addr, int port, int async) GG_DEPRECATED;
--struct in_addr *gg_gethostbyname(const char *hostname) GG_DEPRECATED;
--char *gg_read_line(int sock, char *buf, int length) GG_DEPRECATED;
--void gg_chomp(char *line) GG_DEPRECATED;
--char *gg_urlencode(const char *str) GG_DEPRECATED;
--int gg_http_hash(const char *format, ...) GG_DEPRECATED;
--void gg_http_free_fields(struct gg_http *h) GG_DEPRECATED;
--int gg_read(struct gg_session *sess, char *buf, int length) GG_DEPRECATED;
--int gg_write(struct gg_session *sess, const char *buf, int length) GG_DEPRECATED;
--void *gg_recv_packet(struct gg_session *sess) GG_DEPRECATED;
--int gg_send_packet(struct gg_session *sess, int type, ...) GG_DEPRECATED;
--unsigned int gg_login_hash(const unsigned char *password, unsigned int seed) GG_DEPRECATED;
--void gg_login_hash_sha1(const char *password, uint32_t seed, uint8_t *result) GG_DEPRECATED;
--uint32_t gg_fix32(uint32_t x);
--uint16_t gg_fix16(uint16_t x);
--#define fix16 gg_fix16
--#define fix32 gg_fix32
--char *gg_proxy_auth(void) GG_DEPRECATED;
--char *gg_base64_encode(const char *buf) GG_DEPRECATED;
--char *gg_base64_decode(const char *buf) GG_DEPRECATED;
--int gg_image_queue_remove(struct gg_session *s, struct gg_image_queue *q, int freeq) GG_DEPRECATED;
--
--/**
-- * Kolejka odbieranych obrazków.
-- */
--struct gg_image_queue {
-- uin_t sender; /**< Nadawca obrazka */
-- uint32_t size; /**< Rozmiar obrazka */
-- uint32_t crc32; /**< Suma kontrolna CRC32 */
-- char *filename; /**< Nazwa pliku */
-- char *image; /**< Bufor z odebranymi danymi */
-- uint32_t done; /**< Rozmiar odebranych danych */
--
-- struct gg_image_queue *next; /**< Kolejny element listy */
--} GG_DEPRECATED;
--
--int gg_dcc7_handle_id(struct gg_session *sess, struct gg_event *e, const void *payload, int len) GG_DEPRECATED;
--int gg_dcc7_handle_new(struct gg_session *sess, struct gg_event *e, const void *payload, int len) GG_DEPRECATED;
--int gg_dcc7_handle_info(struct gg_session *sess, struct gg_event *e, const void *payload, int len) GG_DEPRECATED;
--int gg_dcc7_handle_accept(struct gg_session *sess, struct gg_event *e, const void *payload, int len) GG_DEPRECATED;
--int gg_dcc7_handle_reject(struct gg_session *sess, struct gg_event *e, const void *payload, int len) GG_DEPRECATED;
--
--#define GG_APPMSG_HOST "appmsg.gadu-gadu.pl"
--#define GG_APPMSG_PORT 80
--#define GG_PUBDIR_HOST "pubdir.gadu-gadu.pl"
--#define GG_PUBDIR_PORT 80
--#define GG_REGISTER_HOST "register.gadu-gadu.pl"
--#define GG_REGISTER_PORT 80
--#define GG_REMIND_HOST "retr.gadu-gadu.pl"
--#define GG_REMIND_PORT 80
--#define GG_RELAY_HOST "relay.gadu-gadu.pl"
--#define GG_RELAY_PORT 80
--
--#define GG_DEFAULT_PORT 8074
--#define GG_HTTPS_PORT 443
--#define GG_HTTP_USERAGENT "Mozilla/4.7 [en] (Win98; I)"
--
--#define GG_DEFAULT_CLIENT_VERSION "10.1.0.11070"
--#define GG_DEFAULT_PROTOCOL_VERSION 0x2e
--#define GG_DEFAULT_TIMEOUT 30
--#define GG_HAS_AUDIO_MASK 0x40000000
--#define GG_HAS_AUDIO7_MASK 0x20000000
--#define GG_ERA_OMNIX_MASK 0x04000000
--#undef GG_LIBGADU_VERSION
--
--#ifndef DOXYGEN
--
--#define GG_FEATURE_MSG77 0x0001
--#define GG_FEATURE_STATUS77 0x0002
--#define GG_FEATURE_UNKNOWN_4 0x0004
--#define GG_FEATURE_UNKNOWN_8 0x0008
--#define GG_FEATURE_DND_FFC 0x0010
--#define GG_FEATURE_IMAGE_DESCR 0x0020
--#define GG_FEATURE_UNKNOWN_40 0x0040
--#define GG_FEATURE_UNKNOWN_80 0x0080
--#define GG_FEATURE_UNKNOWN_100 0x0100
--#define GG_FEATURE_USER_DATA 0x0200
--#define GG_FEATURE_MSG_ACK 0x0400
--#define GG_FEATURE_UNKNOWN_800 0x0800
--#define GG_FEATURE_UNKNOWN_1000 0x1000
--#define GG_FEATURE_TYPING_NOTIFICATION 0x2000
--#define GG_FEATURE_MULTILOGON 0x4000
--
--/* Poniższe makra zostały zachowane dla zgodności API */
--#define GG_FEATURE_MSG80 0
--#define GG_FEATURE_STATUS80 0
--#define GG_FEATURE_STATUS80BETA 0
--
--#define GG_FEATURE_ALL (GG_FEATURE_MSG80 | GG_FEATURE_STATUS80 | GG_FEATURE_DND_FFC | GG_FEATURE_IMAGE_DESCR | GG_FEATURE_UNKNOWN_100 | GG_FEATURE_USER_DATA | GG_FEATURE_MSG_ACK | GG_FEATURE_TYPING_NOTIFICATION)
--
--#else
--
--/**
-- * \ingroup login
-- *
-- * Flagi opcji protokołu.
-- */
--enum {
-- GG_FEATURE_MSG77, /**< Klient życzy sobie otrzymywać wiadomości zgodnie z protokołem 7.7 */
-- GG_FEATURE_STATUS77, /**< Klient życzy sobie otrzymywać zmiany stanu zgodnie z protokołem 7.7 */
-- GG_FEATURE_DND_FFC, /**< Klient obsługuje statusy "nie przeszkadzać" i "poGGadaj ze mną" */
-- GG_FEATURE_IMAGE_DESCR, /**< Klient obsługuje opisy graficzne oraz flagę \c GG_STATUS80_DESCR_MASK */
--};
--
--
--#endif
--
--#define GG_DEFAULT_DCC_PORT 1550
--
--struct gg_header {
-- uint32_t type; /* typ pakietu */
-- uint32_t length; /* długość reszty pakietu */
--} GG_PACKED;
--
--#define GG_WELCOME 0x0001
--#define GG_NEED_EMAIL 0x0014
--
--struct gg_welcome {
-- uint32_t key; /* klucz szyfrowania hasła */
--} GG_PACKED;
--
--#define GG_LOGIN 0x000c
--
--struct gg_login {
-- uint32_t uin; /* mój numerek */
-- uint32_t hash; /* hash hasła */
-- uint32_t status; /* status na dzień dobry */
-- uint32_t version; /* moja wersja klienta */
-- uint32_t local_ip; /* mój adres ip */
-- uint16_t local_port; /* port, na którym słucham */
--} GG_PACKED;
--
--#define GG_LOGIN_EXT 0x0013
--
--struct gg_login_ext {
-- uint32_t uin; /* mój numerek */
-- uint32_t hash; /* hash hasła */
-- uint32_t status; /* status na dzień dobry */
-- uint32_t version; /* moja wersja klienta */
-- uint32_t local_ip; /* mój adres ip */
-- uint16_t local_port; /* port, na którym słucham */
-- uint32_t external_ip; /* zewnętrzny adres ip */
-- uint16_t external_port; /* zewnętrzny port */
--} GG_PACKED;
--
--#define GG_LOGIN60 0x0015
--
--struct gg_login60 {
-- uint32_t uin; /* mój numerek */
-- uint32_t hash; /* hash hasła */
-- uint32_t status; /* status na dzień dobry */
-- uint32_t version; /* moja wersja klienta */
-- uint8_t dunno1; /* 0x00 */
-- uint32_t local_ip; /* mój adres ip */
-- uint16_t local_port; /* port, na którym słucham */
-- uint32_t external_ip; /* zewnętrzny adres ip */
-- uint16_t external_port; /* zewnętrzny port */
-- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
-- uint8_t dunno2; /* 0xbe */
--} GG_PACKED;
--
--#define GG_LOGIN70 0x0019
--
--struct gg_login70 {
-- uint32_t uin; /* mój numerek */
-- uint8_t hash_type; /* rodzaj hashowania hasła */
-- uint8_t hash[64]; /* hash hasła dopełniony zerami */
-- uint32_t status; /* status na dzień dobry */
-- uint32_t version; /* moja wersja klienta */
-- uint8_t dunno1; /* 0x00 */
-- uint32_t local_ip; /* mój adres ip */
-- uint16_t local_port; /* port, na którym słucham */
-- uint32_t external_ip; /* zewnętrzny adres ip (???) */
-- uint16_t external_port; /* zewnętrzny port (???) */
-- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
-- uint8_t dunno2; /* 0xbe */
--} GG_PACKED;
--
--#define GG_LOGIN_OK 0x0003
--
--#define GG_LOGIN_FAILED 0x0009
--
--#define GG_PUBDIR50_REQUEST 0x0014
--
--struct gg_pubdir50_request {
-- uint8_t type; /* GG_PUBDIR50_* */
-- uint32_t seq; /* czas wysłania zapytania */
--} GG_PACKED;
--
--#define GG_PUBDIR50_REPLY 0x000e
--
--struct gg_pubdir50_reply {
-- uint8_t type; /* GG_PUBDIR50_* */
-- uint32_t seq; /* czas wysłania zapytania */
--} GG_PACKED;
--
--#define GG_NEW_STATUS 0x0002
--
--#ifndef DOXYGEN
--
--#define GG_STATUS_NOT_AVAIL 0x0001
--#define GG_STATUS_NOT_AVAIL_DESCR 0x0015
--#define GG_STATUS_FFC 0x0017
--#define GG_STATUS_FFC_DESCR 0x0018
--#define GG_STATUS_AVAIL 0x0002
--#define GG_STATUS_AVAIL_DESCR 0x0004
--#define GG_STATUS_BUSY 0x0003
--#define GG_STATUS_BUSY_DESCR 0x0005
--#define GG_STATUS_DND 0x0021
--#define GG_STATUS_DND_DESCR 0x0022
--#define GG_STATUS_INVISIBLE 0x0014
--#define GG_STATUS_INVISIBLE_DESCR 0x0016
--#define GG_STATUS_BLOCKED 0x0006
--
--#define GG_STATUS_IMAGE_MASK 0x0100
--#define GG_STATUS_DESCR_MASK 0x4000
--#define GG_STATUS_FRIENDS_MASK 0x8000
--
--#define GG_STATUS_FLAG_UNKNOWN 0x00000001
--#define GG_STATUS_FLAG_VIDEO 0x00000002
--#define GG_STATUS_FLAG_MOBILE 0x00100000
--#define GG_STATUS_FLAG_SPAM 0x00800000
--
--#else
--
--/**
-- * Rodzaje statusów użytkownika.
-- *
-- * \ingroup status
-- */
--enum {
-- GG_STATUS_NOT_AVAIL, /**< Niedostępny */
-- GG_STATUS_NOT_AVAIL_DESCR, /**< Niedostępny z opisem */
-- GG_STATUS_FFC, /**< PoGGadaj ze mnÄ… */
-- GG_STATUS_FFC_DESCR, /**< PoGGadaj ze mnÄ… z opisem */
-- GG_STATUS_AVAIL, /**< Dostępny */
-- GG_STATUS_AVAIL_DESCR, /**< Dostępny z opisem */
-- GG_STATUS_BUSY, /**< Zajęty */
-- GG_STATUS_BUSY_DESCR, /**< Zajęty z opisem */
-- GG_STATUS_DND, /**< Nie przeszkadzać */
-- GG_STATUS_DND_DESCR, /**< Nie przeszakdzać z opisem */
-- GG_STATUS_INVISIBLE, /**< Niewidoczny (tylko własny status) */
-- GG_STATUS_INVISIBLE_DESCR, /**< Niewidoczny z opisem (tylko własny status) */
-- GG_STATUS_BLOCKED, /**< Zablokowany (tylko status innych) */
-- GG_STATUS_IMAGE_MASK, /**< Flaga bitowa oznaczająca opis graficzny (tylko jeśli wybrano \c GG_FEATURE_IMAGE_DESCR) */
-- GG_STATUS_DESCR_MASK, /**< Flaga bitowa oznaczająca status z opisem (tylko jeśli wybrano \c GG_FEATURE_IMAGE_DESCR) */
-- GG_STATUS_FRIENDS_MASK, /**< Flaga bitowa dostępności tylko dla znajomych */
--};
--
--/**
-- * Rodzaje statusów użytkownika. Mapa bitowa.
-- *
-- * \ingroup status
-- */
--enum {
-- GG_STATUS_FLAG_UNKNOWN, /**< Przeznaczenie nieznane, ale występuje zawsze */
-- GG_STATUS_FLAG_VIDEO, /**< Klient obsługuje wideorozmowy */
-- GG_STATUS_FLAG_MOBILE, /**< Klient mobilny (ikona telefonu komórkowego) */
-- GG_STATUS_FLAG_SPAM, /**< Klient chce otrzymywać linki od nieznajomych */
--};
--
--#endif /* DOXYGEN */
--
--/**
-- * \ingroup status
-- *
-- * Flaga bitowa dostepnosci informujaca ze mozemy voipowac
-- */
--
--#define GG_STATUS_VOICE_MASK 0x20000 /**< czy ma wlaczone audio (7.7) */
--
--/**
-- * \ingroup status
-- *
-- * Maksymalna długośc opisu.
-- */
--#define GG_STATUS_DESCR_MAXSIZE 255
--#define GG_STATUS_DESCR_MAXSIZE_PRE_8_0 70
--
--#define GG_STATUS_MASK 0xff
--
--/* GG_S_F() tryb tylko dla znajomych */
--#define GG_S_F(x) (((x) & GG_STATUS_FRIENDS_MASK) != 0)
--
--/* GG_S() stan bez uwzględnienia dodatkowych flag */
--#define GG_S(x) ((x) & GG_STATUS_MASK)
--
--
--/* GG_S_FF() chętny do rozmowy */
--#define GG_S_FF(x) (GG_S(x) == GG_STATUS_FFC || GG_S(x) == GG_STATUS_FFC_DESCR)
--
--/* GG_S_AV() dostępny */
--#define GG_S_AV(x) (GG_S(x) == GG_STATUS_AVAIL || GG_S(x) == GG_STATUS_AVAIL_DESCR)
--
--/* GG_S_AW() zaraz wracam */
--#define GG_S_AW(x) (GG_S(x) == GG_STATUS_BUSY || GG_S(x) == GG_STATUS_BUSY_DESCR)
--
--/* GG_S_DD() nie przeszkadzać */
--#define GG_S_DD(x) (GG_S(x) == GG_STATUS_DND || GG_S(x) == GG_STATUS_DND_DESCR)
--
--/* GG_S_NA() niedostępny */
--#define GG_S_NA(x) (GG_S(x) == GG_STATUS_NOT_AVAIL || GG_S(x) == GG_STATUS_NOT_AVAIL_DESCR)
--
--/* GG_S_I() niewidoczny */
--#define GG_S_I(x) (GG_S(x) == GG_STATUS_INVISIBLE || GG_S(x) == GG_STATUS_INVISIBLE_DESCR)
--
--
--/* GG_S_A() dostępny lub chętny do rozmowy */
--#define GG_S_A(x) (GG_S_FF(x) || GG_S_AV(x))
--
--/* GG_S_B() zajęty lub nie przeszkadzać */
--#define GG_S_B(x) (GG_S_AW(x) || GG_S_DD(x))
--
--
--/* GG_S_D() stan opisowy */
--#define GG_S_D(x) (GG_S(x) == GG_STATUS_NOT_AVAIL_DESCR || \
-- GG_S(x) == GG_STATUS_FFC_DESCR || \
-- GG_S(x) == GG_STATUS_AVAIL_DESCR || \
-- GG_S(x) == GG_STATUS_BUSY_DESCR || \
-- GG_S(x) == GG_STATUS_DND_DESCR || \
-- GG_S(x) == GG_STATUS_INVISIBLE_DESCR)
--
--/* GG_S_BL() blokowany lub blokujÄ…cy */
--#define GG_S_BL(x) (GG_S(x) == GG_STATUS_BLOCKED)
--
--/**
-- * Zmiana statusu (pakiet \c GG_NEW_STATUS i \c GG_NEW_STATUS80BETA)
-- */
--struct gg_new_status {
-- uint32_t status; /**< Nowy status */
--} GG_PACKED;
--
--#define GG_NOTIFY_FIRST 0x000f
--#define GG_NOTIFY_LAST 0x0010
--
--#define GG_NOTIFY 0x0010
--
--struct gg_notify {
-- uint32_t uin; /* numerek danej osoby */
-- uint8_t dunno1; /* rodzaj wpisu w liście */
--} GG_PACKED;
--
--#ifndef DOXYGEN
--
--#define GG_USER_OFFLINE 0x01
--#define GG_USER_NORMAL 0x03
--#define GG_USER_BLOCKED 0x04
--
--#else
--
--/**
-- * \ingroup contacts
-- *
-- * Rodzaj kontaktu.
-- */
--enum {
-- GG_USER_NORMAL, /**< Zwykły kontakt */
-- GG_USER_BLOCKED, /**< Zablokowany */
-- GG_USER_OFFLINE, /**< Niewidoczny dla kontaktu */
--};
--
--#endif /* DOXYGEN */
--
--#define GG_LIST_EMPTY 0x0012
--
--#define GG_NOTIFY_REPLY 0x000c /* tak, to samo co GG_LOGIN */
--
--struct gg_notify_reply {
-- uint32_t uin; /* numerek */
-- uint32_t status; /* status danej osoby */
-- uint32_t remote_ip; /* adres ip delikwenta */
-- uint16_t remote_port; /* port, na którym słucha klient */
-- uint32_t version; /* wersja klienta */
-- uint16_t dunno2; /* znowu port? */
--} GG_PACKED;
--
--#define GG_NOTIFY_REPLY60 0x0011
--
--struct gg_notify_reply60 {
-- uint32_t uin; /* numerek plus flagi w MSB */
-- uint8_t status; /* status danej osoby */
-- uint32_t remote_ip; /* adres ip delikwenta */
-- uint16_t remote_port; /* port, na którym słucha klient */
-- uint8_t version; /* wersja klienta */
-- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
-- uint8_t dunno1; /* 0x00 */
--} GG_PACKED;
--
--#define GG_STATUS60 0x000f
--
--struct gg_status60 {
-- uint32_t uin; /* numerek plus flagi w MSB */
-- uint8_t status; /* status danej osoby */
-- uint32_t remote_ip; /* adres ip delikwenta */
-- uint16_t remote_port; /* port, na którym słucha klient */
-- uint8_t version; /* wersja klienta */
-- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
-- uint8_t dunno1; /* 0x00 */
--} GG_PACKED;
--
--#define GG_NOTIFY_REPLY77 0x0018
--
--struct gg_notify_reply77 {
-- uint32_t uin; /* numerek plus flagi w MSB */
-- uint8_t status; /* status danej osoby */
-- uint32_t remote_ip; /* adres ip delikwenta */
-- uint16_t remote_port; /* port, na którym słucha klient */
-- uint8_t version; /* wersja klienta */
-- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
-- uint8_t dunno1; /* 0x00 */
-- uint32_t dunno2; /* ? */
--} GG_PACKED;
--
--#define GG_STATUS77 0x0017
--
--struct gg_status77 {
-- uint32_t uin; /* numerek plus flagi w MSB */
-- uint8_t status; /* status danej osoby */
-- uint32_t remote_ip; /* adres ip delikwenta */
-- uint16_t remote_port; /* port, na którym słucha klient */
-- uint8_t version; /* wersja klienta */
-- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
-- uint8_t dunno1; /* 0x00 */
-- uint32_t dunno2; /* ? */
--} GG_PACKED;
--
--#define GG_ADD_NOTIFY 0x000d
--#define GG_REMOVE_NOTIFY 0x000e
--
--struct gg_add_remove {
-- uint32_t uin; /* numerek */
-- uint8_t dunno1; /* bitmapa */
--} GG_PACKED;
--
--#define GG_STATUS 0x0002
--
--struct gg_status {
-- uint32_t uin; /* numerek */
-- uint32_t status; /* nowy stan */
--} GG_PACKED;
--
--#define GG_SEND_MSG 0x000b
--
--#ifndef DOXYGEN
--
--#define GG_CLASS_QUEUED 0x0001
--#define GG_CLASS_OFFLINE GG_CLASS_QUEUED
--#define GG_CLASS_MSG 0x0004
--#define GG_CLASS_CHAT 0x0008
--#define GG_CLASS_CTCP 0x0010
--#define GG_CLASS_ACK 0x0020
--#define GG_CLASS_EXT GG_CLASS_ACK /**< Dla kompatybilności wstecz */
--
--#else
--
--/**
-- * Klasy wiadomości. Wartości są maskami bitowymi, które w większości
-- * przypadków można łączyć (połączenie \c GG_CLASS_MSG i \c GG_CLASS_CHAT
-- * nie ma sensu).
-- *
-- * \ingroup messages
-- */
--enum {
-- GG_CLASS_MSG, /**< Wiadomość ma pojawić się w osobnym oknie */
-- GG_CLASS_CHAT, /**< Wiadomość ma pojawić się w oknie rozmowy */
-- GG_CLASS_CTCP, /**< Wiadomość przeznaczona dla klienta Gadu-Gadu */
-- GG_CLASS_ACK, /**< Klient nie życzy sobie potwierdzenia */
-- GG_CLASS_QUEUED, /**< Wiadomość zakolejkowana na serwerze (tylko przy odbieraniu) */
--};
--
--#endif /* DOXYGEN */
--
--/**
-- * Maksymalna długość wiadomości.
-- *
-- * \ingroup messages
-- */
--#define GG_MSG_MAXSIZE 1989
--
--struct gg_send_msg {
-- uint32_t recipient;
-- uint32_t seq;
-- uint32_t msgclass;
--} GG_PACKED;
--
--struct gg_msg_richtext {
-- uint8_t flag;
-- uint16_t length;
--} GG_PACKED;
--
--/**
-- * Struktura opisująca formatowanie tekstu. W zależności od wartości pola
-- * \c font, zaraz za tą strukturą może wystąpić \c gg_msg_richtext_color
-- * lub \c gg_msg_richtext_image.
-- *
-- * \ingroup messages
-- */
--struct gg_msg_richtext_format {
-- uint16_t position; /**< PoczÄ…tkowy znak formatowania (liczony od 0) */
-- uint8_t font; /**< Atrybuty formatowania */
--} GG_PACKED;
--
--#ifndef DOXYGEN
--
--#define GG_FONT_BOLD 0x01
--#define GG_FONT_ITALIC 0x02
--#define GG_FONT_UNDERLINE 0x04
--#define GG_FONT_COLOR 0x08
--#define GG_FONT_IMAGE 0x80
--
--#else
--
--/**
-- * Atrybuty formatowania wiadomości.
-- *
-- * \ingroup messages
-- */
--enum {
-- GG_FONT_BOLD,
-- GG_FONT_ITALIC,
-- GG_FONT_UNDERLINE,
-- GG_FONT_COLOR,
-- GG_FONT_IMAGE
--};
--
--#endif /* DOXYGEN */
--
--/**
-- * Struktura opisujÄ…cÄ… kolor tekstu dla atrybutu \c GG_FONT_COLOR.
-- *
-- * \ingroup messages
-- */
--struct gg_msg_richtext_color {
-- uint8_t red; /**< Składowa czerwona koloru */
-- uint8_t green; /**< Składowa zielona koloru */
-- uint8_t blue; /**< Składowa niebieska koloru */
--} GG_PACKED;
--
--/**
-- * Strukturya opisująca obrazek wstawiony do wiadomości dla atrubutu
-- * \c GG_FONT_IMAGE.
-- *
-- * \ingroup messages
-- */
--struct gg_msg_richtext_image {
-- uint16_t unknown1; /**< Nieznane pole o wartości 0x0109 */
-- uint32_t size; /**< Rozmiar obrazka */
-- uint32_t crc32; /**< Suma kontrolna CRC32 obrazka */
--} GG_PACKED;
--
--struct gg_msg_recipients {
-- uint8_t flag;
-- uint32_t count;
--} GG_PACKED;
--
--struct gg_msg_image_request {
-- uint8_t flag;
-- uint32_t size;
-- uint32_t crc32;
--} GG_PACKED;
--
--struct gg_msg_image_reply {
-- uint8_t flag;
-- uint32_t size;
-- uint32_t crc32;
-- /* char filename[]; */
-- /* char image[]; */
--} GG_PACKED;
--
--#define GG_SEND_MSG_ACK 0x0005
--
--#ifndef DOXYGEN
--
--#define GG_ACK_BLOCKED 0x0001
--#define GG_ACK_DELIVERED 0x0002
--#define GG_ACK_QUEUED 0x0003
--#define GG_ACK_MBOXFULL 0x0004
--#define GG_ACK_NOT_DELIVERED 0x0006
--
--#else
--
--/**
-- * Status doręczenia wiadomości.
-- *
-- * \ingroup messages
-- */
--enum
--{
-- GG_ACK_DELIVERED, /**< Wiadomość dostarczono. */
-- GG_ACK_QUEUED, /**< Wiadomość zakolejkowano z powodu niedostępności odbiorcy. */
-- GG_ACK_BLOCKED, /**< Wiadomość zablokowana przez serwer (spam, świąteczne ograniczenia itd.) */
-- GG_ACK_MBOXFULL, /**< Wiadomości nie dostarczono z powodu zapełnionej kolejki wiadomości odbiorcy. */
-- GG_ACK_NOT_DELIVERED /**< Wiadomości nie dostarczono (tylko dla \c GG_CLASS_CTCP). */
--};
--
--#endif /* DOXYGEN */
--
--struct gg_send_msg_ack {
-- uint32_t status;
-- uint32_t recipient;
-- uint32_t seq;
--} GG_PACKED;
--
--#define GG_RECV_MSG 0x000a
--
--struct gg_recv_msg {
-- uint32_t sender;
-- uint32_t seq;
-- uint32_t time;
-- uint32_t msgclass;
--} GG_PACKED;
--
--#define GG_PING 0x0008
--
--#define GG_PONG 0x0007
--
--#define GG_DISCONNECTING 0x000b
--
--#define GG_USERLIST_REQUEST 0x0016
--
--#define GG_XML_EVENT 0x0027
--
--#ifndef DOXYGEN
--
--#define GG_USERLIST_PUT 0x00
--#define GG_USERLIST_PUT_MORE 0x01
--#define GG_USERLIST_GET 0x02
--
--#else
--
--/**
-- * \ingroup importexport
-- *
-- * Rodzaj zapytania.
-- */
--enum {
-- GG_USERLIST_PUT, /**< Eksport listy kontaktów. */
-- GG_USERLIST_GET, /**< Import listy kontaktów. */
--};
--
--#endif /* DOXYGEN */
--
--struct gg_userlist_request {
-- uint8_t type;
--} GG_PACKED;
--
--#define GG_USERLIST_REPLY 0x0010
--
--#ifndef DOXYGEN
--
--#define GG_USERLIST_PUT_REPLY 0x00
--#define GG_USERLIST_PUT_MORE_REPLY 0x02
--#define GG_USERLIST_GET_REPLY 0x06
--#define GG_USERLIST_GET_MORE_REPLY 0x04
--
--#else
--
--/**
-- * \ingroup importexport
-- *
-- * Rodzaj odpowiedzi.
-- */
--enum {
-- GG_USERLIST_PUT_REPLY, /**< Wyeksportowano listy kontaktów. */
-- GG_USERLIST_GET_REPLY, /**< Zaimportowano listę kontaktów. */
--};
--
--#endif /* DOXYGEN */
--
--struct gg_userlist_reply {
-- uint8_t type;
--} GG_PACKED;
--
--#ifndef DOXYGEN
--
--#define GG_USERLIST100_PUT 0x00
--#define GG_USERLIST100_GET 0x02
--
--#else
--
--/**
-- * \ingroup importexport
-- *
-- * Rodzaj zapytania (10.0).
-- */
--enum {
-- GG_USERLIST100_PUT, /**< Eksport listy kontaktów. */
-- GG_USERLIST100_GET, /**< Import listy kontaktów. */
--};
--
--#endif /* DOXYGEN */
--
--#ifndef DOXYGEN
--
--#define GG_USERLIST100_FORMAT_TYPE_NONE 0x00
--#define GG_USERLIST100_FORMAT_TYPE_GG70 0x01
--#define GG_USERLIST100_FORMAT_TYPE_GG100 0x02
--
--#else
--
--/**
-- * \ingroup importexport
-- *
-- * Typ formatu listy kontaktów (10.0).
-- */
--enum {
-- GG_USERLIST100_FORMAT_TYPE_NONE, /**< Brak treści listy kontaktów. */
-- GG_USERLIST100_FORMAT_TYPE_GG70, /**< Format listy kontaktów zgodny z Gadu-Gadu 7.0. */
-- GG_USERLIST100_FORMAT_TYPE_GG100, /**< Format listy kontaktów zgodny z Gadu-Gadu 10.0. */
--};
--
--#endif /* DOXYGEN */
--
--#ifndef DOXYGEN
--
--#define GG_USERLIST100_REPLY_LIST 0x00
--#define GG_USERLIST100_REPLY_ACK 0x10
--#define GG_USERLIST100_REPLY_REJECT 0x12
--
--#else
--
--/**
-- * \ingroup importexport
-- *
-- * Typ odpowiedzi listy kontaktów (10.0).
-- */
--enum {
-- GG_USERLIST100_REPLY_LIST, /**< W odpowiedzi znajduje się aktualna lista kontaktów na serwerze. */
-- GG_USERLIST100_REPLY_ACK, /**< Potwierdzenie odebrania nowej wersji listy kontaktów. W polu \c gg_userlist100_reply.version znajduje się numer nowej wersji listy kontaktów. */
-- GG_USERLIST100_REPLY_REJECT, /**< Odmowa przyjęcia nowej wersji listy kontaktów. W polu \c gg_userlist100_reply.version znajduje się numer wersji listy kontaktów aktualnie przechowywanej przez serwer. */
--};
--
--#endif /* DOXYGEN */
--
--struct gg_dcc_tiny_packet {
-- uint8_t type; /* rodzaj pakietu */
--} GG_PACKED;
--
--struct gg_dcc_small_packet {
-- uint32_t type; /* rodzaj pakietu */
--} GG_PACKED;
--
--struct gg_dcc_big_packet {
-- uint32_t type; /* rodzaj pakietu */
-- uint32_t dunno1; /* niewiadoma */
-- uint32_t dunno2; /* niewiadoma */
--} GG_PACKED;
--
--/*
-- * póki co, nie znamy dokładnie protokołu. nie wiemy, co czemu odpowiada.
-- * nazwy są niepoważne i tymczasowe.
-- */
--#define GG_DCC_WANT_FILE 0x0003 /* peer chce plik */
--#define GG_DCC_HAVE_FILE 0x0001 /* więc mu damy */
--#define GG_DCC_HAVE_FILEINFO 0x0003 /* niech ma informacje o pliku */
--#define GG_DCC_GIMME_FILE 0x0006 /* peer jest pewny */
--#define GG_DCC_CATCH_FILE 0x0002 /* wysyłamy plik */
--
--#define GG_DCC_FILEATTR_READONLY 0x0020
--
--#define GG_DCC_TIMEOUT_SEND 1800 /* 30 minut */
--#define GG_DCC_TIMEOUT_GET 1800 /* 30 minut */
--#define GG_DCC_TIMEOUT_FILE_ACK 300 /* 5 minut */
--#define GG_DCC_TIMEOUT_VOICE_ACK 300 /* 5 minut */
--
--#define GG_DCC7_INFO 0x1f
--
--struct gg_dcc7_info {
-- uint32_t uin; /* numer nadawcy */
-- uint32_t type; /* sposób połączenia */
-- gg_dcc7_id_t id; /* identyfikator połączenia */
-- char info[GG_DCC7_INFO_LEN]; /* informacje o połączeniu "ip port" */
-- char hash[GG_DCC7_INFO_HASH_LEN];/* skrót "ip" */
--} GG_PACKED;
--
--#define GG_DCC7_NEW 0x20
--
--struct gg_dcc7_new {
-- gg_dcc7_id_t id; /* identyfikator połączenia */
-- uint32_t uin_from; /* numer nadawcy */
-- uint32_t uin_to; /* numer odbiorcy */
-- uint32_t type; /* rodzaj transmisji */
-- unsigned char filename[GG_DCC7_FILENAME_LEN]; /* nazwa pliku */
-- uint32_t size; /* rozmiar pliku */
-- uint32_t size_hi; /* rozmiar pliku (starsze bajty) */
-- unsigned char hash[GG_DCC7_HASH_LEN]; /* hash SHA1 */
--} GG_PACKED;
--
--#define GG_DCC7_ACCEPT 0x21
--
--struct gg_dcc7_accept {
-- uint32_t uin; /* numer przyjmującego połączenie */
-- gg_dcc7_id_t id; /* identyfikator połączenia */
-- uint32_t offset; /* offset przy wznawianiu transmisji */
-- uint32_t dunno1; /* 0x00000000 */
--} GG_PACKED;
--
--// XXX API
--#define GG_DCC7_TYPE_P2P 0x00000001 /**< Połączenie bezpośrednie */
--#define GG_DCC7_TYPE_SERVER 0x00000002 /**< Połączenie przez serwer */
--
--#define GG_DCC7_REJECT 0x22
--
--struct gg_dcc7_reject {
-- uint32_t uin; /**< Numer odrzucającego połączenie */
-- gg_dcc7_id_t id; /**< Identyfikator połączenia */
-- uint32_t reason; /**< Powód rozłączenia */
--} GG_PACKED;
--
--// XXX API
--#define GG_DCC7_REJECT_BUSY 0x00000001 /**< Połączenie bezpośrednie już trwa, nie umiem obsłużyć więcej */
--#define GG_DCC7_REJECT_USER 0x00000002 /**< Użytkownik odrzucił połączenie */
--#define GG_DCC7_REJECT_VERSION 0x00000006 /**< Druga strona ma wersję klienta nieobsługującą połączeń bezpośrednich tego typu */
--
--#define GG_DCC7_ID_REQUEST 0x23
--
--struct gg_dcc7_id_request {
-- uint32_t type; /**< Rodzaj tranmisji */
--} GG_PACKED;
--
--// XXX API
--#define GG_DCC7_TYPE_VOICE 0x00000001 /**< Transmisja głosu */
--#define GG_DCC7_TYPE_FILE 0x00000004 /**< transmisja pliku */
--
--#define GG_DCC7_ID_REPLY 0x23
--
--struct gg_dcc7_id_reply {
-- uint32_t type; /** Rodzaj transmisji */
-- gg_dcc7_id_t id; /** Przyznany identyfikator */
--} GG_PACKED;
--
--#define GG_DCC7_DUNNO1 0x24
--
--struct gg_dcc7_dunno1 {
-- // XXX
--} GG_PACKED;
--
--#define GG_DCC7_TIMEOUT_CONNECT 10 /* 10 sekund */
--#define GG_DCC7_TIMEOUT_SEND 1800 /* 30 minut */
--#define GG_DCC7_TIMEOUT_GET 1800 /* 30 minut */
--#define GG_DCC7_TIMEOUT_FILE_ACK 300 /* 5 minut */
--#define GG_DCC7_TIMEOUT_VOICE_ACK 300 /* 5 minut */
--
--#ifdef _WIN32
--#pragma pack(pop)
--#endif
--
--#ifdef __cplusplus
--}
--#endif
--
--#endif /* __GG_LIBGADU_H */
--
--/*
-- * Local variables:
-- * c-indentation-style: k&r
-- * c-basic-offset: 8
-- * indent-tabs-mode: notnil
-- * End:
-- *
-- * vim: shiftwidth=8:
-- */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu-internal.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu-internal.h
---- pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu-internal.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu-internal.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,44 +0,0 @@
--/* $Id$ */
--
--/*
-- * (C) Copyright 2009 Jakub Zawadzki <darkjames@darkjames.ath.cx>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--#ifndef LIBGADU_INTERNAL_H
--#define LIBGADU_INTERNAL_H
--
--#include "libgadu.h"
--
--struct gg_dcc7_relay {
-- uint32_t addr;
-- uint16_t port;
-- uint8_t family;
--};
--
--typedef struct gg_dcc7_relay gg_dcc7_relay_t;
--
--int gg_pubdir50_handle_reply_sess(struct gg_session *sess, struct gg_event *e, const char *packet, int length);
--
--int gg_resolve(int *fd, int *pid, const char *hostname);
--int gg_resolve_pthread(int *fd, void **resolver, const char *hostname);
--void gg_resolve_pthread_cleanup(void *resolver, int kill);
--
--#ifdef HAVE_UINT64_T
--uint64_t gg_fix64(uint64_t x);
--#endif
--
--#endif /* LIBGADU_INTERNAL_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/message.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/message.c
---- pidgin-2.10.7/libpurple/protocols/gg/lib/message.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/message.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,663 +0,0 @@
--/*
-- * (C) Copyright 2001-2010 Wojtek Kaniewski <wojtekka@irc.pl>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--/**
-- * \file message.c
-- *
-- * \brief Obsługa wiadomości
-- *
-- * Plik zawiera funkcje dotyczące obsługi "klasy" gg_message_t, które
-- * w przyszłości zostaną dołączone do API. Obecnie używane są funkcje
-- * konwersji między tekstem z atrybutami i HTML.
-- */
--
--#include <stdlib.h>
--#include <string.h>
--#include <errno.h>
--#include <limits.h>
--#include <ctype.h>
--
--#include "message.h"
--
--#if 0
--
--gg_message_t *gg_message_new(void)
--{
-- gg_message_t *gm;
--
-- gm = malloc(sizeof(gg_message_t));
--
-- if (gm == NULL)
-- return NULL;
--
-- memset(gm, 0, sizeof(gg_message_t));
--
-- gm->msgclass = GG_CLASS_CHAT;
-- gm->seq = (uint32_t) -1;
--
-- return gm;
--}
--
--int gg_message_init(gg_message_t *gm, int msgclass, int seq, uin_t *recipients, size_t recipient_count, char *text, char *html, char *attributes, size_t attributes_length, int auto_convert)
--{
-- GG_MESSAGE_CHECK(gm, -1);
--
-- memset(gm, 0, sizeof(gg_message_t));
-- gm->recipients = recipients;
-- gm->recipient_count = recipient_count;
-- gm->text = text;
-- gm->html = html;
-- gm->attributes = attributes;
-- gm->attributes_length = attributes_length;
-- gm->msgclass = msgclass;
-- gm->seq = seq;
-- gm->auto_convert = auto_convert;
--
-- return 0;
--}
--
--void gg_message_free(gg_message_t *gm)
--{
-- if (gm == NULL) {
-- errno = EINVAL;
-- return;
-- }
--
-- free(gm->text);
-- free(gm->text_converted);
-- free(gm->html);
-- free(gm->html_converted);
-- free(gm->recipients);
-- free(gm->attributes);
--
-- free(gm);
--}
--
--int gg_message_set_auto_convert(gg_message_t *gm, int auto_convert)
--{
-- GG_MESSAGE_CHECK(gm, -1);
--
-- gm->auto_convert = !!auto_convert;
--
-- if (!gm->auto_convert) {
-- free(gm->text_converted);
-- free(gm->html_converted);
-- gm->text_converted = NULL;
-- gm->html_converted = NULL;
-- }
--
-- return 0;
--}
--
--int gg_message_get_auto_convert(gg_message_t *gm)
--{
-- GG_MESSAGE_CHECK(gm, -1);
--
-- return gm->auto_convert;
--}
--
--int gg_message_set_recipients(gg_message_t *gm, const uin_t *recipients, size_t recipient_count)
--{
-- GG_MESSAGE_CHECK(gm, -1);
--
-- if (recipient_count >= INT_MAX / sizeof(uin_t)) {
-- errno = EINVAL;
-- return -1;
-- }
--
-- if ((recipients == NULL) || (recipient_count == 0)) {
-- free(gm->recipients);
-- gm->recipients = NULL;
-- gm->recipient_count = 0;
-- } else {
-- uin_t *tmp;
--
-- tmp = realloc(gm->recipients, recipient_count * sizeof(uin_t));
--
-- if (tmp == NULL)
-- return -1;
--
-- memcpy(tmp, recipients, recipient_count * sizeof(uin_t));
--
-- gm->recipients = tmp;
-- gm->recipient_count = recipient_count;
-- }
--
-- return 0;
--}
--
--int gg_message_set_recipient(gg_message_t *gm, uin_t recipient)
--{
-- return gg_message_set_recipients(gm, &recipient, 1);
--}
--
--int gg_message_get_recipients(gg_message_t *gm, const uin_t **recipients, size_t *recipient_count)
--{
-- GG_MESSAGE_CHECK(gm, -1);
--
-- if (recipients != NULL)
-- *recipients = gm->recipients;
--
-- if (recipient_count != NULL)
-- *recipient_count = gm->recipient_count;
--
-- return 0;
--}
--
--uin_t gg_message_get_recipient(gg_message_t *gm)
--{
-- GG_MESSAGE_CHECK(gm, (uin_t) -1);
--
-- if ((gm->recipients == NULL) || (gm->recipient_count < 1)) {
-- // errno = XXX;
-- return (uin_t) -1;
-- }
--
-- return gm->recipients[0];
--}
--
--int gg_message_set_class(gg_message_t *gm, uint32_t msgclass)
--{
-- GG_MESSAGE_CHECK(gm, -1);
--
-- gm->msgclass = msgclass;
--
-- return 0;
--}
--
--uint32_t gg_message_get_class(gg_message_t *gm)
--{
-- GG_MESSAGE_CHECK(gm, (uint32_t) -1);
--
-- return gm->msgclass;
--}
--
--int gg_message_set_seq(gg_message_t *gm, uint32_t seq)
--{
-- GG_MESSAGE_CHECK(gm, -1);
--
-- gm->seq = seq;
--
-- return 0;
--}
--
--uint32_t gg_message_get_seq(gg_message_t *gm)
--{
-- GG_MESSAGE_CHECK(gm, (uint32_t) -1);
--
-- return gm->seq;
--}
--
--int gg_message_set_text(gg_message_t *gm, const char *text)
--{
-- GG_MESSAGE_CHECK(gm, -1);
--
-- if (text == NULL) {
-- free(gm->text);
-- gm->text = NULL;
-- } else {
-- char *tmp;
--
-- tmp = strdup(text);
--
-- if (tmp == NULL)
-- return -1;
--
-- free(gm->text);
-- gm->text = tmp;
-- }
--
-- free(gm->html_converted);
-- gm->html_converted = NULL;
--
-- return 0;
--}
--
--const char *gg_message_get_text(gg_message_t *gm)
--{
-- GG_MESSAGE_CHECK(gm, NULL);
--
-- if (gm->text_converted != NULL)
-- return gm->text_converted;
--
-- if (gm->text == NULL && gm->html != NULL && gm->auto_convert) {
-- size_t len;
--
-- free(gm->text_converted);
--
-- len = gg_message_html_to_text(NULL, gm->html);
--
-- gm->text_converted = malloc(len + 1);
--
-- if (gm->text_converted == NULL)
-- return NULL;
--
-- gg_message_html_to_text(gm->text_converted, gm->html);
--
-- return gm->text_converted;
-- }
--
-- return gm->text;
--}
--
--int gg_message_set_html(gg_message_t *gm, const char *html)
--{
-- GG_MESSAGE_CHECK(gm, -1);
--
-- if (html == NULL) {
-- free(gm->html);
-- gm->html = NULL;
-- } else {
-- char *tmp;
--
-- tmp = strdup(html);
--
-- if (tmp == NULL)
-- return -1;
--
-- free(gm->html);
-- gm->html = tmp;
-- }
--
-- free(gm->text_converted);
-- gm->text_converted = NULL;
--
-- return 0;
--}
--
--const char *gg_message_get_html(gg_message_t *gm)
--{
-- GG_MESSAGE_CHECK(gm, NULL);
--
-- if (gm->html_converted != NULL)
-- return gm->html_converted;
--
-- if (gm->html == NULL && gm->text != NULL && gm->auto_convert) {
-- size_t len;
--
-- free(gm->html_converted);
--
-- len = gg_message_text_to_html(NULL, gm->text, gm->attributes, gm->attributes_length);
--
-- gm->html_converted = malloc(len + 1);
--
-- if (gm->html_converted == NULL)
-- return NULL;
--
-- gg_message_text_to_html(gm->html_converted, gm->text, gm->attributes, gm->attributes_length);
--
-- return gm->html_converted;
-- }
--
-- return gm->html;
--}
--
--int gg_message_set_attributes(gg_message_t *gm, const char *attributes, size_t length)
--{
-- GG_MESSAGE_CHECK(gm, -1);
--
-- if (length > 0xfffd) {
-- // errno = XXX;
-- return -1;
-- }
--
-- if ((attributes == NULL) || (length == 0)) {
-- free(gm->attributes);
-- gm->attributes = NULL;
-- gm->attributes_length = 0;
-- } else {
-- char *tmp;
--
-- tmp = realloc(gm->attributes, length);
--
-- if (tmp == NULL)
-- return -1;
--
-- gm->attributes = tmp;
-- gm->attributes_length = length;
-- }
--
-- free(gm->html_converted);
-- gm->html_converted = NULL;
--
-- return 0;
--}
--
--int gg_message_get_attributes(gg_message_t *gm, const char **attributes, size_t *attributes_length)
--{
-- GG_MESSAGE_CHECK(gm, -1);
--
-- if (attributes != NULL)
-- *attributes = gm->attributes;
--
-- if (attributes_length != NULL)
-- *attributes_length = gm->attributes_length;
--
-- return 0;
--}
--
--#endif
--
--/**
-- * \internal Dodaje tekst na koniec bufora.
-- *
-- * \param dst Wskaźnik na bufor roboczy
-- * \param pos Wskaźnik na aktualne położenie w buforze roboczym
-- * \param src Dodawany tekst
-- * \param len Długość dodawanego tekstu
-- */
--static void gg_append(char *dst, size_t *pos, const void *src, int len)
--{
-- if (dst != NULL)
-- memcpy(&dst[*pos], src, len);
--
-- *pos += len;
--}
--
--/**
-- * \internal Zamienia tekst z formatowaniem Gadu-Gadu na HTML.
-- *
-- * \param dst Bufor wynikowy (może być \c NULL)
-- * \param src Tekst źródłowy w UTF-8
-- * \param format Atrybuty tekstu źródłowego
-- * \param format_len Długość bloku atrybutów tekstu źródłowego
-- *
-- * \note Wynikowy tekst nie jest idealnym kodem HTML, ponieważ ma jak
-- * dokładniej odzwierciedlać to, co wygenerowałby oryginalny klient.
-- *
-- * \note Dokleja \c \\0 na końcu bufora wynikowego.
-- *
-- * \return Długość tekstu wynikowego bez \c \\0 (nawet jeśli \c dst to \c NULL).
-- */
--size_t gg_message_text_to_html(char *dst, const char *src, const char *format, size_t format_len)
--{
-- const char span_fmt[] = "<span style=\"color:#%02x%02x%02x; font-family:'MS Shell Dlg 2'; font-size:9pt; \">";
-- const int span_len = 75;
-- const char img_fmt[] = "<img name=\"%02x%02x%02x%02x%02x%02x%02x%02x\">";
-- const int img_len = 29;
-- int char_pos = 0;
-- int format_idx = 0;
-- unsigned char old_attr = 0;
-- const unsigned char *color = (const unsigned char*) "\x00\x00\x00";
-- int i;
-- size_t len;
-- const unsigned char *format_ = (const unsigned char*) format;
--
-- len = 0;
--
-- /* Nie mamy atrybutów dla pierwsze znaku, a tekst nie jest pusty, więc
-- * tak czy inaczej trzeba otworzyć <span>. */
--
-- if (src[0] != 0 && (format_idx + 3 > format_len || (format_[format_idx] | (format_[format_idx + 1] << 8)) != 0)) {
-- if (dst != NULL)
-- sprintf(&dst[len], span_fmt, 0, 0, 0);
--
-- len += span_len;
-- }
--
-- /* Pętla przechodzi też przez kończące \0, żeby móc dokleić obrazek
-- * na końcu tekstu. */
--
-- for (i = 0; ; i++) {
-- /* Analizuj atrybuty tak długo jak dotyczą aktualnego znaku. */
-- for (;;) {
-- unsigned char attr;
-- int attr_pos;
--
-- if (format_idx + 3 > format_len)
-- break;
--
-- attr_pos = format_[format_idx] | (format_[format_idx + 1] << 8);
--
-- if (attr_pos != char_pos)
-- break;
--
-- attr = format_[format_idx + 2];
--
-- /* Nie doklejaj atrybutów na końcu, co najwyżej obrazki. */
--
-- if (src[i] == 0)
-- attr &= ~(GG_FONT_BOLD | GG_FONT_ITALIC | GG_FONT_UNDERLINE | GG_FONT_COLOR);
--
-- format_idx += 3;
--
-- if ((attr & (GG_FONT_BOLD | GG_FONT_ITALIC | GG_FONT_UNDERLINE | GG_FONT_COLOR)) != 0 || (attr == 0 && old_attr != 0)) {
-- if (char_pos != 0) {
-- if ((old_attr & GG_FONT_UNDERLINE) != 0)
-- gg_append(dst, &len, "</u>", 4);
--
-- if ((old_attr & GG_FONT_ITALIC) != 0)
-- gg_append(dst, &len, "</i>", 4);
--
-- if ((old_attr & GG_FONT_BOLD) != 0)
-- gg_append(dst, &len, "</b>", 4);
--
-- if (src[i] != 0)
-- gg_append(dst, &len, "</span>", 7);
-- }
--
-- if (((attr & GG_FONT_COLOR) != 0) && (format_idx + 3 <= format_len)) {
-- color = &format_[format_idx];
-- format_idx += 3;
-- } else {
-- color = (unsigned char*) "\x00\x00\x00";
-- }
--
-- if (src[i] != 0) {
-- if (dst != NULL)
-- sprintf(&dst[len], span_fmt, color[0], color[1], color[2]);
-- len += span_len;
-- }
-- } else if (char_pos == 0 && src[0] != 0) {
-- if (dst != NULL)
-- sprintf(&dst[len], span_fmt, 0, 0, 0);
-- len += span_len;
-- }
--
-- if ((attr & GG_FONT_BOLD) != 0)
-- gg_append(dst, &len, "<b>", 3);
--
-- if ((attr & GG_FONT_ITALIC) != 0)
-- gg_append(dst, &len, "<i>", 3);
--
-- if ((attr & GG_FONT_UNDERLINE) != 0)
-- gg_append(dst, &len, "<u>", 3);
--
-- if (((attr & GG_FONT_IMAGE) != 0) && (format_idx + 10 <= format_len)) {
-- if (dst != NULL) {
-- sprintf(&dst[len], img_fmt,
-- format_[format_idx + 9],
-- format_[format_idx + 8],
-- format_[format_idx + 7],
-- format_[format_idx + 6],
-- format_[format_idx + 5],
-- format_[format_idx + 4],
-- format_[format_idx + 3],
-- format_[format_idx + 2]);
-- }
--
-- len += img_len;
-- format_idx += 10;
-- }
--
-- old_attr = attr;
-- }
--
-- /* Doklej znak zachowujÄ…c htmlowe escapowanie. */
--
-- switch (src[i]) {
-- case '&':
-- gg_append(dst, &len, "&amp;", 5);
-- break;
-- case '<':
-- gg_append(dst, &len, "&lt;", 4);
-- break;
-- case '>':
-- gg_append(dst, &len, "&gt;", 4);
-- break;
-- case '\'':
-- gg_append(dst, &len, "&apos;", 6);
-- break;
-- case '\"':
-- gg_append(dst, &len, "&quot;", 6);
-- break;
-- case '\n':
-- gg_append(dst, &len, "<br>", 4);
-- break;
-- case '\r':
-- case 0:
-- break;
-- default:
-- if (dst != NULL)
-- dst[len] = src[i];
-- len++;
-- }
--
-- /* Sprawdź, czy bajt nie jest kontynuacją znaku unikodowego. */
--
-- if ((src[i] & 0xc0) != 0xc0)
-- char_pos++;
--
-- if (src[i] == 0)
-- break;
-- }
--
-- /* Zamknij tagi. */
--
-- if ((old_attr & GG_FONT_UNDERLINE) != 0)
-- gg_append(dst, &len, "</u>", 4);
--
-- if ((old_attr & GG_FONT_ITALIC) != 0)
-- gg_append(dst, &len, "</i>", 4);
--
-- if ((old_attr & GG_FONT_BOLD) != 0)
-- gg_append(dst, &len, "</b>", 4);
--
-- if (src[0] != 0)
-- gg_append(dst, &len, "</span>", 7);
--
-- if (dst != NULL)
-- dst[len] = 0;
--
-- return len;
--}
--
--/**
-- * \internal Zamienia tekst w formacie HTML na czysty tekst.
-- *
-- * \param dst Bufor wynikowy (może być \c NULL)
-- * \param html Tekst źródłowy
-- *
-- * \note Dokleja \c \\0 na końcu bufora wynikowego.
-- *
-- * \note Funkcja służy do zachowania kompatybilności przy przesyłaniu
-- * wiadomości HTML do klientów, które tego formatu nie obsługują. Z tego
-- * powodu funkcja nie zachowuje formatowania, a jedynie usuwa tagi i
-- * zamienia podstawowe encje na ich odpowiedniki ASCII.
-- *
-- * \return Długość tekstu wynikowego bez \c \\0 (nawet jeśli \c dst to \c NULL).
-- */
--size_t gg_message_html_to_text(char *dst, const char *html)
--{
-- const char *src, *entity, *tag;
-- int in_tag, in_entity;
-- size_t len;
--
-- len = 0;
-- in_tag = 0;
-- tag = NULL;
-- in_entity = 0;
-- entity = NULL;
--
-- for (src = html; *src != 0; src++) {
-- if (in_entity && !(isalnum(*src) || *src == '#' || *src == ';')) {
-- in_entity = 0;
-- gg_append(dst, &len, entity, src - entity);
-- }
--
-- if (*src == '<') {
-- tag = src;
-- in_tag = 1;
-- continue;
-- }
--
-- if (in_tag && (*src == '>')) {
-- if (strncmp(tag, "<br", 3) == 0) {
-- if (dst != NULL)
-- dst[len] = '\n';
-- len++;
-- }
-- in_tag = 0;
-- continue;
-- }
--
-- if (in_tag)
-- continue;
--
-- if (*src == '&') {
-- in_entity = 1;
-- entity = src;
-- continue;
-- }
--
-- if (in_entity && *src == ';') {
-- in_entity = 0;
-- if (dst != NULL) {
-- if (strncmp(entity, "&lt;", 4) == 0)
-- dst[len++] = '<';
-- else if (strncmp(entity, "&gt;", 4) == 0)
-- dst[len++] = '>';
-- else if (strncmp(entity, "&quot;", 6) == 0)
-- dst[len++] = '"';
-- else if (strncmp(entity, "&apos;", 6) == 0)
-- dst[len++] = '\'';
-- else if (strncmp(entity, "&amp;", 5) == 0)
-- dst[len++] = '&';
-- else if (strncmp(entity, "&nbsp;", 6) == 0) {
-- dst[len++] = 0xc2;
-- dst[len++] = 0xa0;
-- } else
-- dst[len++] = '?';
-- } else {
-- if (strncmp(entity, "&nbsp;", 6) == 0)
-- len += 2;
-- else
-- len++;
-- }
--
-- continue;
-- }
--
-- if (in_entity && !(isalnum(*src) || *src == '#'))
-- in_entity = 0;
--
-- if (in_entity)
-- continue;
--
-- if (dst != NULL)
-- dst[len] = *src;
--
-- len++;
-- }
--
-- if (dst != NULL)
-- dst[len] = 0;
--
-- return len;
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/message.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/message.h
---- pidgin-2.10.7/libpurple/protocols/gg/lib/message.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/message.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,56 +0,0 @@
--/*
-- * (C) Copyright 2009 Wojtek Kaniewski <wojtekka@irc.pl>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--#ifndef LIBGADU_MESSAGE_H
--#define LIBGADU_MESSAGE_H
--
--#include <sys/types.h>
--#include <inttypes.h>
--#include "libgadu.h"
--
--#if 0
--
--struct gg_message {
-- uin_t *recipients;
-- size_t recipient_count;
-- char *text;
-- char *html;
-- char *attributes;
-- size_t attributes_length;
-- uint32_t msgclass;
-- uint32_t seq;
--
-- int auto_convert;
-- char *text_converted;
-- char *html_converted;
--};
--
--#define GG_MESSAGE_CHECK(gm, result) \
-- if ((gm) == NULL) { \
-- errno = EINVAL; \
-- return (result); \
-- }
--
--int gg_message_init(gg_message_t *gm, int msgclass, int seq, uin_t *recipients, size_t recipient_count, char *text, char *xhtml, char *attributes, size_t attributes_length, int auto_convert);
--
--#endif
--
--size_t gg_message_html_to_text(char *dst, const char *html);
--size_t gg_message_text_to_html(char *dst, const char *utf_msg, const char *format, size_t format_len);
--
--#endif /* LIBGADU_MESSAGE_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/obsolete.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/obsolete.c
---- pidgin-2.10.7/libpurple/protocols/gg/lib/obsolete.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/obsolete.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,237 +0,0 @@
--/* $Id: obsolete.c 1082 2011-04-08 17:50:14Z wojtekka $ */
--
--/*
-- * (C) Copyright 2001-2003 Wojtek Kaniewski <wojtekka@irc.pl>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--/**
-- * \file obsolete.c
-- *
-- * \brief Nieaktualne funkcje
-- *
-- * Plik zawiera definicje funkcji, które są już nieaktualne ze względu
-- * na zmiany w protokole. Programy konsolidowane ze starszych wersjami
-- * bibliotek powinny nadal mieć możliwość działania, mimo ograniczonej
-- * funkcjonalności.
-- */
--
--/** \cond obsolete */
--
--#include <errno.h>
--
--#include "libgadu.h"
--#include "libgadu-internal.h"
--
--struct gg_http *gg_userlist_get(uin_t uin, const char *passwd, int async)
--{
-- gg_debug(GG_DEBUG_MISC, "// gg_userlist_get() is obsolete. use gg_userlist_request() instead!\n");
-- errno = EINVAL;
-- return NULL;
--}
--
--int gg_userlist_get_watch_fd(struct gg_http *h)
--{
-- errno = EINVAL;
-- return -1;
--}
--
--void gg_userlist_get_free(struct gg_http *h)
--{
--
--}
--
--struct gg_http *gg_userlist_put(uin_t uin, const char *password, const char *contacts, int async)
--{
-- gg_debug(GG_DEBUG_MISC, "// gg_userlist_put() is obsolete. use gg_userlist_request() instead!\n");
-- errno = EINVAL;
-- return NULL;
--}
--
--int gg_userlist_put_watch_fd(struct gg_http *h)
--{
-- errno = EINVAL;
-- return -1;
--}
--
--void gg_userlist_put_free(struct gg_http *h)
--{
--
--}
--
--struct gg_http *gg_userlist_remove(uin_t uin, const char *passwd, int async)
--{
-- gg_debug(GG_DEBUG_MISC, "// gg_userlist_remove() is obsolete. use gg_userlist_request() instead!\n");
-- errno = EINVAL;
-- return NULL;
--}
--
--int gg_userlist_remove_watch_fd(struct gg_http *h)
--{
-- errno = EINVAL;
-- return -1;
--}
--
--void gg_userlist_remove_free(struct gg_http *h)
--{
--
--}
--
--struct gg_http *gg_search(const struct gg_search_request *r, int async)
--{
-- gg_debug(GG_DEBUG_MISC, "// gg_search() is obsolete. use gg_search50() instead!\n");
-- errno = EINVAL;
-- return NULL;
--}
--
--int gg_search_watch_fd(struct gg_http *h)
--{
-- errno = EINVAL;
-- return -1;
--}
--
--void gg_search_free(struct gg_http *h)
--{
--
--}
--
--const struct gg_search_request *gg_search_request_mode_0(char *nickname, char *first_name, char *last_name, char *city, int gender, int min_birth, int max_birth, int active, int start)
--{
-- return NULL;
--}
--
--const struct gg_search_request *gg_search_request_mode_1(char *email, int active, int start)
--{
-- return NULL;
--}
--
--const struct gg_search_request *gg_search_request_mode_2(char *phone, int active, int start)
--{
-- return NULL;
--}
--
--const struct gg_search_request *gg_search_request_mode_3(uin_t uin, int active, int start)
--{
-- return NULL;
--}
--
--void gg_search_request_free(struct gg_search_request *r)
--{
--
--}
--
--struct gg_http *gg_register(const char *email, const char *password, int async)
--{
-- gg_debug(GG_DEBUG_MISC, "// gg_register() is obsolete. use gg_register3() instead!\n");
-- errno = EINVAL;
-- return NULL;
--}
--
--struct gg_http *gg_register2(const char *email, const char *password, const char *qa, int async)
--{
-- gg_debug(GG_DEBUG_MISC, "// gg_register2() is obsolete. use gg_register3() instead!\n");
-- errno = EINVAL;
-- return NULL;
--}
--
--struct gg_http *gg_unregister(uin_t uin, const char *password, const char *email, int async)
--{
-- gg_debug(GG_DEBUG_MISC, "// gg_unregister() is obsolete. use gg_unregister3() instead!\n");
-- errno = EINVAL;
-- return NULL;
--}
--
--struct gg_http *gg_unregister2(uin_t uin, const char *password, const char *qa, int async)
--{
-- gg_debug(GG_DEBUG_MISC, "// gg_unregister2() is obsolete. use gg_unregister3() instead!\n");
-- errno = EINVAL;
-- return NULL;
--}
--
--
--struct gg_http *gg_change_passwd(uin_t uin, const char *passwd, const char *newpasswd, const char *newemail, int async)
--{
-- gg_debug(GG_DEBUG_MISC, "// gg_change_passwd() is obsolete. use gg_change_passwd4() instead!\n");
-- errno = EINVAL;
-- return NULL;
--}
--
--struct gg_http *gg_change_passwd2(uin_t uin, const char *passwd, const char *newpasswd, const char *email, const char *newemail, int async)
--{
-- gg_debug(GG_DEBUG_MISC, "// gg_change_passwd2() is obsolete. use gg_change_passwd4() instead!\n");
-- errno = EINVAL;
-- return NULL;
--}
--
--struct gg_http *gg_change_passwd3(uin_t uin, const char *passwd, const char *newpasswd, const char *qa, int async)
--{
-- gg_debug(GG_DEBUG_MISC, "// gg_change_passwd3() is obsolete. use gg_change_passwd4() instead!\n");
-- errno = EINVAL;
-- return NULL;
--}
--
--struct gg_http *gg_remind_passwd(uin_t uin, int async)
--{
-- gg_debug(GG_DEBUG_MISC, "// gg_remind_passwd() is obsolete. use gg_remind_passwd3() instead!\n");
-- errno = EINVAL;
-- return NULL;
--}
--
--struct gg_http *gg_remind_passwd2(uin_t uin, const char *tokenid, const char *tokenval, int async)
--{
-- gg_debug(GG_DEBUG_MISC, "// gg_remind_passwd2() is obsolete. use gg_remind_passwd3() instead!\n");
-- errno = EINVAL;
-- return NULL;
--}
--
--struct gg_http *gg_change_info(uin_t uin, const char *passwd, const struct gg_change_info_request *request, int async)
--{
-- gg_debug(GG_DEBUG_MISC, "// gg_change_info() is obsolete. use gg_pubdir50() instead\n");
-- errno = EINVAL;
-- return NULL;
--}
--
--struct gg_change_info_request *gg_change_info_request_new(const char *first_name, const char *last_name, const char *nickname, const char *email, int born, int gender, const char *city)
--{
-- return NULL;
--}
--
--void gg_change_info_request_free(struct gg_change_info_request *r)
--{
--
--}
--
--int gg_resolve(int *fd, int *pid, const char *hostname)
--{
-- return -1;
--}
--
--void gg_resolve_pthread_cleanup(void *arg, int kill)
--{
--
--}
--
--int gg_resolve_pthread(int *fd, void **resolver, const char *hostname)
--{
-- return -1;
--}
--
--int gg_pubdir50_handle_reply(struct gg_event *e, const char *packet, int length)
--{
-- return -1;
--}
--
--/** \endcond */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/protocol.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/protocol.h
---- pidgin-2.10.7/libpurple/protocols/gg/lib/protocol.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/protocol.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,326 +0,0 @@
--/* $Id$ */
--
--/*
-- * (C) Copyright 2009-2010 Jakub Zawadzki <darkjames@darkjames.ath.cx>
-- * Bartłomiej Zimoń <uzi18@o2.pl>
-- * Wojtek Kaniewski <wojtekka@irc.pl>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--#ifndef LIBGADU_PROTOCOL_H
--#define LIBGADU_PROTOCOL_H
--
--#include "libgadu.h"
--
--#ifdef _WIN32
--#pragma pack(push, 1)
--#endif
--
--#define GG_LOGIN80BETA 0x0029
--
--#define GG_LOGIN80 0x0031
--
--#undef GG_FEATURE_STATUS80BETA
--#undef GG_FEATURE_MSG80
--#undef GG_FEATURE_STATUS80
--#define GG_FEATURE_STATUS80BETA 0x01
--#define GG_FEATURE_MSG80 0x02
--#define GG_FEATURE_STATUS80 0x05
--
--#define GG8_LANG "pl"
--#define GG8_VERSION "Gadu-Gadu Client Build "
--
--struct gg_login80 {
-- uint32_t uin; /* mój numerek */
-- uint8_t language[2]; /* język: GG8_LANG */
-- uint8_t hash_type; /* rodzaj hashowania hasła */
-- uint8_t hash[64]; /* hash hasła dopełniony zerami */
-- uint32_t status; /* status na dzień dobry */
-- uint32_t flags; /* flagi (przeznaczenie nieznane) */
-- uint32_t features; /* opcje protokołu (GG8_FEATURES) */
-- uint32_t local_ip; /* mój adres ip */
-- uint16_t local_port; /* port, na którym słucham */
-- uint32_t external_ip; /* zewnętrzny adres ip (???) */
-- uint16_t external_port; /* zewnętrzny port (???) */
-- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
-- uint8_t dunno2; /* 0x64 */
--} GG_PACKED;
--
--#define GG_LOGIN_HASH_TYPE_INVALID 0x0016
--
--#define GG_LOGIN80_OK 0x0035
--
--/**
-- * Logowanie powiodło się (pakiet \c GG_LOGIN80_OK)
-- */
--struct gg_login80_ok {
-- uint32_t unknown1; /* 0x00000001 */
--} GG_PACKED;
--
--/**
-- * Logowanie nie powiodło się (pakiet \c GG_LOGIN80_FAILED)
-- */
--#define GG_LOGIN80_FAILED 0x0043
--
--struct gg_login80_failed {
-- uint32_t unknown1; /* 0x00000001 */
--} GG_PACKED;
--
--#define GG_NEW_STATUS80BETA 0x0028
--
--#define GG_NEW_STATUS80 0x0038
--
--/**
-- * Zmiana stanu (pakiet \c GG_NEW_STATUS80)
-- */
--struct gg_new_status80 {
-- uint32_t status; /**< Nowy status */
-- uint32_t flags; /**< flagi (nieznane przeznaczenie) */
-- uint32_t description_size; /**< rozmiar opisu */
--} GG_PACKED;
--
--#define GG_STATUS80BETA 0x002a
--#define GG_NOTIFY_REPLY80BETA 0x002b
--
--#define GG_STATUS80 0x0036
--#define GG_NOTIFY_REPLY80 0x0037
--
--struct gg_notify_reply80 {
-- uint32_t uin; /* numerek plus flagi w najstarszym bajcie */
-- uint32_t status; /* status danej osoby */
-- uint32_t features; /* opcje protokołu */
-- uint32_t remote_ip; /* adres IP bezpośrednich połączeń */
-- uint16_t remote_port; /* port bezpośrednich połączeń */
-- uint8_t image_size; /* maksymalny rozmiar obrazków w KB */
-- uint8_t unknown1; /* 0x00 */
-- uint32_t flags; /* flagi połączenia */
-- uint32_t descr_len; /* rozmiar opisu */
--} GG_PACKED;
--
--#define GG_SEND_MSG80 0x002d
--
--struct gg_send_msg80 {
-- uint32_t recipient;
-- uint32_t seq;
-- uint32_t msgclass;
-- uint32_t offset_plain;
-- uint32_t offset_attr;
--} GG_PACKED;
--
--#define GG_RECV_MSG80 0x002e
--
--struct gg_recv_msg80 {
-- uint32_t sender;
-- uint32_t seq;
-- uint32_t time;
-- uint32_t msgclass;
-- uint32_t offset_plain;
-- uint32_t offset_attr;
--} GG_PACKED;
--
--#define GG_DISCONNECT_ACK 0x000d
--
--#define GG_RECV_MSG_ACK 0x0046
--
--struct gg_recv_msg_ack {
-- uint32_t seq;
--} GG_PACKED;
--
--#define GG_USER_DATA 0x0044
--
--struct gg_user_data {
-- uint32_t type;
-- uint32_t user_count;
--} GG_PACKED;
--
--struct gg_user_data_user {
-- uint32_t uin;
-- uint32_t attr_count;
--} GG_PACKED;
--
--#define GG_TYPING_NOTIFICATION 0x0059
--
--struct gg_typing_notification {
-- uint16_t length;
-- uint32_t uin;
--} GG_PACKED;
--
--#define GG_XML_ACTION 0x002c
--
--#define GG_RECV_OWN_MSG 0x005a
--
--#define GG_MULTILOGON_INFO 0x005b
--
--struct gg_multilogon_info {
-- uint32_t count;
--} GG_PACKED;
--
--struct gg_multilogon_info_item {
-- uint32_t addr;
-- uint32_t flags;
-- uint32_t features;
-- uint32_t logon_time;
-- gg_multilogon_id_t conn_id;
-- uint32_t unknown1;
-- uint32_t name_size;
--} GG_PACKED;
--
--#define GG_MULTILOGON_DISCONNECT 0x0062
--
--struct gg_multilogon_disconnect {
-- gg_multilogon_id_t conn_id;
--} GG_PACKED;
--
--#define GG_MSG_CALLBACK 0x02 /**< Żądanie zwrotnego połączenia bezpośredniego */
--
--#define GG_MSG_OPTION_CONFERENCE 0x01
--#define GG_MSG_OPTION_ATTRIBUTES 0x02
--#define GG_MSG_OPTION_IMAGE_REQUEST 0x04
--#define GG_MSG_OPTION_IMAGE_REPLY 0x05
--#define GG_MSG_OPTION_IMAGE_REPLY_MORE 0x06
--
--#define GG_DCC7_ABORT 0x0025
--
--struct gg_dcc7_abort {
-- gg_dcc7_id_t id; /* identyfikator połączenia */
-- uint32_t uin_from; /* numer nadawcy */
-- uint32_t uin_to; /* numer odbiorcy */
--} GG_PACKED;
--
--#define GG_DCC7_ABORTED 0x0025
--
--struct gg_dcc7_aborted {
-- gg_dcc7_id_t id; /* identyfikator połączenia */
--} GG_PACKED;
--
--#define GG_DCC7_VOICE_RETRIES 0x11 /* 17 powtorzen */
--
--#define GG_DCC7_RESERVED1 0xdeadc0de
--#define GG_DCC7_RESERVED2 0xdeadbeaf
--
--struct gg_dcc7_voice_auth {
-- uint8_t type; /* 0x00 -> wysylanie ID
-- 0x01 -> potwierdzenie ID
-- */
-- gg_dcc7_id_t id; /* identyfikator połączenia */
-- uint32_t reserved1; /* GG_DCC7_RESERVED1 */
-- uint32_t reserved2; /* GG_DCC7_RESERVED2 */
--} GG_PACKED;
--
--struct gg_dcc7_voice_nodata { /* wyciszony mikrofon, ten pakiet jest wysylany co 1s (jesli chcemy podtrzymac polaczenie) */
-- uint8_t type; /* 0x02 */
-- gg_dcc7_id_t id; /* identyfikator połączenia */
-- uint32_t reserved1; /* GG_DCC7_RESERVED1 */
-- uint32_t reserved2; /* GG_DCC7_RESERVED2 */
--} GG_PACKED;
--
--struct gg_dcc7_voice_data {
-- uint8_t type; /* 0x03 */
-- uint32_t did; /* XXX: co ile zwieksza sie u nas id pakietu [uzywac 0x28] */
-- uint32_t len; /* rozmiar strukturki - 1 (sizeof(type)) */
-- uint32_t packet_id; /* numerek pakietu */
-- uint32_t datalen; /* rozmiar danych */
-- /* char data[]; */ /* ramki: albo gsm, albo speex, albo melp, albo inne. */
--} GG_PACKED;
--
--struct gg_dcc7_voice_init {
-- uint8_t type; /* 0x04 */
-- uint32_t id; /* nr kroku [0x1 - 0x5] */
-- uint32_t protocol; /* XXX: wersja protokolu (0x29, 0x2a, 0x2b) */
-- uint32_t len; /* rozmiar sizeof(protocol)+sizeof(len)+sizeof(data) = 0x08 + sizeof(data) */
-- /* char data[]; */ /* reszta danych */
--} GG_PACKED;
--
--struct gg_dcc7_voice_init_confirm {
-- uint8_t type; /* 0x05 */
-- uint32_t id; /* id tego co potwierdzamy [0x1 - 0x5] */
--} GG_PACKED;
--
--#define GG_DCC7_RELAY_TYPE_SERVER 0x01 /* adres serwera, na który spytać o proxy */
--#define GG_DCC7_RELAY_TYPE_PROXY 0x08 /* adresy proxy, na które sie łączyć */
--
--#define GG_DCC7_RELAY_DUNNO1 0x02
--
--#define GG_DCC7_RELAY_REQUEST 0x0a
--
--struct gg_dcc7_relay_req {
-- uint32_t magic; /* 0x0a */
-- uint32_t len; /* długość całego pakietu */
-- gg_dcc7_id_t id; /* identyfikator połączenia */
-- uint16_t type; /* typ zapytania */
-- uint16_t dunno1; /* 0x02 */
--} GG_PACKED;
--
--#define GG_DCC7_RELAY_REPLY_RCOUNT 0x02
--
--#define GG_DCC7_RELAY_REPLY 0x0b
--
--struct gg_dcc7_relay_reply {
-- uint32_t magic; /* 0x0b */
-- uint32_t len; /* długość całego pakietu */
-- uint32_t rcount; /* ilość serwerów */
--} GG_PACKED;
--
--struct gg_dcc7_relay_reply_server {
-- uint32_t addr; /* adres ip serwera */
-- uint16_t port; /* port serwera */
-- uint8_t family; /* rodzina adresów (na końcu?!) AF_INET=2 */
--} GG_PACKED;
--
--#define GG_DCC7_WELCOME_SERVER 0xc0debabe
--
--struct gg_dcc7_welcome_server {
-- uint32_t magic; /* 0xc0debabe */
-- gg_dcc7_id_t id; /* identyfikator połączenia */
--} GG_PACKED;
--
--struct gg_dcc7_welcome_p2p {
-- gg_dcc7_id_t id; /* identyfikator połączenia */
--} GG_PACKED;
--
--#define GG_TIMEOUT_DISCONNECT 5 /**< Maksymalny czas oczekiwania na rozłączenie */
--
--#define GG_USERLIST100_VERSION 0x5c
--
--struct gg_userlist100_version {
-- uint32_t version; /* numer wersji listy kontaktów */
--} GG_PACKED;
--
--#define GG_USERLIST100_REQUEST 0x0040
--
--struct gg_userlist100_request {
-- uint8_t type; /* rodzaj żądania */
-- uint32_t version; /* numer ostatniej znanej wersji listy kontaktów bądź 0 */
-- uint8_t format_type; /* rodzaj żądanego typu formatu listy kontaktów */
-- uint8_t unknown1; /* 0x01 */
-- /* char request[]; */
--} GG_PACKED;
--
--#define GG_USERLIST100_REPLY 0x41
--
--struct gg_userlist100_reply {
-- uint8_t type; /* rodzaj odpowiedzi */
-- uint32_t version; /* numer wersji listy kontaktów aktualnie przechowywanej przez serwer */
-- uint8_t format_type; /* rodzaj przesyłanego typu formatu listy kontaktów */
-- uint8_t unknown1; /* 0x01 */
-- /* char reply[]; */
--} GG_PACKED;
--
--#ifdef _WIN32
--#pragma pack(pop)
--#endif
--
--#endif /* LIBGADU_PROTOCOL_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/pubdir50.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/pubdir50.c
---- pidgin-2.10.7/libpurple/protocols/gg/lib/pubdir50.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/pubdir50.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,554 +0,0 @@
--/*
-- * (C) Copyright 2003 Wojtek Kaniewski <wojtekka@irc.pl>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--/**
-- * \file pubdir50.c
-- *
-- * \brief Obsługa katalogu publicznego od wersji Gadu-Gadu 5.x
-- *
-- * \todo Zoptymalizować konwersję CP1250<->UTF8. Obecnie robiona jest
-- * testowa konwersja, żeby poznać długość tekstu wynikowego.
-- */
--
--#include <errno.h>
--#include <stdlib.h>
--#include <string.h>
--#include <time.h>
--
--#include "libgadu.h"
--#include "libgadu-config.h"
--#include "libgadu-internal.h"
--#include "encoding.h"
--
--/**
-- * Tworzy nowe zapytanie katalogu publicznego.
-- *
-- * \param type Rodzaj zapytania
-- *
-- * \return Zmienna \c gg_pubdir50_t lub \c NULL w przypadku błędu.
-- *
-- * \ingroup pubdir50
-- */
--gg_pubdir50_t gg_pubdir50_new(int type)
--{
-- gg_pubdir50_t res = malloc(sizeof(struct gg_pubdir50_s));
--
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_new(%d);\n", type);
--
-- if (!res) {
-- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_new() out of memory\n");
-- return NULL;
-- }
--
-- memset(res, 0, sizeof(struct gg_pubdir50_s));
--
-- res->type = type;
--
-- return res;
--}
--
--/**
-- * \internal Dodaje lub zastępuje pole zapytania lub odpowiedzi katalogu
-- * publicznego.
-- *
-- * \param req Zapytanie lub odpowiedź
-- * \param num Numer wyniku odpowiedzi (0 dla zapytania)
-- * \param field Nazwa pola
-- * \param value Wartość pola
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--static int gg_pubdir50_add_n(gg_pubdir50_t req, int num, const char *field, const char *value)
--{
-- struct gg_pubdir50_entry *tmp = NULL, *entry;
-- char *dupfield, *dupvalue;
-- int i;
--
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_add_n(%p, %d, \"%s\", \"%s\");\n", req, num, field, value);
--
-- if (!(dupvalue = strdup(value))) {
-- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_add_n() out of memory\n");
-- return -1;
-- }
--
-- for (i = 0; i < req->entries_count; i++) {
-- if (req->entries[i].num != num || strcmp(req->entries[i].field, field))
-- continue;
--
-- free(req->entries[i].value);
-- req->entries[i].value = dupvalue;
--
-- return 0;
-- }
--
-- if (!(dupfield = strdup(field))) {
-- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_add_n() out of memory\n");
-- free(dupvalue);
-- return -1;
-- }
--
-- if (!(tmp = realloc(req->entries, sizeof(struct gg_pubdir50_entry) * (req->entries_count + 1)))) {
-- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_add_n() out of memory\n");
-- free(dupfield);
-- free(dupvalue);
-- return -1;
-- }
--
-- req->entries = tmp;
--
-- entry = &req->entries[req->entries_count];
-- entry->num = num;
-- entry->field = dupfield;
-- entry->value = dupvalue;
--
-- req->entries_count++;
--
-- return 0;
--}
--
--/**
-- * Dodaje pole zapytania.
-- *
-- * \param req Zapytanie
-- * \param field Nazwa pola
-- * \param value Wartość pola
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup pubdir50
-- */
--int gg_pubdir50_add(gg_pubdir50_t req, const char *field, const char *value)
--{
-- return gg_pubdir50_add_n(req, 0, field, value);
--}
--
--/**
-- * Ustawia numer sekwencyjny zapytania.
-- *
-- * \param req Zapytanie
-- * \param seq Numer sekwencyjny
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup pubdir50
-- */
--int gg_pubdir50_seq_set(gg_pubdir50_t req, uint32_t seq)
--{
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_seq_set(%p, %d);\n", req, seq);
--
-- if (!req) {
-- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_seq_set() invalid arguments\n");
-- errno = EFAULT;
-- return -1;
-- }
--
-- req->seq = seq;
--
-- return 0;
--}
--
--/**
-- * Zwalnia zasoby po zapytaniu lub odpowiedzi katalogu publicznego.
-- *
-- * \param s Zapytanie lub odpowiedź
-- *
-- * \ingroup pubdir50
-- */
--void gg_pubdir50_free(gg_pubdir50_t s)
--{
-- int i;
--
-- if (!s)
-- return;
--
-- for (i = 0; i < s->entries_count; i++) {
-- free(s->entries[i].field);
-- free(s->entries[i].value);
-- }
--
-- free(s->entries);
-- free(s);
--}
--
--/**
-- * Wysyła zapytanie katalogu publicznego do serwera.
-- *
-- * \param sess Struktura sesji
-- * \param req Zapytanie
-- *
-- * \return Numer sekwencyjny zapytania lub 0 w przypadku błędu
-- *
-- * \ingroup pubdir50
-- */
--uint32_t gg_pubdir50(struct gg_session *sess, gg_pubdir50_t req)
--{
-- int i, size = 5;
-- uint32_t res;
-- char *buf, *p;
-- struct gg_pubdir50_request *r;
--
-- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_pubdir50(%p, %p);\n", sess, req);
--
-- if (!sess || !req) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_pubdir50() invalid arguments\n");
-- errno = EFAULT;
-- return 0;
-- }
--
-- if (sess->state != GG_STATE_CONNECTED) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_pubdir50() not connected\n");
-- errno = ENOTCONN;
-- return 0;
-- }
--
-- for (i = 0; i < req->entries_count; i++) {
-- /* wyszukiwanie bierze tylko pierwszy wpis */
-- if (req->entries[i].num)
-- continue;
--
-- if (sess->encoding == GG_ENCODING_CP1250) {
-- size += strlen(req->entries[i].field) + 1;
-- size += strlen(req->entries[i].value) + 1;
-- } else {
-- char *tmp;
--
-- // XXX \todo zoptymalizować
-- tmp = gg_encoding_convert(req->entries[i].field, sess->encoding, GG_ENCODING_CP1250, -1, -1);
--
-- if (tmp == NULL)
-- return -1;
--
-- size += strlen(tmp) + 1;
--
-- free(tmp);
--
-- // XXX \todo zoptymalizować
-- tmp = gg_encoding_convert(req->entries[i].value, sess->encoding, GG_ENCODING_CP1250, -1, -1);
--
-- if (tmp == NULL)
-- return -1;
--
-- size += strlen(tmp) + 1;
--
-- free(tmp);
-- }
-- }
--
-- if (!(buf = malloc(size))) {
-- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_pubdir50() out of memory (%d bytes)\n", size);
-- return 0;
-- }
--
-- if (!req->seq)
-- req->seq = time(NULL);
--
-- res = req->seq;
--
-- r = (struct gg_pubdir50_request*) buf;
-- r->type = req->type;
-- r->seq = gg_fix32(req->seq);
--
-- for (i = 0, p = buf + 5; i < req->entries_count; i++) {
-- if (req->entries[i].num)
-- continue;
--
-- if (sess->encoding == GG_ENCODING_CP1250) {
-- strcpy(p, req->entries[i].field);
-- p += strlen(p) + 1;
--
-- strcpy(p, req->entries[i].value);
-- p += strlen(p) + 1;
-- } else {
-- char *tmp;
--
-- // XXX \todo zoptymalizować
-- tmp = gg_encoding_convert(req->entries[i].field, sess->encoding, GG_ENCODING_CP1250, -1, -1);
--
-- if (tmp == NULL) {
-- free(buf);
-- return -1;
-- }
--
-- strcpy(p, tmp);
-- p += strlen(tmp) + 1;
-- free(tmp);
--
-- // XXX \todo zoptymalizować
-- tmp = gg_encoding_convert(req->entries[i].value, sess->encoding, GG_ENCODING_CP1250, -1, -1);
--
--
-- if (tmp == NULL) {
-- free(buf);
-- return -1;
-- }
--
-- strcpy(p, tmp);
-- p += strlen(tmp) + 1;
-- free(tmp);
-- }
-- }
--
-- if (gg_send_packet(sess, GG_PUBDIR50_REQUEST, buf, size, NULL, 0) == -1)
-- res = 0;
--
-- free(buf);
--
-- return res;
--}
--
--/*
-- * \internal Analizuje przychodzÄ…cy pakiet odpowiedzi i zapisuje wynik
-- * w strukturze \c gg_event.
-- *
-- * \param sess Struktura sesji
-- * \param e Struktura zdarzenia
-- * \param packet Pakiet odpowiedzi
-- * \param length Długość pakietu odpowiedzi
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--int gg_pubdir50_handle_reply_sess(struct gg_session *sess, struct gg_event *e, const char *packet, int length)
--{
-- const char *end = packet + length, *p;
-- struct gg_pubdir50_reply *r = (struct gg_pubdir50_reply*) packet;
-- gg_pubdir50_t res;
-- int num = 0;
--
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_handle_reply_sess(%p, %p, %p, %d);\n", sess, e, packet, length);
--
-- if (!sess || !e || !packet) {
-- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() invalid arguments\n");
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (length < 5) {
-- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() packet too short\n");
-- errno = EINVAL;
-- return -1;
-- }
--
-- if (!(res = gg_pubdir50_new(r->type))) {
-- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() unable to allocate reply\n");
-- return -1;
-- }
--
-- e->event.pubdir50 = res;
--
-- res->seq = gg_fix32(r->seq);
--
-- switch (res->type) {
-- case GG_PUBDIR50_READ:
-- e->type = GG_EVENT_PUBDIR50_READ;
-- break;
--
-- case GG_PUBDIR50_WRITE:
-- e->type = GG_EVENT_PUBDIR50_WRITE;
-- break;
--
-- default:
-- e->type = GG_EVENT_PUBDIR50_SEARCH_REPLY;
-- break;
-- }
--
-- /* brak wyników? */
-- if (length == 5)
-- return 0;
--
-- /* pomiń początek odpowiedzi */
-- p = packet + 5;
--
-- while (p < end) {
-- const char *field, *value;
--
-- field = p;
--
-- /* sprawdź, czy nie mamy podziału na kolejne pole */
-- if (!*field) {
-- num++;
-- field++;
-- }
--
-- value = NULL;
--
-- for (p = field; p < end; p++) {
-- /* jeśli mamy koniec tekstu... */
-- if (!*p) {
-- /* ...i jeszcze nie mieliśmy wartości pola to
-- * wiemy, że po tym zerze jest wartość... */
-- if (!value)
-- value = p + 1;
-- else
-- /* ...w przeciwym wypadku koniec
-- * wartości i możemy wychodzić
-- * grzecznie z pętli */
-- break;
-- }
-- }
--
-- /* sprawdźmy, czy pole nie wychodzi poza pakiet, żeby nie
-- * mieć segfaultów, jeśli serwer przestanie zakańczać pakietów
-- * przez \0 */
--
-- if (p == end) {
-- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() premature end of packet\n");
-- goto failure;
-- }
--
-- p++;
--
-- /* jeśli dostaliśmy namier na następne wyniki, to znaczy że
-- * mamy koniec wyników i nie jest to kolejna osoba. */
-- if (!strcasecmp(field, "nextstart")) {
-- res->next = atoi(value);
-- num--;
-- } else {
-- if (sess->encoding == GG_ENCODING_CP1250) {
-- if (gg_pubdir50_add_n(res, num, field, value) == -1)
-- goto failure;
-- } else {
-- char *tmp;
--
-- tmp = gg_encoding_convert(value, GG_ENCODING_CP1250, sess->encoding, -1, -1);
--
-- if (tmp == NULL)
-- goto failure;
--
-- if (gg_pubdir50_add_n(res, num, field, tmp) == -1) {
-- free(tmp);
-- goto failure;
-- }
--
-- free(tmp);
-- }
-- }
-- }
--
-- res->count = num + 1;
--
-- return 0;
--
--failure:
-- gg_pubdir50_free(res);
-- return -1;
--}
--
--/**
-- * Pobiera pole z odpowiedzi katalogu publicznego.
-- *
-- * \param res Odpowiedź
-- * \param num Numer wyniku odpowiedzi
-- * \param field Nazwa pola (wielkość liter nie ma znaczenia)
-- *
-- * \return Wartość pola lub \c NULL jeśli nie znaleziono
-- *
-- * \ingroup pubdir50
-- */
--const char *gg_pubdir50_get(gg_pubdir50_t res, int num, const char *field)
--{
-- char *value = NULL;
-- int i;
--
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_get(%p, %d, \"%s\");\n", res, num, field);
--
-- if (!res || num < 0 || !field) {
-- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_get() invalid arguments\n");
-- errno = EINVAL;
-- return NULL;
-- }
--
-- for (i = 0; i < res->entries_count; i++) {
-- if (res->entries[i].num == num && !strcasecmp(res->entries[i].field, field)) {
-- value = res->entries[i].value;
-- break;
-- }
-- }
--
-- return value;
--}
--
--/**
-- * Zwraca liczbę wyników odpowiedzi.
-- *
-- * \param res Odpowiedź
-- *
-- * \return Liczba wyników lub -1 w przypadku błędu
-- *
-- * \ingroup pubdir50
-- */
--int gg_pubdir50_count(gg_pubdir50_t res)
--{
-- return (!res) ? -1 : res->count;
--}
--
--/**
-- * Zwraca rodzaj zapytania lub odpowiedzi.
-- *
-- * \param res Zapytanie lub odpowiedź
-- *
-- * \return Rodzaj lub -1 w przypadku błędu
-- *
-- * \ingroup pubdir50
-- */
--int gg_pubdir50_type(gg_pubdir50_t res)
--{
-- return (!res) ? -1 : res->type;
--}
--
--/**
-- * Zwraca numer, od którego należy rozpocząc kolejne wyszukiwanie.
-- *
-- * Dłuższe odpowiedzi katalogu publicznego są wysyłane przez serwer
-- * w mniejszych paczkach. Po otrzymaniu odpowiedzi, jeśli numer kolejnego
-- * wyszukiwania jest większy od zera, dalsze wyniki można otrzymać przez
-- * wywołanie kolejnego zapytania z określonym numerem początkowym.
-- *
-- * \param res Odpowiedź
-- *
-- * \return Numer lub -1 w przypadku błędu
-- *
-- * \ingroup pubdir50
-- */
--uin_t gg_pubdir50_next(gg_pubdir50_t res)
--{
-- return (!res) ? (unsigned) -1 : res->next;
--}
--
--/**
-- * Zwraca numer sekwencyjny zapytania lub odpowiedzi.
-- *
-- * \param res Zapytanie lub odpowiedź
-- *
-- * \return Numer sekwencyjny lub -1 w przypadku błędu
-- *
-- * \ingroup pubdir50
-- */
--uint32_t gg_pubdir50_seq(gg_pubdir50_t res)
--{
-- return (!res) ? (unsigned) -1 : res->seq;
--}
--
--/*
-- * Local variables:
-- * c-indentation-style: k&r
-- * c-basic-offset: 8
-- * indent-tabs-mode: notnil
-- * End:
-- *
-- * vim: shiftwidth=8:
-- */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/pubdir.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/pubdir.c
---- pidgin-2.10.7/libpurple/protocols/gg/lib/pubdir.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/pubdir.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,857 +0,0 @@
--/* $Id: pubdir.c 502 2008-01-10 23:25:17Z wojtekka $ */
--
--/*
-- * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl>
-- * Dawid Jarosz <dawjar@poczta.onet.pl>
-- * Adam Wysocki <gophi@ekg.chmurka.net>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--/**
-- * \file pubdir.c
-- *
-- * \brief Obsługa katalogu publicznego
-- */
--
--#include <ctype.h>
--#include <errno.h>
--#include <stdarg.h>
--#include <stdio.h>
--#include <stdlib.h>
--#include <string.h>
--#include <unistd.h>
--
--#include "libgadu.h"
--#include "libgadu-config.h"
--
--/**
-- * Rejestruje nowego użytkownika.
-- *
-- * Wymaga wcześniejszego pobrania tokenu za pomocą \c gg_token().
-- *
-- * \param email Adres e-mail
-- * \param password Hasło
-- * \param tokenid Identyfikator tokenu
-- * \param tokenval Zawartość tokenu
-- * \param async Flaga połączenia asynchronicznego
-- *
-- * \return Struktura \c gg_http lub \c NULL w przypadku błędu
-- *
-- * \ingroup register
-- */
--struct gg_http *gg_register3(const char *email, const char *password, const char *tokenid, const char *tokenval, int async)
--{
-- struct gg_http *h;
-- char *__pwd, *__email, *__tokenid, *__tokenval, *form, *query;
--
-- if (!email || !password || !tokenid || !tokenval) {
-- gg_debug(GG_DEBUG_MISC, "=> register, NULL parameter\n");
-- errno = EFAULT;
-- return NULL;
-- }
--
-- __pwd = gg_urlencode(password);
-- __email = gg_urlencode(email);
-- __tokenid = gg_urlencode(tokenid);
-- __tokenval = gg_urlencode(tokenval);
--
-- if (!__pwd || !__email || !__tokenid || !__tokenval) {
-- gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for form fields\n");
-- free(__pwd);
-- free(__email);
-- free(__tokenid);
-- free(__tokenval);
-- return NULL;
-- }
--
-- form = gg_saprintf("pwd=%s&email=%s&tokenid=%s&tokenval=%s&code=%u",
-- __pwd, __email, __tokenid, __tokenval,
-- gg_http_hash("ss", email, password));
--
-- free(__pwd);
-- free(__email);
-- free(__tokenid);
-- free(__tokenval);
--
-- if (!form) {
-- gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for form query\n");
-- return NULL;
-- }
--
-- gg_debug(GG_DEBUG_MISC, "=> register, %s\n", form);
--
-- query = gg_saprintf(
-- "Host: " GG_REGISTER_HOST "\r\n"
-- "Content-Type: application/x-www-form-urlencoded\r\n"
-- "User-Agent: " GG_HTTP_USERAGENT "\r\n"
-- "Content-Length: %d\r\n"
-- "Pragma: no-cache\r\n"
-- "\r\n"
-- "%s",
-- (int) strlen(form), form);
--
-- free(form);
--
-- if (!query) {
-- gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for query\n");
-- return NULL;
-- }
--
-- if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/fmregister3.asp", query))) {
-- gg_debug(GG_DEBUG_MISC, "=> register, gg_http_connect() failed mysteriously\n");
-- free(query);
-- return NULL;
-- }
--
-- h->type = GG_SESSION_REGISTER;
--
-- free(query);
--
-- h->callback = gg_pubdir_watch_fd;
-- h->destroy = gg_pubdir_free;
--
-- if (!async)
-- gg_pubdir_watch_fd(h);
--
-- return h;
--}
--
--#ifdef DOXYGEN
--
--/**
-- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
-- *
-- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
-- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
-- * znajdzie siÄ™ w polu \c error.
-- *
-- * \note W rzeczywistości funkcja jest makrem rozwijanym do
-- * \c gg_pubdir_watch_fd().
-- *
-- * \param h Struktura połączenia
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup register
-- */
--int gg_register_watch_fd(struct gg_httpd *h)
--{
-- return gg_pubdir_watch_fd(h);
--}
--
--/**
-- * Zwalnia zasoby po operacji.
-- *
-- * \note W rzeczywistości funkcja jest makrem rozwijanym do \c gg_pubdir_free().
-- *
-- * \param h Struktura połączenia
-- *
-- * \ingroup register
-- */
--void gg_register_free(struct gg_http *h)
--{
-- return gg_pubdir_free(h);
--}
--
--#endif /* DOXYGEN */
--
--/**
-- * Usuwa użytkownika.
-- *
-- * Wymaga wcześniejszego pobrania tokenu za pomocą \c gg_token().
-- *
-- * \param uin Numer Gadu-Gadu
-- * \param password Hasło
-- * \param tokenid Identyfikator tokenu
-- * \param tokenval Zawartość tokenu
-- * \param async Flaga połączenia asynchronicznego
-- *
-- * \return Struktura \c gg_http lub \c NULL w przypadku błędu
-- *
-- * \ingroup unregister
-- */
--struct gg_http *gg_unregister3(uin_t uin, const char *password, const char *tokenid, const char *tokenval, int async)
--{
-- struct gg_http *h;
-- char *__fmpwd, *__pwd, *__tokenid, *__tokenval, *form, *query;
--
-- if (!password || !tokenid || !tokenval) {
-- gg_debug(GG_DEBUG_MISC, "=> unregister, NULL parameter\n");
-- errno = EFAULT;
-- return NULL;
-- }
--
-- __pwd = gg_saprintf("%ld", random());
-- __fmpwd = gg_urlencode(password);
-- __tokenid = gg_urlencode(tokenid);
-- __tokenval = gg_urlencode(tokenval);
--
-- if (!__fmpwd || !__pwd || !__tokenid || !__tokenval) {
-- gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for form fields\n");
-- free(__pwd);
-- free(__fmpwd);
-- free(__tokenid);
-- free(__tokenval);
-- return NULL;
-- }
--
-- form = gg_saprintf("fmnumber=%d&fmpwd=%s&delete=1&pwd=%s&email=deletedaccount@gadu-gadu.pl&tokenid=%s&tokenval=%s&code=%u", uin, __fmpwd, __pwd, __tokenid, __tokenval, gg_http_hash("ss", "deletedaccount@gadu-gadu.pl", __pwd));
--
-- free(__fmpwd);
-- free(__pwd);
-- free(__tokenid);
-- free(__tokenval);
--
-- if (!form) {
-- gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for form query\n");
-- return NULL;
-- }
--
-- gg_debug(GG_DEBUG_MISC, "=> unregister, %s\n", form);
--
-- query = gg_saprintf(
-- "Host: " GG_REGISTER_HOST "\r\n"
-- "Content-Type: application/x-www-form-urlencoded\r\n"
-- "User-Agent: " GG_HTTP_USERAGENT "\r\n"
-- "Content-Length: %d\r\n"
-- "Pragma: no-cache\r\n"
-- "\r\n"
-- "%s",
-- (int) strlen(form), form);
--
-- free(form);
--
-- if (!query) {
-- gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for query\n");
-- return NULL;
-- }
--
-- if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/fmregister3.asp", query))) {
-- gg_debug(GG_DEBUG_MISC, "=> unregister, gg_http_connect() failed mysteriously\n");
-- free(query);
-- return NULL;
-- }
--
-- h->type = GG_SESSION_UNREGISTER;
--
-- free(query);
--
-- h->callback = gg_pubdir_watch_fd;
-- h->destroy = gg_pubdir_free;
--
-- if (!async)
-- gg_pubdir_watch_fd(h);
--
-- return h;
--}
--
--#ifdef DOXYGEN
--
--/**
-- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
-- *
-- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
-- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
-- * znajdzie siÄ™ w polu \c error.
-- *
-- * \note W rzeczywistości funkcja jest makrem rozwijanym do
-- * \c gg_pubdir_watch_fd().
-- *
-- * \param h Struktura połączenia
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup unregister
-- */
--int gg_unregister_watch_fd(struct gg_httpd *h)
--{
-- return gg_pubdir_watch_fd(h);
--}
--
--/**
-- * Zwalnia zasoby po operacji.
-- *
-- * \note W rzeczywistości funkcja jest makrem rozwijanym do \c gg_pubdir_free().
-- *
-- * \param h Struktura połączenia
-- *
-- * \ingroup unregister
-- */
--void gg_unregister_free(struct gg_http *h)
--{
-- return gg_pubdir_free(h);
--}
--
--#endif /* DOXYGEN */
--
--/**
-- * Zmienia hasło użytkownika.
-- *
-- * Wymaga wcześniejszego pobrania tokenu za pomocą \c gg_token().
-- *
-- * \param uin Numer Gadu-Gadu
-- * \param email Adres e-mail
-- * \param passwd Obecne hasło
-- * \param newpasswd Nowe hasło
-- * \param tokenid Identyfikator tokenu
-- * \param tokenval Zawartość tokenu
-- * \param async Flaga połączenia asynchronicznego
-- *
-- * \return Struktura \c gg_http lub \c NULL w przypadku błędu
-- *
-- * \ingroup passwd
-- */
--struct gg_http *gg_change_passwd4(uin_t uin, const char *email, const char *passwd, const char *newpasswd, const char *tokenid, const char *tokenval, int async)
--{
-- struct gg_http *h;
-- char *form, *query, *__email, *__fmpwd, *__pwd, *__tokenid, *__tokenval;
--
-- if (!uin || !email || !passwd || !newpasswd || !tokenid || !tokenval) {
-- gg_debug(GG_DEBUG_MISC, "=> change, NULL parameter\n");
-- errno = EFAULT;
-- return NULL;
-- }
--
-- __fmpwd = gg_urlencode(passwd);
-- __pwd = gg_urlencode(newpasswd);
-- __email = gg_urlencode(email);
-- __tokenid = gg_urlencode(tokenid);
-- __tokenval = gg_urlencode(tokenval);
--
-- if (!__fmpwd || !__pwd || !__email || !__tokenid || !__tokenval) {
-- gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for form fields\n");
-- free(__fmpwd);
-- free(__pwd);
-- free(__email);
-- free(__tokenid);
-- free(__tokenval);
-- return NULL;
-- }
--
-- if (!(form = gg_saprintf("fmnumber=%d&fmpwd=%s&pwd=%s&email=%s&tokenid=%s&tokenval=%s&code=%u", uin, __fmpwd, __pwd, __email, __tokenid, __tokenval, gg_http_hash("ss", email, newpasswd)))) {
-- gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for form fields\n");
-- free(__fmpwd);
-- free(__pwd);
-- free(__email);
-- free(__tokenid);
-- free(__tokenval);
--
-- return NULL;
-- }
--
-- free(__fmpwd);
-- free(__pwd);
-- free(__email);
-- free(__tokenid);
-- free(__tokenval);
--
-- gg_debug(GG_DEBUG_MISC, "=> change, %s\n", form);
--
-- query = gg_saprintf(
-- "Host: " GG_REGISTER_HOST "\r\n"
-- "Content-Type: application/x-www-form-urlencoded\r\n"
-- "User-Agent: " GG_HTTP_USERAGENT "\r\n"
-- "Content-Length: %d\r\n"
-- "Pragma: no-cache\r\n"
-- "\r\n"
-- "%s",
-- (int) strlen(form), form);
--
-- free(form);
--
-- if (!query) {
-- gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for query\n");
-- return NULL;
-- }
--
-- if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/fmregister3.asp", query))) {
-- gg_debug(GG_DEBUG_MISC, "=> change, gg_http_connect() failed mysteriously\n");
-- free(query);
-- return NULL;
-- }
--
-- h->type = GG_SESSION_PASSWD;
--
-- free(query);
--
-- h->callback = gg_pubdir_watch_fd;
-- h->destroy = gg_pubdir_free;
--
-- if (!async)
-- gg_pubdir_watch_fd(h);
--
-- return h;
--}
--
--#ifdef DOXYGEN
--
--/**
-- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
-- *
-- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
-- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
-- * znajdzie siÄ™ w polu \c error.
-- *
-- * \note W rzeczywistości funkcja jest makrem rozwijanym do
-- * \c gg_pubdir_watch_fd().
-- *
-- * \param h Struktura połączenia
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup passwd
-- */
--int gg_change_passwd_watch_fd(struct gg_httpd *h)
--{
-- return gg_pubdir_watch_fd(h);
--}
--
--/**
-- * Zwalnia zasoby po operacji.
-- *
-- * \note W rzeczywistości funkcja jest makrem rozwijanym do \c gg_pubdir_free().
-- *
-- * \param h Struktura połączenia
-- *
-- * \ingroup passwd
-- */
--void gg_change_passwd_free(struct gg_http *h)
--{
-- return gg_pubdir_free(h);
--}
--
--#endif /* DOXYGEN */
--
--/**
-- * Wysyła hasło użytkownika na e-mail.
-- *
-- * Wymaga wcześniejszego pobrania tokenu za pomocą \c gg_token().
-- *
-- * \param uin Numer Gadu-Gadu
-- * \param email Adres e-mail (podany przy rejestracji)
-- * \param tokenid Identyfikator tokenu
-- * \param tokenval Zawartość tokenu
-- * \param async Flaga połączenia asynchronicznego
-- *
-- * \return Struktura \c gg_http lub \c NULL w przypadku błędu
-- *
-- * \ingroup remind
-- */
--struct gg_http *gg_remind_passwd3(uin_t uin, const char *email, const char *tokenid, const char *tokenval, int async)
--{
-- struct gg_http *h;
-- char *form, *query, *__tokenid, *__tokenval, *__email;
--
-- if (!tokenid || !tokenval || !email) {
-- gg_debug(GG_DEBUG_MISC, "=> remind, NULL parameter\n");
-- errno = EFAULT;
-- return NULL;
-- }
--
-- __tokenid = gg_urlencode(tokenid);
-- __tokenval = gg_urlencode(tokenval);
-- __email = gg_urlencode(email);
--
-- if (!__tokenid || !__tokenval || !__email) {
-- gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for form fields\n");
-- free(__tokenid);
-- free(__tokenval);
-- free(__email);
-- return NULL;
-- }
--
-- if (!(form = gg_saprintf("userid=%d&code=%u&tokenid=%s&tokenval=%s&email=%s", uin, gg_http_hash("u", uin), __tokenid, __tokenval, __email))) {
-- gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for form fields\n");
-- free(__tokenid);
-- free(__tokenval);
-- free(__email);
-- return NULL;
-- }
--
-- free(__tokenid);
-- free(__tokenval);
-- free(__email);
--
-- gg_debug(GG_DEBUG_MISC, "=> remind, %s\n", form);
--
-- query = gg_saprintf(
-- "Host: " GG_REMIND_HOST "\r\n"
-- "Content-Type: application/x-www-form-urlencoded\r\n"
-- "User-Agent: " GG_HTTP_USERAGENT "\r\n"
-- "Content-Length: %d\r\n"
-- "Pragma: no-cache\r\n"
-- "\r\n"
-- "%s",
-- (int) strlen(form), form);
--
-- free(form);
--
-- if (!query) {
-- gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for query\n");
-- return NULL;
-- }
--
-- if (!(h = gg_http_connect(GG_REMIND_HOST, GG_REMIND_PORT, async, "POST", "/appsvc/fmsendpwd3.asp", query))) {
-- gg_debug(GG_DEBUG_MISC, "=> remind, gg_http_connect() failed mysteriously\n");
-- free(query);
-- return NULL;
-- }
--
-- h->type = GG_SESSION_REMIND;
--
-- free(query);
--
-- h->callback = gg_pubdir_watch_fd;
-- h->destroy = gg_pubdir_free;
--
-- if (!async)
-- gg_pubdir_watch_fd(h);
--
-- return h;
--}
--
--#ifdef DOXYGEN
--
--/**
-- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
-- *
-- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
-- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
-- * znajdzie siÄ™ w polu \c error.
-- *
-- * \note W rzeczywistości funkcja jest makrem rozwijanym do
-- * \c gg_pubdir_watch_fd().
-- *
-- * \param h Struktura połączenia
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup remind
-- */
--int gg_remind_watch_fd(struct gg_httpd *h)
--{
-- return gg_pubdir_watch_fd(h);
--}
--
--/**
-- * Zwalnia zasoby po operacji.
-- *
-- * \note W rzeczywistości funkcja jest makrem rozwijanym do \c gg_pubdir_free().
-- *
-- * \param h Struktura połączenia
-- *
-- * \ingroup remind
-- */
--void gg_remind_free(struct gg_http *h)
--{
-- return gg_pubdir_free(h);
--}
--
--#endif /* DOXYGEN */
--
--/**
-- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
-- *
-- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
-- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
-- * znajdzie siÄ™ w polu \c error.
-- *
-- * \param h Struktura połączenia
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--int gg_pubdir_watch_fd(struct gg_http *h)
--{
-- struct gg_pubdir *p;
-- char *tmp;
--
-- if (!h) {
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (h->state == GG_STATE_ERROR) {
-- gg_debug(GG_DEBUG_MISC, "=> pubdir, watch_fd issued on failed session\n");
-- errno = EINVAL;
-- return -1;
-- }
--
-- if (h->state != GG_STATE_PARSING) {
-- if (gg_http_watch_fd(h) == -1) {
-- gg_debug(GG_DEBUG_MISC, "=> pubdir, http failure\n");
-- errno = EINVAL;
-- return -1;
-- }
-- }
--
-- if (h->state != GG_STATE_PARSING)
-- return 0;
--
-- h->state = GG_STATE_DONE;
--
-- if (!(h->data = p = malloc(sizeof(struct gg_pubdir)))) {
-- gg_debug(GG_DEBUG_MISC, "=> pubdir, not enough memory for results\n");
-- return -1;
-- }
--
-- p->success = 0;
-- p->uin = 0;
--
-- gg_debug(GG_DEBUG_MISC, "=> pubdir, let's parse \"%s\"\n", h->body);
--
-- if ((tmp = strstr(h->body, "Tokens okregisterreply_packet.reg.dwUserId="))) {
-- p->success = 1;
-- p->uin = strtol(tmp + sizeof("Tokens okregisterreply_packet.reg.dwUserId=") - 1, NULL, 0);
-- gg_debug(GG_DEBUG_MISC, "=> pubdir, success (okregisterreply, uin=%d)\n", p->uin);
-- } else if ((tmp = strstr(h->body, "success")) || (tmp = strstr(h->body, "results"))) {
-- p->success = 1;
-- if (tmp[7] == ':')
-- p->uin = strtol(tmp + 8, NULL, 0);
-- gg_debug(GG_DEBUG_MISC, "=> pubdir, success (uin=%d)\n", p->uin);
-- } else
-- gg_debug(GG_DEBUG_MISC, "=> pubdir, error.\n");
--
-- return 0;
--}
--
--/**
-- * Zwalnia zasoby po operacji na katalogu publicznym.
-- *
-- * \param h Struktura połączenia
-- */
--void gg_pubdir_free(struct gg_http *h)
--{
-- if (!h)
-- return;
--
-- free(h->data);
-- gg_http_free(h);
--}
--
--/**
-- * Pobiera token do autoryzacji operacji na katalogu publicznym.
-- *
-- * Token jest niezbędny do tworzenia nowego i usuwania użytkownika,
-- * zmiany hasła itd.
-- *
-- * \param async Flaga połączenia asynchronicznego
-- *
-- * \return Struktura \c gg_http lub \c NULL w przypadku błędu
-- *
-- * \ingroup token
-- */
--struct gg_http *gg_token(int async)
--{
-- struct gg_http *h;
-- const char *query;
--
-- query = "Host: " GG_REGISTER_HOST "\r\n"
-- "Content-Type: application/x-www-form-urlencoded\r\n"
-- "User-Agent: " GG_HTTP_USERAGENT "\r\n"
-- "Content-Length: 0\r\n"
-- "Pragma: no-cache\r\n"
-- "\r\n";
--
-- if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/regtoken.asp", query))) {
-- gg_debug(GG_DEBUG_MISC, "=> token, gg_http_connect() failed mysteriously\n");
-- return NULL;
-- }
--
-- h->type = GG_SESSION_TOKEN;
--
-- h->callback = gg_token_watch_fd;
-- h->destroy = gg_token_free;
--
-- if (!async)
-- gg_token_watch_fd(h);
--
-- return h;
--}
--
--/**
-- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
-- *
-- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
-- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
-- * znajdzie siÄ™ w polu \c error.
-- *
-- * \param h Struktura połączenia
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- *
-- * \ingroup token
-- */
--int gg_token_watch_fd(struct gg_http *h)
--{
-- if (!h) {
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (h->state == GG_STATE_ERROR) {
-- gg_debug(GG_DEBUG_MISC, "=> token, watch_fd issued on failed session\n");
-- errno = EINVAL;
-- return -1;
-- }
--
-- if (h->state != GG_STATE_PARSING) {
-- if (gg_http_watch_fd(h) == -1) {
-- gg_debug(GG_DEBUG_MISC, "=> token, http failure\n");
-- errno = EINVAL;
-- return -1;
-- }
-- }
--
-- if (h->state != GG_STATE_PARSING)
-- return 0;
--
-- /* jeśli h->data jest puste, to ściągaliśmy tokenid i url do niego,
-- * ale jeśli coś tam jest, to znaczy, że mamy drugi etap polegający
-- * na pobieraniu tokenu. */
-- if (!h->data) {
-- int width, height, length;
-- char *url = NULL, *tokenid = NULL, *path, *headers;
-- const char *host;
-- struct gg_http *h2;
-- struct gg_token *t;
--
-- gg_debug(GG_DEBUG_MISC, "=> token body \"%s\"\n", h->body);
--
-- if (h->body && (!(url = malloc(strlen(h->body))) || !(tokenid = malloc(strlen(h->body))))) {
-- gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for results\n");
-- free(url);
-- return -1;
-- }
--
-- if (!h->body || sscanf(h->body, "%d %d %d\r\n%s\r\n%s", &width, &height, &length, tokenid, url) != 5) {
-- gg_debug(GG_DEBUG_MISC, "=> token, parsing failed\n");
-- free(url);
-- free(tokenid);
-- errno = EINVAL;
-- return -1;
-- }
--
-- /* dostaliśmy tokenid i wszystkie niezbędne informacje,
-- * więc pobierzmy obrazek z tokenem */
--
-- if (strncmp(url, "http://", 7)) {
-- path = gg_saprintf("%s?tokenid=%s", url, tokenid);
-- host = GG_REGISTER_HOST;
-- } else {
-- char *slash = strchr(url + 7, '/');
--
-- if (slash) {
-- path = gg_saprintf("%s?tokenid=%s", slash, tokenid);
-- *slash = 0;
-- host = url + 7;
-- } else {
-- gg_debug(GG_DEBUG_MISC, "=> token, url parsing failed\n");
-- free(url);
-- free(tokenid);
-- errno = EINVAL;
-- return -1;
-- }
-- }
--
-- if (!path) {
-- gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token url\n");
-- free(url);
-- free(tokenid);
-- return -1;
-- }
--
-- if (!(headers = gg_saprintf("Host: %s\r\nUser-Agent: " GG_HTTP_USERAGENT "\r\n\r\n", host))) {
-- gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token url\n");
-- free(path);
-- free(url);
-- free(tokenid);
-- return -1;
-- }
--
-- if (!(h2 = gg_http_connect(host, GG_REGISTER_PORT, h->async, "GET", path, headers))) {
-- gg_debug(GG_DEBUG_MISC, "=> token, gg_http_connect() failed mysteriously\n");
-- free(headers);
-- free(url);
-- free(path);
-- free(tokenid);
-- return -1;
-- }
--
-- free(headers);
-- free(path);
-- free(url);
--
-- gg_http_free_fields(h);
--
-- memcpy(h, h2, sizeof(struct gg_http));
-- free(h2);
--
-- h->type = GG_SESSION_TOKEN;
--
-- h->callback = gg_token_watch_fd;
-- h->destroy = gg_token_free;
--
-- if (!h->async)
-- gg_token_watch_fd(h);
--
-- if (!(h->data = t = malloc(sizeof(struct gg_token)))) {
-- gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token data\n");
-- free(tokenid);
-- return -1;
-- }
--
-- t->width = width;
-- t->height = height;
-- t->length = length;
-- t->tokenid = tokenid;
-- } else {
-- /* obrazek mamy w h->body */
-- h->state = GG_STATE_DONE;
-- }
--
-- return 0;
--}
--
--/**
-- * Zwalnia zasoby po operacji pobierania tokenu.
-- *
-- * \param h Struktura połączenia
-- *
-- * \ingroup token
-- */
--void gg_token_free(struct gg_http *h)
--{
-- struct gg_token *t;
--
-- if (!h)
-- return;
--
-- if ((t = h->data))
-- free(t->tokenid);
--
-- free(h->data);
-- gg_http_free(h);
--}
--
--/*
-- * Local variables:
-- * c-indentation-style: k&r
-- * c-basic-offset: 8
-- * indent-tabs-mode: notnil
-- * End:
-- *
-- * vim: shiftwidth=8:
-- */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/resolver.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/resolver.c
---- pidgin-2.10.7/libpurple/protocols/gg/lib/resolver.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/resolver.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1149 +0,0 @@
--/*
-- * (C) Copyright 2001-2009 Wojtek Kaniewski <wojtekka@irc.pl>
-- * Robert J. Woźny <speedy@ziew.org>
-- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
-- * Tomasz Chiliński <chilek@chilan.com>
-- * Adam Wysocki <gophi@ekg.chmurka.net>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--/**
-- * \file resolver.c
-- *
-- * \brief Funkcje rozwiÄ…zywania nazw
-- */
--
--#ifndef _WIN32
--# include <sys/wait.h>
--# include <netdb.h>
--#endif
--#include <errno.h>
--#include <stdlib.h>
--#include <string.h>
--#include <unistd.h>
--#ifndef _WIN32
--# include <signal.h>
--# include <netinet/in.h>
--# include <arpa/inet.h>
--#endif
--
--#include "libgadu.h"
--#include "libgadu-config.h"
--#include "resolver.h"
--#include "compat.h"
--#include "session.h"
--
--/** Sposób rozwiązywania nazw serwerów */
--static gg_resolver_t gg_global_resolver_type = GG_RESOLVER_DEFAULT;
--
--/** Funkcja rozpoczynajÄ…ca rozwiÄ…zywanie nazwy */
--static int (*gg_global_resolver_start)(int *fd, void **private_data, const char *hostname);
--
--/** Funkcja zwalniajÄ…ca zasoby po rozwiÄ…zaniu nazwy */
--static void (*gg_global_resolver_cleanup)(void **private_data, int force);
--
--#ifdef GG_CONFIG_HAVE_PTHREAD
--
--#include <pthread.h>
--
--/**
-- * \internal Funkcja pomocnicza zwalniajÄ…ca zasoby po rozwiÄ…zywaniu nazwy
-- * w wÄ…tku.
-- *
-- * \param data Wskaźnik na wskaźnik bufora zaalokowanego w wątku
-- */
--static void gg_gethostbyname_cleaner(void *data)
--{
-- char **buf_ptr = (char**) data;
--
-- if (buf_ptr != NULL) {
-- free(*buf_ptr);
-- *buf_ptr = NULL;
-- }
--}
--
--#endif /* GG_CONFIG_HAVE_PTHREAD */
--
--/**
-- * \internal Odpowiednik \c gethostbyname zapewniający współbieżność.
-- *
-- * Jeśli dany system dostarcza \c gethostbyname_r, używa się tej wersji, jeśli
-- * nie, to zwykłej \c gethostbyname. Wynikiem jest tablica adresów zakończona
-- * wartością INADDR_NONE, którą należy zwolnić po użyciu.
-- *
-- * \param hostname Nazwa serwera
-- * \param result Wskaźnik na wskaźnik z tablicą adresów zakończoną INADDR_NONE
-- * \param count Wskaźnik na zmienną, do ktorej zapisze się liczbę wyników
-- * \param pthread Flaga blokowania unicestwiania wątku podczas alokacji pamięci
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--int gg_gethostbyname_real(const char *hostname, struct in_addr **result, int *count, int pthread)
--{
--#ifdef GG_CONFIG_HAVE_GETHOSTBYNAME_R
-- char *buf = NULL;
-- char *new_buf = NULL;
-- struct hostent he;
-- struct hostent *he_ptr = NULL;
-- size_t buf_len = 1024;
-- int res = -1;
-- int h_errnop;
-- int ret = 0;
--#ifdef GG_CONFIG_HAVE_PTHREAD
-- int old_state;
--#endif
--
-- if (result == NULL) {
-- errno = EINVAL;
-- return -1;
-- }
--
--#ifdef GG_CONFIG_HAVE_PTHREAD
-- pthread_cleanup_push(gg_gethostbyname_cleaner, &buf);
--
-- if (pthread)
-- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
--#endif
--
-- buf = malloc(buf_len);
--
--#ifdef GG_CONFIG_HAVE_PTHREAD
-- if (pthread)
-- pthread_setcancelstate(old_state, NULL);
--#endif
--
-- if (buf != NULL) {
--#ifndef sun
-- while ((ret = gethostbyname_r(hostname, &he, buf, buf_len, &he_ptr, &h_errnop)) == ERANGE) {
--#else
-- while (((he_ptr = gethostbyname_r(hostname, &he, buf, buf_len, &h_errnop)) == NULL) && (errno == ERANGE)) {
--#endif
-- buf_len *= 2;
--
--#ifdef GG_CONFIG_HAVE_PTHREAD
-- if (pthread)
-- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
--#endif
--
-- new_buf = realloc(buf, buf_len);
--
-- if (new_buf != NULL)
-- buf = new_buf;
--
--#ifdef GG_CONFIG_HAVE_PTHREAD
-- if (pthread)
-- pthread_setcancelstate(old_state, NULL);
--#endif
--
-- if (new_buf == NULL) {
-- ret = ENOMEM;
-- break;
-- }
-- }
--
-- if (ret == 0 && he_ptr != NULL && he_ptr->h_addr_list[0] != NULL) {
-- int i;
--
-- /* Policz liczbę adresów */
--
-- for (i = 0; he_ptr->h_addr_list[i] != NULL; i++)
-- ;
--
-- /* Zaalokuj */
--
--#ifdef GG_CONFIG_HAVE_PTHREAD
-- if (pthread)
-- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
--#endif
--
-- *result = malloc((i + 1) * sizeof(struct in_addr));
--
--#ifdef GG_CONFIG_HAVE_PTHREAD
-- if (pthread)
-- pthread_setcancelstate(old_state, NULL);
--#endif
--
-- if (*result == NULL)
-- return -1;
--
-- /* Kopiuj */
--
-- for (i = 0; he_ptr->h_addr_list[i] != NULL; i++)
-- memcpy(&((*result)[i]), he_ptr->h_addr_list[i], sizeof(struct in_addr));
--
-- (*result)[i].s_addr = INADDR_NONE;
--
-- *count = i;
--
-- res = 0;
-- }
--
--#ifdef GG_CONFIG_HAVE_PTHREAD
-- if (pthread)
-- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
--#endif
--
-- free(buf);
-- buf = NULL;
--
--#ifdef GG_CONFIG_HAVE_PTHREAD
-- if (pthread)
-- pthread_setcancelstate(old_state, NULL);
--#endif
-- }
--
--#ifdef GG_CONFIG_HAVE_PTHREAD
-- pthread_cleanup_pop(1);
--#endif
--
-- return res;
--#else /* GG_CONFIG_HAVE_GETHOSTBYNAME_R */
-- struct hostent *he;
-- int i;
--
-- if (result == NULL || count == NULL) {
-- errno = EINVAL;
-- return -1;
-- }
--
-- he = gethostbyname(hostname);
--
-- if (he == NULL || he->h_addr_list[0] == NULL)
-- return -1;
--
-- /* Policz liczbę adresów */
--
-- for (i = 0; he->h_addr_list[i] != NULL; i++)
-- ;
--
-- /* Zaalokuj */
--
-- *result = malloc((i + 1) * sizeof(struct in_addr));
--
-- if (*result == NULL)
-- return -1;
--
-- /* Kopiuj */
--
-- for (i = 0; he->h_addr_list[i] != NULL; i++)
-- memcpy(&((*result)[i]), he->h_addr_list[0], sizeof(struct in_addr));
--
-- (*result)[i].s_addr = INADDR_NONE;
--
-- *count = i;
--
-- return 0;
--#endif /* GG_CONFIG_HAVE_GETHOSTBYNAME_R */
--}
--
--#if defined(GG_CONFIG_HAVE_PTHREAD) || !defined(_WIN32)
--/**
-- * \internal RozwiÄ…zuje nazwÄ™ i zapisuje wynik do podanego desktyptora.
-- *
-- * \param fd Deskryptor
-- * \param hostname Nazwa serwera
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--static int gg_resolver_run(int fd, const char *hostname)
--{
-- struct in_addr addr_ip[2], *addr_list;
-- int addr_count;
-- int res = 0;
--
-- gg_debug(GG_DEBUG_MISC, "// gg_resolver_run(%d, %s)\n", fd, hostname);
--
-- if ((addr_ip[0].s_addr = inet_addr(hostname)) == INADDR_NONE) {
-- if (gg_gethostbyname_real(hostname, &addr_list, &addr_count, 1) == -1) {
-- addr_list = addr_ip;
-- /* addr_ip[0] już zawiera INADDR_NONE */
-- }
-- } else {
-- addr_list = addr_ip;
-- addr_ip[1].s_addr = INADDR_NONE;
-- addr_count = 1;
-- }
--
-- gg_debug(GG_DEBUG_MISC, "// gg_resolver_run() count = %d\n", addr_count);
--
-- if (write(fd, addr_list, (addr_count + 1) * sizeof(struct in_addr)) != (addr_count + 1) * sizeof(struct in_addr))
-- res = -1;
--
-- if (addr_list != addr_ip)
-- free(addr_list);
--
-- return res;
--}
--#endif
--
--/**
-- * \internal Odpowiednik \c gethostbyname zapewniający współbieżność.
-- *
-- * Jeśli dany system dostarcza \c gethostbyname_r, używa się tej wersji, jeśli
-- * nie, to zwykłej \c gethostbyname. Funkcja służy do zachowania zgodności
-- * ABI i służy do pobierania tylko pierwszego adresu -- pozostałe mogą
-- * zostać zignorowane przez aplikację.
-- *
-- * \param hostname Nazwa serwera
-- *
-- * \return Zaalokowana struktura \c in_addr lub NULL w przypadku błędu.
-- */
--struct in_addr *gg_gethostbyname(const char *hostname)
--{
-- struct in_addr *result;
-- int count;
--
-- if (gg_gethostbyname_real(hostname, &result, &count, 0) == -1)
-- return NULL;
--
-- return result;
--}
--
--/**
-- * \internal Struktura przekazywana do wÄ…tku rozwiÄ…zujÄ…cego nazwÄ™.
-- */
--struct gg_resolver_fork_data {
-- int pid; /*< Identyfikator procesu */
--};
--
--#ifdef _WIN32
--/**
-- * Deal with the fact that you can't select() on a win32 file fd.
-- * This makes it practically impossible to tie into purple's event loop.
-- *
-- * -This is thanks to Tor Lillqvist.
-- * XXX - Move this to where the rest of the the win32 compatiblity stuff goes when we push the changes back to libgadu.
-- */
--static int
--socket_pipe (int *fds)
--{
-- SOCKET temp, socket1 = -1, socket2 = -1;
-- struct sockaddr_in saddr;
-- int len;
-- u_long arg;
-- fd_set read_set, write_set;
-- struct timeval tv;
--
-- temp = socket(AF_INET, SOCK_STREAM, 0);
--
-- if (temp == INVALID_SOCKET) {
-- goto out0;
-- }
--
-- arg = 1;
-- if (ioctlsocket(temp, FIONBIO, &arg) == SOCKET_ERROR) {
-- goto out0;
-- }
--
-- memset(&saddr, 0, sizeof(saddr));
-- saddr.sin_family = AF_INET;
-- saddr.sin_port = 0;
-- saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
--
-- if (bind(temp, (struct sockaddr *)&saddr, sizeof (saddr))) {
-- goto out0;
-- }
--
-- if (listen(temp, 1) == SOCKET_ERROR) {
-- goto out0;
-- }
--
-- len = sizeof(saddr);
-- if (getsockname(temp, (struct sockaddr *)&saddr, &len)) {
-- goto out0;
-- }
--
-- socket1 = socket(AF_INET, SOCK_STREAM, 0);
--
-- if (socket1 == INVALID_SOCKET) {
-- goto out0;
-- }
--
-- arg = 1;
-- if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) {
-- goto out1;
-- }
--
-- if (connect(socket1, (struct sockaddr *)&saddr, len) != SOCKET_ERROR ||
-- WSAGetLastError() != WSAEWOULDBLOCK) {
-- goto out1;
-- }
--
-- FD_ZERO(&read_set);
-- FD_SET(temp, &read_set);
--
-- tv.tv_sec = 0;
-- tv.tv_usec = 0;
--
-- if (select(0, &read_set, NULL, NULL, NULL) == SOCKET_ERROR) {
-- goto out1;
-- }
--
-- if (!FD_ISSET(temp, &read_set)) {
-- goto out1;
-- }
--
-- socket2 = accept(temp, (struct sockaddr *) &saddr, &len);
-- if (socket2 == INVALID_SOCKET) {
-- goto out1;
-- }
--
-- FD_ZERO(&write_set);
-- FD_SET(socket1, &write_set);
--
-- tv.tv_sec = 0;
-- tv.tv_usec = 0;
--
-- if (select(0, NULL, &write_set, NULL, NULL) == SOCKET_ERROR) {
-- goto out2;
-- }
--
-- if (!FD_ISSET(socket1, &write_set)) {
-- goto out2;
-- }
--
-- arg = 0;
-- if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) {
-- goto out2;
-- }
--
-- arg = 0;
-- if (ioctlsocket(socket2, FIONBIO, &arg) == SOCKET_ERROR) {
-- goto out2;
-- }
--
-- fds[0] = socket1;
-- fds[1] = socket2;
--
-- closesocket (temp);
--
-- return 0;
--
--out2:
-- closesocket (socket2);
--out1:
-- closesocket (socket1);
--out0:
-- closesocket (temp);
-- errno = EIO; /* XXX */
--
-- return -1;
--}
--#endif
--
--
--
--#ifdef _WIN32
--struct gg_resolve_win32thread_data {
-- char *hostname;
-- int fd;
--};
--
--static DWORD WINAPI gg_resolve_win32thread_thread(LPVOID arg)
--{
-- struct gg_resolve_win32thread_data *d = arg;
-- struct in_addr addr_ip[2], *addr_list;
-- int addr_count;
--
-- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_thread() host: %s, fd: %i called\n", d->hostname, d->fd);
--
-- if ((addr_ip[0].s_addr = inet_addr(d->hostname)) == INADDR_NONE) {
-- /* W przypadku błędu gg_gethostbyname_real() zwróci -1
-- * i nie zmieni &addr. Tam jest już INADDR_NONE,
-- * więc nie musimy robić nic więcej. */
-- if (gg_gethostbyname_real(d->hostname, &addr_list, &addr_count, 0) == -1)
-- {
-- addr_list = addr_ip;
-- }
-- } else {
-- addr_list = addr_ip;
-- addr_ip[1].s_addr = INADDR_NONE;
-- addr_count = 1;
-- }
--
-- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_thread() count = %d\n", addr_count);
--
-- write(d->fd, addr_list, (addr_count+1) * sizeof(struct in_addr));
-- close(d->fd);
--
-- free(d->hostname);
-- d->hostname = NULL;
--
-- free(d);
--
-- if (addr_list != addr_ip)
-- free(addr_list);
--
-- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_thread() done\n");
--
-- return 0;
--}
--
--
--static int gg_resolve_win32thread(int *fd, void **resolver, const char *hostname)
--{
-- struct gg_resolve_win32thread_data *d = NULL;
-- HANDLE h;
-- DWORD dwTId;
-- int pipes[2], new_errno;
--
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve_win32thread(%p, %p, \"%s\");\n", fd, resolver, hostname);
--
-- if (!resolver || !fd || !hostname) {
-- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() invalid arguments\n");
-- errno = EFAULT;
-- return -1;
-- }
--
-- if (socket_pipe(pipes) == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno));
-- return -1;
-- }
--
-- if (!(d = malloc(sizeof(*d)))) {
-- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() out of memory\n");
-- new_errno = errno;
-- goto cleanup;
-- }
--
-- d->hostname = NULL;
--
-- if (!(d->hostname = strdup(hostname))) {
-- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() out of memory\n");
-- new_errno = errno;
-- goto cleanup;
-- }
--
-- d->fd = pipes[1];
--
-- h = CreateThread(NULL, 0, gg_resolve_win32thread_thread,
-- d, 0, &dwTId);
--
-- if (h == NULL) {
-- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() unable to create thread\n");
-- new_errno = errno;
-- goto cleanup;
-- }
--
-- *resolver = h;
-- *fd = pipes[0];
--
-- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() done\n");
--
-- return 0;
--
--cleanup:
-- if (d) {
-- free(d->hostname);
-- free(d);
-- }
--
-- close(pipes[0]);
-- close(pipes[1]);
--
-- errno = new_errno;
--
-- return -1;
--
--}
--
--static void gg_resolve_win32thread_cleanup(void **priv_data, int force)
--{
-- struct gg_resolve_win32thread_data *data;
--
-- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() force: %i called\n", force);
--
-- if (priv_data == NULL || *priv_data == NULL)
-- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() priv_data: NULL\n");
-- return;
--
-- data = (struct gg_resolve_win32thread_data*) *priv_data;
-- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() data: %s called\n", data->hostname);
-- *priv_data = NULL;
--
-- if (force) {
-- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() force called\n", force);
-- //pthread_cancel(data->thread);
-- //pthread_join(data->thread, NULL);
-- }
--
-- free(data->hostname);
-- data->hostname = NULL;
--
-- if (data->fd != -1) {
-- close(data->fd);
-- data->fd = -1;
-- }
-- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() done\n");
-- free(data);
--}
--#endif
--
--#ifndef _WIN32
--/**
-- * \internal RozwiÄ…zuje nazwÄ™ serwera w osobnym procesie.
-- *
-- * Połączenia asynchroniczne nie mogą blokować procesu w trakcie rozwiązywania
-- * nazwy serwera. W tym celu tworzony jest potok, nowy proces i dopiero w nim
-- * przeprowadzane jest rozwiÄ…zywanie nazwy. Deskryptor strony do odczytu
-- * zapisuje siÄ™ w strukturze sieci i czeka na dane w postaci struktury
-- * \c in_addr. Jeśli nie znaleziono nazwy, zwracana jest \c INADDR_NONE.
-- *
-- * \param fd Wskaźnik na zmienną, gdzie zostanie umieszczony deskryptor
-- * potoku
-- * \param priv_data Wskaźnik na zmienną, gdzie zostanie umieszczony wskaźnik
-- * do numeru procesu potomnego rozwiÄ…zujÄ…cego nazwÄ™
-- * \param hostname Nazwa serwera do rozwiÄ…zania
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--static int gg_resolver_fork_start(int *fd, void **priv_data, const char *hostname)
--{
-- struct gg_resolver_fork_data *data = NULL;
-- int pipes[2], new_errno;
--
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_resolver_fork_start(%p, %p, \"%s\");\n", fd, priv_data, hostname);
--
-- if (fd == NULL || priv_data == NULL || hostname == NULL) {
-- gg_debug(GG_DEBUG_MISC, "// gg_resolver_fork_start() invalid arguments\n");
-- errno = EFAULT;
-- return -1;
-- }
--
-- data = malloc(sizeof(struct gg_resolver_fork_data));
--
-- if (data == NULL) {
-- gg_debug(GG_DEBUG_MISC, "// gg_resolver_fork_start() out of memory for resolver data\n");
-- return -1;
-- }
--
-- if (pipe(pipes) == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_resolver_fork_start() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno));
-- free(data);
-- return -1;
-- }
--
-- data->pid = fork();
--
-- if (data->pid == -1) {
-- new_errno = errno;
-- goto cleanup;
-- }
--
-- if (data->pid == 0) {
-- close(pipes[0]);
--
-- if (gg_resolver_run(pipes[1], hostname) == -1)
-- _exit(1);
-- else
-- _exit(0);
-- }
--
-- close(pipes[1]);
--
-- gg_debug(GG_DEBUG_MISC, "// gg_resolver_fork_start() %p\n", data);
--
-- *fd = pipes[0];
-- *priv_data = data;
--
-- return 0;
--
--cleanup:
-- free(data);
-- close(pipes[0]);
-- close(pipes[1]);
--
-- errno = new_errno;
--
-- return -1;
--}
--
--/**
-- * \internal Usuwanie zasobów po procesie rozwiązywaniu nazwy.
-- *
-- * Funkcja wywoływana po zakończeniu rozwiązanywania nazwy lub przy zwalnianiu
-- * zasobów sesji podczas rozwiązywania nazwy.
-- *
-- * \param priv_data Wskaźnik na zmienną przechowującą wskaźnik do prywatnych
-- * danych
-- * \param force Flaga usuwania zasobów przed zakończeniem działania
-- */
--static void gg_resolver_fork_cleanup(void **priv_data, int force)
--{
-- struct gg_resolver_fork_data *data;
--
-- if (priv_data == NULL || *priv_data == NULL)
-- return;
--
-- data = (struct gg_resolver_fork_data*) *priv_data;
-- *priv_data = NULL;
--
-- if (force)
-- kill(data->pid, SIGKILL);
--
-- waitpid(data->pid, NULL, WNOHANG);
--
-- free(data);
--}
--#endif
--
--#ifdef GG_CONFIG_HAVE_PTHREAD
--
--/**
-- * \internal Struktura przekazywana do wÄ…tku rozwiÄ…zujÄ…cego nazwÄ™.
-- */
--struct gg_resolver_pthread_data {
-- pthread_t thread; /*< Identyfikator wÄ…tku */
-- char *hostname; /*< Nazwa serwera */
-- int rfd; /*< Deskryptor do odczytu */
-- int wfd; /*< Deskryptor do zapisu */
--};
--
--/**
-- * \internal Usuwanie zasobów po wątku rozwiązywaniu nazwy.
-- *
-- * Funkcja wywoływana po zakończeniu rozwiązanywania nazwy lub przy zwalnianiu
-- * zasobów sesji podczas rozwiązywania nazwy.
-- *
-- * \param priv_data Wskaźnik na zmienną przechowującą wskaźnik do prywatnych
-- * danych
-- * \param force Flaga usuwania zasobów przed zakończeniem działania
-- */
--static void gg_resolver_pthread_cleanup(void **priv_data, int force)
--{
-- struct gg_resolver_pthread_data *data;
--
-- if (priv_data == NULL || *priv_data == NULL)
-- return;
--
-- data = (struct gg_resolver_pthread_data *) *priv_data;
-- *priv_data = NULL;
--
-- if (force) {
-- pthread_cancel(data->thread);
-- pthread_join(data->thread, NULL);
-- }
--
-- free(data->hostname);
-- data->hostname = NULL;
--
-- if (data->wfd != -1) {
-- close(data->wfd);
-- data->wfd = -1;
-- }
--
-- free(data);
--}
--
--/**
-- * \internal WÄ…tek rozwiÄ…zujÄ…cy nazwÄ™.
-- *
-- * \param arg Wskaźnik na strukturę \c gg_resolver_pthread_data
-- */
--static void *gg_resolver_pthread_thread(void *arg)
--{
-- struct gg_resolver_pthread_data *data = arg;
--
-- pthread_detach(pthread_self());
--
-- if (gg_resolver_run(data->wfd, data->hostname) == -1)
-- pthread_exit((void*) -1);
-- else
-- pthread_exit(NULL);
--
-- return NULL; /* żeby kompilator nie marudził */
--}
--
--/**
-- * \internal RozwiÄ…zuje nazwÄ™ serwera w osobnym wÄ…tku.
-- *
-- * Funkcja działa analogicznie do \c gg_resolver_fork_start(), z tą różnicą,
-- * że działa na wątkach, nie procesach. Jest dostępna wyłącznie gdy podczas
-- * kompilacji włączono odpowiednią opcję.
-- *
-- * \param fd Wskaźnik na zmienną, gdzie zostanie umieszczony deskryptor
-- * potoku
-- * \param priv_data Wskaźnik na zmienną, gdzie zostanie umieszczony wskaźnik
-- * do prywatnych danych wÄ…tku rozwiÄ…zujÄ…cego nazwÄ™
-- * \param hostname Nazwa serwera do rozwiÄ…zania
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--static int gg_resolver_pthread_start(int *fd, void **priv_data, const char *hostname)
--{
-- struct gg_resolver_pthread_data *data = NULL;
-- int pipes[2], new_errno;
--
-- gg_debug(GG_DEBUG_FUNCTION, "** gg_resolver_pthread_start(%p, %p, \"%s\");\n", fd, priv_data, hostname);
--
-- if (fd == NULL || priv_data == NULL || hostname == NULL) {
-- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() invalid arguments\n");
-- errno = EFAULT;
-- return -1;
-- }
--
-- data = malloc(sizeof(struct gg_resolver_pthread_data));
--
-- if (data == NULL) {
-- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() out of memory for resolver data\n");
-- return -1;
-- }
--
-- if (pipe(pipes) == -1) {
-- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno));
-- free(data);
-- return -1;
-- }
--
-- data->hostname = strdup(hostname);
--
-- if (data->hostname == NULL) {
-- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() out of memory\n");
-- new_errno = errno;
-- goto cleanup;
-- }
--
-- data->rfd = pipes[0];
-- data->wfd = pipes[1];
--
-- if (pthread_create(&data->thread, NULL, gg_resolver_pthread_thread, data)) {
-- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() unable to create thread\n");
-- new_errno = errno;
-- goto cleanup;
-- }
--
-- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() %p\n", data);
--
-- *fd = pipes[0];
-- *priv_data = data;
--
-- return 0;
--
--cleanup:
-- if (data != NULL)
-- free(data->hostname);
--
-- free(data);
--
-- close(pipes[0]);
-- close(pipes[1]);
--
-- errno = new_errno;
--
-- return -1;
--}
--
--#endif /* GG_CONFIG_HAVE_PTHREAD */
--
--/**
-- * Ustawia sposób rozwiązywania nazw w sesji.
-- *
-- * \param gs Struktura sesji
-- * \param type Sposób rozwiązywania nazw (patrz \ref build-resolver)
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--int gg_session_set_resolver(struct gg_session *gs, gg_resolver_t type)
--{
-- GG_SESSION_CHECK(gs, -1);
--
-- if (type == GG_RESOLVER_DEFAULT) {
-- if (gg_global_resolver_type != GG_RESOLVER_DEFAULT) {
-- gs->resolver_type = gg_global_resolver_type;
-- gs->resolver_start = gg_global_resolver_start;
-- gs->resolver_cleanup = gg_global_resolver_cleanup;
-- return 0;
-- }
--
--#if !defined(GG_CONFIG_HAVE_PTHREAD) || !defined(GG_CONFIG_PTHREAD_DEFAULT)
--# ifdef _WIN32
-- type = GG_RESOLVER_WIN32;
--# else
-- type = GG_RESOLVER_FORK;
--# endif
--#else
-- type = GG_RESOLVER_PTHREAD;
--#endif
-- }
--
-- switch (type) {
--#ifdef _WIN32
-- case GG_RESOLVER_WIN32:
-- gs->resolver_type = type;
-- gs->resolver_start = gg_resolve_win32thread;
-- gs->resolver_cleanup = gg_resolve_win32thread_cleanup;
-- return 0;
--#else
-- case GG_RESOLVER_FORK:
-- gs->resolver_type = type;
-- gs->resolver_start = gg_resolver_fork_start;
-- gs->resolver_cleanup = gg_resolver_fork_cleanup;
-- return 0;
--#endif
--
--#ifdef GG_CONFIG_HAVE_PTHREAD
-- case GG_RESOLVER_PTHREAD:
-- gs->resolver_type = type;
-- gs->resolver_start = gg_resolver_pthread_start;
-- gs->resolver_cleanup = gg_resolver_pthread_cleanup;
-- return 0;
--#endif
--
-- default:
-- errno = EINVAL;
-- return -1;
-- }
--}
--
--/**
-- * Zwraca sposób rozwiązywania nazw w sesji.
-- *
-- * \param gs Struktura sesji
-- *
-- * \return Sposób rozwiązywania nazw
-- */
--gg_resolver_t gg_session_get_resolver(struct gg_session *gs)
--{
-- GG_SESSION_CHECK(gs, (gg_resolver_t) -1);
--
-- return gs->resolver_type;
--}
--
--/**
-- * Ustawia własny sposób rozwiązywania nazw w sesji.
-- *
-- * \param gs Struktura sesji
-- * \param resolver_start Funkcja rozpoczynajÄ…ca rozwiÄ…zywanie nazwy
-- * \param resolver_cleanup Funkcja zwalniajÄ…ca zasoby
-- *
-- * Parametry funkcji rozpoczynającej rozwiązywanie nazwy wyglądają następująco:
-- * - \c "int *fd" &mdash; wskaźnik na zmienną, gdzie zostanie umieszczony deskryptor potoku
-- * - \c "void **priv_data" &mdash; wskaźnik na zmienną, gdzie można umieścić wskaźnik do prywatnych danych na potrzeby rozwiązywania nazwy
-- * - \c "const char *name" &mdash; nazwa serwera do rozwiÄ…zania
-- *
-- * Parametry funkcji zwalniającej zasoby wyglądają następująco:
-- * - \c "void **priv_data" &mdash; wskaźnik na zmienną przechowującą wskaźnik do prywatnych danych, należy go ustawić na \c NULL po zakończeniu
-- * - \c "int force" &mdash; flaga mówiąca o tym, że zasoby są zwalniane przed zakończeniem rozwiązywania nazwy, np. z powodu zamknięcia sesji.
-- *
-- * Własny kod rozwiązywania nazwy powinien stworzyć potok, parę gniazd lub
-- * inny deskryptor pozwalajÄ…cy na co najmniej jednostronnÄ… komunikacjÄ™ i
-- * przekazać go w parametrze \c fd. Po zakończeniu rozwiązywania nazwy,
-- * powinien wysłać otrzymany adres IP w postaci sieciowej (big-endian) do
-- * deskryptora. Jeśli rozwiązywanie nazwy się nie powiedzie, należy wysłać
-- * \c INADDR_NONE. Następnie zostanie wywołana funkcja zwalniająca zasoby
-- * z parametrem \c force równym \c 0. Gdyby sesja została zakończona przed
-- * rozwiÄ…zaniem nazwy, np. za pomocÄ… funkcji \c gg_logoff(), funkcja
-- * zwalniająca zasoby zostanie wywołana z parametrem \c force równym \c 1.
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--int gg_session_set_custom_resolver(struct gg_session *gs, int (*resolver_start)(int*, void**, const char*), void (*resolver_cleanup)(void**, int))
--{
-- GG_SESSION_CHECK(gs, -1);
--
-- if (resolver_start == NULL || resolver_cleanup == NULL) {
-- errno = EINVAL;
-- return -1;
-- }
--
-- gs->resolver_type = GG_RESOLVER_CUSTOM;
-- gs->resolver_start = resolver_start;
-- gs->resolver_cleanup = resolver_cleanup;
--
-- return 0;
--}
--
--/**
-- * Ustawia sposób rozwiązywania nazw połączenia HTTP.
-- *
-- * \param gh Struktura połączenia
-- * \param type Sposób rozwiązywania nazw (patrz \ref build-resolver)
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--int gg_http_set_resolver(struct gg_http *gh, gg_resolver_t type)
--{
-- if (gh == NULL) {
-- errno = EINVAL;
-- return -1;
-- }
--
-- if (type == GG_RESOLVER_DEFAULT) {
-- if (gg_global_resolver_type != GG_RESOLVER_DEFAULT) {
-- gh->resolver_type = gg_global_resolver_type;
-- gh->resolver_start = gg_global_resolver_start;
-- gh->resolver_cleanup = gg_global_resolver_cleanup;
-- return 0;
-- }
--
--#if !defined(GG_CONFIG_HAVE_PTHREAD) || !defined(GG_CONFIG_PTHREAD_DEFAULT)
--# ifdef _WIN32
-- type = GG_RESOLVER_WIN32;
--# else
-- type = GG_RESOLVER_FORK;
--# endif
--#else
-- type = GG_RESOLVER_PTHREAD;
--#endif
-- }
--
-- switch (type) {
--#ifdef _WIN32
-- case GG_RESOLVER_WIN32:
-- gh->resolver_type = type;
-- gh->resolver_start = gg_resolve_win32thread;
-- gh->resolver_cleanup = gg_resolve_win32thread_cleanup;
-- return 0;
--#else
-- case GG_RESOLVER_FORK:
-- gh->resolver_type = type;
-- gh->resolver_start = gg_resolver_fork_start;
-- gh->resolver_cleanup = gg_resolver_fork_cleanup;
-- return 0;
--#endif
--
--#ifdef GG_CONFIG_HAVE_PTHREAD
-- case GG_RESOLVER_PTHREAD:
-- gh->resolver_type = type;
-- gh->resolver_start = gg_resolver_pthread_start;
-- gh->resolver_cleanup = gg_resolver_pthread_cleanup;
-- return 0;
--#endif
--
-- default:
-- errno = EINVAL;
-- return -1;
-- }
--}
--
--/**
-- * Zwraca sposób rozwiązywania nazw połączenia HTTP.
-- *
-- * \param gh Struktura połączenia
-- *
-- * \return Sposób rozwiązywania nazw
-- */
--gg_resolver_t gg_http_get_resolver(struct gg_http *gh)
--{
-- if (gh == NULL) {
-- errno = EINVAL;
-- return GG_RESOLVER_INVALID;
-- }
--
-- return gh->resolver_type;
--}
--
--/**
-- * Ustawia własny sposób rozwiązywania nazw połączenia HTTP.
-- *
-- * \param gh Struktura sesji
-- * \param resolver_start Funkcja rozpoczynajÄ…ca rozwiÄ…zywanie nazwy
-- * \param resolver_cleanup Funkcja zwalniajÄ…ca zasoby
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--int gg_http_set_custom_resolver(struct gg_http *gh, int (*resolver_start)(int*, void**, const char*), void (*resolver_cleanup)(void**, int))
--{
-- if (gh == NULL || resolver_start == NULL || resolver_cleanup == NULL) {
-- errno = EINVAL;
-- return -1;
-- }
--
-- gh->resolver_type = GG_RESOLVER_CUSTOM;
-- gh->resolver_start = resolver_start;
-- gh->resolver_cleanup = resolver_cleanup;
--
-- return 0;
--}
--
--/**
-- * Ustawia sposób rozwiązywania nazw globalnie dla biblioteki.
-- *
-- * \param type Sposób rozwiązywania nazw (patrz \ref build-resolver)
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--int gg_global_set_resolver(gg_resolver_t type)
--{
-- switch (type) {
-- case GG_RESOLVER_DEFAULT:
-- gg_global_resolver_type = type;
-- gg_global_resolver_start = NULL;
-- gg_global_resolver_cleanup = NULL;
-- return 0;
--
--#ifdef _WIN32
-- case GG_RESOLVER_WIN32:
-- gg_global_resolver_type = type;
-- gg_global_resolver_start = gg_resolve_win32thread;
-- gg_global_resolver_cleanup = gg_resolve_win32thread_cleanup;
-- return 0;
--#else
-- case GG_RESOLVER_FORK:
-- gg_global_resolver_type = type;
-- gg_global_resolver_start = gg_resolver_fork_start;
-- gg_global_resolver_cleanup = gg_resolver_fork_cleanup;
-- return 0;
--#endif
--
--#ifdef GG_CONFIG_HAVE_PTHREAD
-- case GG_RESOLVER_PTHREAD:
-- gg_global_resolver_type = type;
-- gg_global_resolver_start = gg_resolver_pthread_start;
-- gg_global_resolver_cleanup = gg_resolver_pthread_cleanup;
-- return 0;
--#endif
--
-- default:
-- errno = EINVAL;
-- return -1;
-- }
--}
--
--/**
-- * Zwraca sposób rozwiązywania nazw globalnie dla biblioteki.
-- *
-- * \return Sposób rozwiązywania nazw
-- */
--gg_resolver_t gg_global_get_resolver(void)
--{
-- return gg_global_resolver_type;
--}
--
--/**
-- * Ustawia własny sposób rozwiązywania nazw globalnie dla biblioteki.
-- *
-- * \param resolver_start Funkcja rozpoczynajÄ…ca rozwiÄ…zywanie nazwy
-- * \param resolver_cleanup Funkcja zwalniajÄ…ca zasoby
-- *
-- * Patrz \ref gg_session_set_custom_resolver.
-- *
-- * \return 0 jeśli się powiodło, -1 w przypadku błędu
-- */
--int gg_global_set_custom_resolver(int (*resolver_start)(int*, void**, const char*), void (*resolver_cleanup)(void**, int))
--{
-- if (resolver_start == NULL || resolver_cleanup == NULL) {
-- errno = EINVAL;
-- return -1;
-- }
--
-- gg_global_resolver_type = GG_RESOLVER_CUSTOM;
-- gg_global_resolver_start = resolver_start;
-- gg_global_resolver_cleanup = resolver_cleanup;
--
-- return 0;
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/resolver.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/resolver.h
---- pidgin-2.10.7/libpurple/protocols/gg/lib/resolver.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/resolver.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,28 +0,0 @@
--/*
-- * (C) Copyright 2008 Wojtek Kaniewski <wojtekka@irc.pl>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--#ifndef LIBGADU_RESOLVER_H
--#define LIBGADU_RESOLVER_H
--
--#ifndef _WIN32
--# include <arpa/inet.h>
--#endif
--
--int gg_gethostbyname_real(const char *hostname, struct in_addr **result, int *count, int pthread);
--
--#endif /* LIBGADU_RESOLVER_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/session.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/session.h
---- pidgin-2.10.7/libpurple/protocols/gg/lib/session.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/session.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,70 +0,0 @@
--/*
-- * (C) Copyright 2008-2010 Wojtek Kaniewski <wojtekka@irc.pl>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--#ifndef LIBGADU_SESSION_H
--#define LIBGADU_SESSION_H
--
--#ifdef GG_CONFIG_HAVE_GNUTLS
--# include <gnutls/gnutls.h>
--#endif
--
--#define GG_SESSION_CHECK(gs, result) \
-- do { \
-- if ((gs) == NULL) { \
-- errno = EINVAL; \
-- return (result); \
-- } \
-- } while (0)
--
--#define GG_SESSION_CHECK_CONNECTED(gs, result) \
-- do { \
-- GG_SESSION_CHECK(gs, result); \
-- \
-- if (!GG_SESSION_IS_CONNECTED(gs)) { \
-- errno = ENOTCONN; \
-- return (result); \
-- } \
-- } while (0)
--
--#define GG_SESSION_IS_PROTOCOL_7_7(gs) ((gs)->protocol_version >= 0x2a)
--#define GG_SESSION_IS_PROTOCOL_8_0(gs) ((gs)->protocol_version >= 0x2d)
--
--#define GG_SESSION_IS_IDLE(gs) ((gs)->state == GG_STATE_IDLE)
--#define GG_SESSION_IS_CONNECTING(gs) ((gs)->state != GG_STATE_IDLE && (gs)->state != GG_STATE_CONNECTED)
--#define GG_SESSION_IS_CONNECTED(gs) ((gs)->state == GG_STATE_CONNECTED)
--
--#ifdef GG_CONFIG_HAVE_GNUTLS
--
--typedef struct {
-- gnutls_session_t session;
-- gnutls_certificate_credentials_t xcred;
--} gg_session_gnutls_t;
--
--#define GG_SESSION_GNUTLS(gs) ((gg_session_gnutls_t*) (gs)->ssl)->session
--
--#endif /* GG_CONFIG_HAVE_GNUTLS */
--
--#ifdef GG_CONFIG_HAVE_OPENSSL
--
--#define GG_SESSION_OPENSSL(gs) ((SSL*) (gs)->ssl)
--
--#endif /* GG_CONFIG_HAVE_OPENSSL */
--
--int gg_session_handle_packet(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge);
--
--#endif /* LIBGADU_SESSION_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/sha1.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/sha1.c
---- pidgin-2.10.7/libpurple/protocols/gg/lib/sha1.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/sha1.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,303 +0,0 @@
--/* $Id: sha1.c 1067 2011-03-15 18:57:16Z wojtekka $ */
--
--/*
-- * (C) Copyright 2007 Wojtek Kaniewski <wojtekka@irc.pl>
-- *
-- * Public domain SHA-1 implementation by Steve Reid <steve@edmweb.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU Lesser General Public License Version
-- * 2.1 as published by the Free Software Foundation.
-- *
-- * 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 Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this program; if not, write to the Free Software
-- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-- * USA.
-- */
--
--/**
-- * \file sha1.c
-- *
-- * \brief Funkcje wyznaczania skrótu SHA1
-- */
--
--#include <string.h>
--#include <sys/types.h>
--#include <unistd.h>
--
--#include "libgadu.h"
--
--/** \cond ignore */
--
--#ifdef GG_CONFIG_HAVE_OPENSSL
--
--#include <openssl/sha.h>
--
--#else
--
--/*
--SHA-1 in C
--By Steve Reid <steve@edmweb.com>
--100% Public Domain
--
--Modified by Wojtek Kaniewski <wojtekka@toxygen.net> for compatibility
--with libgadu and OpenSSL API.
--
--Test Vectors (from FIPS PUB 180-1)
--"abc"
-- A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
--"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-- 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
--A million repetitions of "a"
-- 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
--*/
--
--/* #define LITTLE_ENDIAN * This should be #define'd if true. */
--/* #define SHA1HANDSOFF * Copies data before messing with it. */
--
--#include <string.h>
--
--typedef struct {
-- uint32_t state[5];
-- uint32_t count[2];
-- unsigned char buffer[64];
--} SHA_CTX;
--
--static void SHA1_Transform(uint32_t state[5], const unsigned char buffer[64]);
--static void SHA1_Init(SHA_CTX* context);
--static void SHA1_Update(SHA_CTX* context, const unsigned char* data, unsigned int len);
--static void SHA1_Final(unsigned char digest[20], SHA_CTX* context);
--
--#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
--
--/* blk0() and blk() perform the initial expand. */
--/* I got the idea of expanding during the round function from SSLeay */
--#ifndef GG_CONFIG_BIGENDIAN
--#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
-- |(rol(block->l[i],8)&0x00FF00FF))
--#else
--#define blk0(i) block->l[i]
--#endif
--#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
-- ^block->l[(i+2)&15]^block->l[i&15],1))
--
--/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
--#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
--#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
--#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
--#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
--#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
--
--
--/* Hash a single 512-bit block. This is the core of the algorithm. */
--
--static void SHA1_Transform(uint32_t state[5], const unsigned char buffer[64])
--{
--uint32_t a, b, c, d, e;
--typedef union {
-- unsigned char c[64];
-- uint32_t l[16];
--} CHAR64LONG16;
--CHAR64LONG16* block;
--static unsigned char workspace[64];
-- block = (CHAR64LONG16*)workspace;
-- memcpy(block, buffer, 64);
-- /* Copy context->state[] to working vars */
-- a = state[0];
-- b = state[1];
-- c = state[2];
-- d = state[3];
-- e = state[4];
-- /* 4 rounds of 20 operations each. Loop unrolled. */
-- R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
-- R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
-- R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
-- R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
-- R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
-- R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
-- R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
-- R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
-- R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
-- R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
-- R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
-- R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
-- R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
-- R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
-- R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
-- R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
-- R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
-- R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
-- R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
-- R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-- /* Add the working vars back into context.state[] */
-- state[0] += a;
-- state[1] += b;
-- state[2] += c;
-- state[3] += d;
-- state[4] += e;
-- /* Wipe variables */
-- a = b = c = d = e = 0;
--}
--
--
--/* SHA1_Init - Initialize new context */
--
--static void SHA1_Init(SHA_CTX* context)
--{
-- /* SHA1 initialization constants */
-- context->state[0] = 0x67452301;
-- context->state[1] = 0xEFCDAB89;
-- context->state[2] = 0x98BADCFE;
-- context->state[3] = 0x10325476;
-- context->state[4] = 0xC3D2E1F0;
-- context->count[0] = context->count[1] = 0;
--}
--
--
--/* Run your data through this. */
--
--static void SHA1_Update(SHA_CTX* context, const unsigned char* data, unsigned int len)
--{
--unsigned int i, j;
--
-- j = (context->count[0] >> 3) & 63;
-- if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
-- context->count[1] += (len >> 29);
-- if ((j + len) > 63) {
-- memcpy(&context->buffer[j], data, (i = 64-j));
-- SHA1_Transform(context->state, context->buffer);
-- for ( ; i + 63 < len; i += 64) {
-- SHA1_Transform(context->state, &data[i]);
-- }
-- j = 0;
-- }
-- else i = 0;
-- memcpy(&context->buffer[j], &data[i], len - i);
--}
--
--
--/* Add padding and return the message digest. */
--
--static void SHA1_Final(unsigned char digest[20], SHA_CTX* context)
--{
--uint32_t i, j;
--unsigned char finalcount[8];
--
-- for (i = 0; i < 8; i++) {
-- finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
-- >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
-- }
-- SHA1_Update(context, (unsigned char *)"\200", 1);
-- while ((context->count[0] & 504) != 448) {
-- SHA1_Update(context, (unsigned char *)"\0", 1);
-- }
-- SHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */
-- for (i = 0; i < 20; i++) {
-- digest[i] = (unsigned char)
-- ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
-- }
-- /* Wipe variables */
-- i = j = 0;
-- memset(context->buffer, 0, 64);
-- memset(context->state, 0, 20);
-- memset(context->count, 0, 8);
-- memset(&finalcount, 0, 8);
--#ifdef SHA1HANDSOFF /* make SHA1_Transform overwrite it's own static vars */
-- SHA1_Transform(context->state, context->buffer);
--#endif
--}
--
--#endif /* GG_CONFIG_HAVE_OPENSSL */
--
--/** \endcond */
--
--/** \cond internal */
--
--/**
-- * \internal Liczy skrót SHA1 z ziarna i hasła.
-- *
-- * \param password Hasło
-- * \param seed Ziarno
-- * \param result Bufor na wynik funkcji skrĂłtu (20 bajtĂłw)
-- */
--void gg_login_hash_sha1(const char *password, uint32_t seed, uint8_t *result)
--{
-- SHA_CTX ctx;
--
-- SHA1_Init(&ctx);
-- SHA1_Update(&ctx, (const unsigned char*) password, strlen(password));
-- seed = gg_fix32(seed);
-- SHA1_Update(&ctx, (uint8_t*) &seed, 4);
--
-- SHA1_Final(result, &ctx);
--}
--
--/**
-- * \internal Liczy skrĂłt SHA1 z pliku.
-- *
-- * \param fd Deskryptor pliku
-- * \param result WskaĹşnik na skrĂłt
-- *
-- * \return 0 lub -1
-- */
--int gg_file_hash_sha1(int fd, uint8_t *result)
--{
-- unsigned char buf[4096];
-- SHA_CTX ctx;
-- off_t pos, len;
-- int res;
--
-- if ((pos = lseek(fd, 0, SEEK_CUR)) == (off_t) -1)
-- return -1;
--
-- if ((len = lseek(fd, 0, SEEK_END)) == (off_t) -1)
-- return -1;
--
-- if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
-- return -1;
--
-- SHA1_Init(&ctx);
--
-- if (len <= 10485760) {
-- while ((res = read(fd, buf, sizeof(buf))) > 0)
-- SHA1_Update(&ctx, buf, res);
-- } else {
-- int i;
--
-- for (i = 0; i < 9; i++) {
-- int j;
--
-- if (lseek(fd, (len - 1048576) / 9 * i, SEEK_SET) == (off_t) - 1)
-- return -1;
--
-- for (j = 0; j < 1048576 / sizeof(buf); j++) {
-- if ((res = read(fd, buf, sizeof(buf))) != sizeof(buf)) {
-- res = -1;
-- break;
-- }
--
-- SHA1_Update(&ctx, buf, res);
-- }
--
-- if (res == -1)
-- break;
-- }
-- }
--
-- if (res == -1)
-- return -1;
--
-- SHA1_Final(result, &ctx);
--
-- if (lseek(fd, pos, SEEK_SET) == (off_t) -1)
-- return -1;
--
-- return 0;
--}
--
--/** \endcond */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/gg/Makefile.am
---- pidgin-2.10.7/libpurple/protocols/gg/Makefile.am 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/Makefile.am 1969-12-31 21:00:00.000000000 -0300
-@@ -1,111 +0,0 @@
--EXTRA_DIST = \
-- Makefile.mingw \
-- lib/common.c \
-- lib/compat.h \
-- lib/COPYING \
-- lib/dcc.c \
-- lib/dcc7.c \
-- lib/debug.c \
-- lib/deflate.c \
-- lib/deflate.h \
-- lib/encoding.c \
-- lib/encoding.h \
-- lib/events.c \
-- lib/handlers.c \
-- lib/http.c \
-- lib/libgadu.h \
-- lib/libgadu.c \
-- lib/libgadu-config.h \
-- lib/libgadu-debug.h \
-- lib/libgadu-internal.h \
-- lib/message.c \
-- lib/message.h \
-- lib/obsolete.c \
-- lib/protocol.h \
-- lib/pubdir.c \
-- lib/pubdir50.c \
-- lib/resolver.c \
-- lib/resolver.h \
-- lib/session.h \
-- lib/sha1.c
--
--pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
--
--if USE_INTERNAL_LIBGADU
--INTGGSOURCES = \
-- lib/common.c \
-- lib/compat.h \
-- lib/dcc.c \
-- lib/dcc7.c \
-- lib/debug.c \
-- lib/deflate.c \
-- lib/deflate.h \
-- lib/encoding.c \
-- lib/encoding.h \
-- lib/events.c \
-- lib/handlers.c \
-- lib/http.c \
-- lib/libgadu.h \
-- lib/libgadu.c \
-- lib/libgadu-config.h \
-- lib/libgadu-internal.h \
-- lib/message.c \
-- lib/message.h \
-- lib/obsolete.c \
-- lib/protocol.h \
-- lib/pubdir.c \
-- lib/pubdir50.c \
-- lib/resolver.c \
-- lib/resolver.h \
-- lib/session.h \
-- lib/sha1.c
--
--INTGG_CFLAGS = -I$(top_srcdir)/libpurple/protocols/gg/lib -DGG_IGNORE_DEPRECATED -DUSE_INTERNAL_LIBGADU
--endif
--
--if USE_GNUTLS
--GADU_LIBS += $(GNUTLS_LIBS)
--GADU_CFLAGS += $(GNUTLS_CFLAGS)
--endif
--
--GGSOURCES = \
-- $(INTGGSOURCES) \
-- gg-utils.h \
-- gg-utils.c \
-- confer.h \
-- confer.c \
-- search.h \
-- search.c \
-- buddylist.h \
-- buddylist.c \
-- gg.h \
-- gg.c
--
--AM_CFLAGS = $(st)
--
--libgg_la_LDFLAGS = -module -avoid-version
--
--if STATIC_GG
--
--st = -DPURPLE_STATIC_PRPL $(GADU_CFLAGS)
--noinst_LTLIBRARIES = libgg.la
--libgg_la_SOURCES = $(GGSOURCES)
--libgg_la_CFLAGS = $(AM_CFLAGS)
--libgg_la_LIBADD = $(GADU_LIBS)
--
--else
--
--st = $(GADU_CFLAGS)
--pkg_LTLIBRARIES = libgg.la
--libgg_la_SOURCES = $(GGSOURCES)
--libgg_la_LIBADD = $(GLIB_LIBS) $(GADU_LIBS)
--
--endif
--
--AM_CPPFLAGS = \
-- -I$(top_srcdir)/libpurple \
-- -I$(top_builddir)/libpurple \
-- $(INTGG_CFLAGS) \
-- $(GLIB_CFLAGS) \
-- $(DEBUG_CFLAGS)
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/gg/Makefile.in
---- pidgin-2.10.7/libpurple/protocols/gg/Makefile.in 2013-02-11 07:17:20.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/Makefile.in 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1007 +0,0 @@
--# Makefile.in generated by automake 1.11.6 from Makefile.am.
--# @configure_input@
--
--# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
--# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
--# Foundation, Inc.
--# This Makefile.in is free software; the Free Software Foundation
--# gives unlimited permission to copy and/or distribute it,
--# with or without modifications, as long as this notice is preserved.
--
--# This program is distributed in the hope that it will be useful,
--# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
--# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
--# PARTICULAR PURPOSE.
--
--@SET_MAKE@
--
--VPATH = @srcdir@
--am__make_dryrun = \
-- { \
-- am__dry=no; \
-- case $$MAKEFLAGS in \
-- *\\[\ \ ]*) \
-- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
-- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
-- *) \
-- for am__flg in $$MAKEFLAGS; do \
-- case $$am__flg in \
-- *=*|--*) ;; \
-- *n*) am__dry=yes; break;; \
-- esac; \
-- done;; \
-- esac; \
-- test $$am__dry = yes; \
-- }
--pkgdatadir = $(datadir)/@PACKAGE@
--pkgincludedir = $(includedir)/@PACKAGE@
--pkglibdir = $(libdir)/@PACKAGE@
--pkglibexecdir = $(libexecdir)/@PACKAGE@
--am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
--install_sh_DATA = $(install_sh) -c -m 644
--install_sh_PROGRAM = $(install_sh) -c
--install_sh_SCRIPT = $(install_sh) -c
--INSTALL_HEADER = $(INSTALL_DATA)
--transform = $(program_transform_name)
--NORMAL_INSTALL = :
--PRE_INSTALL = :
--POST_INSTALL = :
--NORMAL_UNINSTALL = :
--PRE_UNINSTALL = :
--POST_UNINSTALL = :
--build_triplet = @build@
--host_triplet = @host@
--@USE_GNUTLS_TRUE@am__append_1 = $(GNUTLS_LIBS)
--@USE_GNUTLS_TRUE@am__append_2 = $(GNUTLS_CFLAGS)
--subdir = libpurple/protocols/gg
--DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
--ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
--am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
-- $(top_srcdir)/configure.ac
--am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-- $(ACLOCAL_M4)
--mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
--CONFIG_HEADER = $(top_builddir)/config.h
--CONFIG_CLEAN_FILES =
--CONFIG_CLEAN_VPATH_FILES =
--am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
--am__vpath_adj = case $$p in \
-- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
-- *) f=$$p;; \
-- esac;
--am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
--am__install_max = 40
--am__nobase_strip_setup = \
-- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
--am__nobase_strip = \
-- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
--am__nobase_list = $(am__nobase_strip_setup); \
-- for p in $$list; do echo "$$p $$p"; done | \
-- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
-- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
-- if (++n[$$2] == $(am__install_max)) \
-- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
-- END { for (dir in files) print dir, files[dir] }'
--am__base_list = \
-- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
-- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
--am__uninstall_files_from_dir = { \
-- test -z "$$files" \
-- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
-- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
-- $(am__cd) "$$dir" && rm -f $$files; }; \
-- }
--am__installdirs = "$(DESTDIR)$(pkgdir)"
--LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkg_LTLIBRARIES)
--am__DEPENDENCIES_1 =
--@USE_GNUTLS_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
--am__DEPENDENCIES_3 = $(am__DEPENDENCIES_2)
--@STATIC_GG_FALSE@libgg_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
--@STATIC_GG_FALSE@ $(am__DEPENDENCIES_3)
--@STATIC_GG_TRUE@libgg_la_DEPENDENCIES = $(am__DEPENDENCIES_3)
--am__libgg_la_SOURCES_DIST = lib/common.c lib/compat.h lib/dcc.c \
-- lib/dcc7.c lib/debug.c lib/deflate.c lib/deflate.h \
-- lib/encoding.c lib/encoding.h lib/events.c lib/handlers.c \
-- lib/http.c lib/libgadu.h lib/libgadu.c lib/libgadu-config.h \
-- lib/libgadu-internal.h lib/message.c lib/message.h \
-- lib/obsolete.c lib/protocol.h lib/pubdir.c lib/pubdir50.c \
-- lib/resolver.c lib/resolver.h lib/session.h lib/sha1.c \
-- gg-utils.h gg-utils.c confer.h confer.c search.h search.c \
-- buddylist.h buddylist.c gg.h gg.c
--@USE_INTERNAL_LIBGADU_TRUE@am__objects_1 = libgg_la-common.lo \
--@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-dcc.lo libgg_la-dcc7.lo \
--@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-debug.lo \
--@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-deflate.lo \
--@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-encoding.lo \
--@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-events.lo \
--@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-handlers.lo \
--@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-http.lo \
--@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-libgadu.lo \
--@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-message.lo \
--@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-obsolete.lo \
--@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-pubdir.lo \
--@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-pubdir50.lo \
--@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-resolver.lo \
--@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-sha1.lo
--am__objects_2 = $(am__objects_1) libgg_la-gg-utils.lo \
-- libgg_la-confer.lo libgg_la-search.lo libgg_la-buddylist.lo \
-- libgg_la-gg.lo
--@STATIC_GG_FALSE@am_libgg_la_OBJECTS = $(am__objects_2)
--@STATIC_GG_TRUE@am_libgg_la_OBJECTS = $(am__objects_2)
--libgg_la_OBJECTS = $(am_libgg_la_OBJECTS)
--AM_V_lt = $(am__v_lt_@AM_V@)
--am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
--am__v_lt_0 = --silent
--libgg_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libgg_la_CFLAGS) \
-- $(CFLAGS) $(libgg_la_LDFLAGS) $(LDFLAGS) -o $@
--@STATIC_GG_FALSE@am_libgg_la_rpath = -rpath $(pkgdir)
--@STATIC_GG_TRUE@am_libgg_la_rpath =
--DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
--depcomp = $(SHELL) $(top_srcdir)/depcomp
--am__depfiles_maybe = depfiles
--am__mv = mv -f
--COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
--LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-- $(AM_CFLAGS) $(CFLAGS)
--AM_V_CC = $(am__v_CC_@AM_V@)
--am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
--am__v_CC_0 = @echo " CC " $@;
--AM_V_at = $(am__v_at_@AM_V@)
--am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
--am__v_at_0 = @
--CCLD = $(CC)
--LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-- $(AM_LDFLAGS) $(LDFLAGS) -o $@
--AM_V_CCLD = $(am__v_CCLD_@AM_V@)
--am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
--am__v_CCLD_0 = @echo " CCLD " $@;
--AM_V_GEN = $(am__v_GEN_@AM_V@)
--am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
--am__v_GEN_0 = @echo " GEN " $@;
--SOURCES = $(libgg_la_SOURCES)
--DIST_SOURCES = $(am__libgg_la_SOURCES_DIST)
--am__can_run_installinfo = \
-- case $$AM_UPDATE_INFO_DIR in \
-- n|no|NO) false;; \
-- *) (install-info --version) >/dev/null 2>&1;; \
-- esac
--ETAGS = etags
--CTAGS = ctags
--DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
--ACLOCAL = @ACLOCAL@
--ALLOCA = @ALLOCA@
--ALL_LINGUAS = @ALL_LINGUAS@
--AMTAR = @AMTAR@
--AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
--AR = @AR@
--AUTOCONF = @AUTOCONF@
--AUTOHEADER = @AUTOHEADER@
--AUTOMAKE = @AUTOMAKE@
--AVAHI_CFLAGS = @AVAHI_CFLAGS@
--AVAHI_LIBS = @AVAHI_LIBS@
--AWK = @AWK@
--CATALOGS = @CATALOGS@
--CATOBJEXT = @CATOBJEXT@
--CC = @CC@
--CCDEPMODE = @CCDEPMODE@
--CFLAGS = @CFLAGS@
--CHECK_CFLAGS = @CHECK_CFLAGS@
--CHECK_LIBS = @CHECK_LIBS@
--CPP = @CPP@
--CPPFLAGS = @CPPFLAGS@
--CYGPATH_W = @CYGPATH_W@
--DATADIRNAME = @DATADIRNAME@
--DBUS_CFLAGS = @DBUS_CFLAGS@
--DBUS_LIBS = @DBUS_LIBS@
--DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
--DEBUG_CFLAGS = @DEBUG_CFLAGS@
--DEFS = @DEFS@
--DEPDIR = @DEPDIR@
--DLLTOOL = @DLLTOOL@
--DOT = @DOT@
--DOXYGEN = @DOXYGEN@
--DSYMUTIL = @DSYMUTIL@
--DUMPBIN = @DUMPBIN@
--DYNALOADER_A = @DYNALOADER_A@
--DYNAMIC_PRPLS = @DYNAMIC_PRPLS@
--ECHO_C = @ECHO_C@
--ECHO_N = @ECHO_N@
--ECHO_T = @ECHO_T@
--EGREP = @EGREP@
--EVOLUTION_ADDRESSBOOK_CFLAGS = @EVOLUTION_ADDRESSBOOK_CFLAGS@
--EVOLUTION_ADDRESSBOOK_LIBS = @EVOLUTION_ADDRESSBOOK_LIBS@
--EXEEXT = @EXEEXT@
--FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
--FARSTREAM_LIBS = @FARSTREAM_LIBS@
--FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@ $(am__append_2)
--GADU_LIBS = @GADU_LIBS@ $(am__append_1)
--GCONFTOOL = @GCONFTOOL@
--GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
--GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
--GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
--GLIB_CFLAGS = @GLIB_CFLAGS@
--GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
--GLIB_LIBS = @GLIB_LIBS@
--GMOFILES = @GMOFILES@
--GMSGFMT = @GMSGFMT@
--GNT_CFLAGS = @GNT_CFLAGS@
--GNT_LIBS = @GNT_LIBS@
--GNT_LT_VERSION_INFO = @GNT_LT_VERSION_INFO@
--GNT_MAJOR_VERSION = @GNT_MAJOR_VERSION@
--GNT_MICRO_VERSION = @GNT_MICRO_VERSION@
--GNT_MINOR_VERSION = @GNT_MINOR_VERSION@
--GNT_VERSION = @GNT_VERSION@
--GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
--GNUTLS_LIBS = @GNUTLS_LIBS@
--GREP = @GREP@
--GSTINTERFACES_CFLAGS = @GSTINTERFACES_CFLAGS@
--GSTINTERFACES_LIBS = @GSTINTERFACES_LIBS@
--GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
--GSTREAMER_LIBS = @GSTREAMER_LIBS@
--GTKSPELL_CFLAGS = @GTKSPELL_CFLAGS@
--GTKSPELL_LIBS = @GTKSPELL_LIBS@
--GTK_CFLAGS = @GTK_CFLAGS@
--GTK_LIBS = @GTK_LIBS@
--IDN_CFLAGS = @IDN_CFLAGS@
--IDN_LIBS = @IDN_LIBS@
--INSTALL = @INSTALL@
--INSTALL_DATA = @INSTALL_DATA@
--INSTALL_PROGRAM = @INSTALL_PROGRAM@
--INSTALL_SCRIPT = @INSTALL_SCRIPT@
--INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
--INSTOBJEXT = @INSTOBJEXT@
--INTLLIBS = @INTLLIBS@
--INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
--INTLTOOL_MERGE = @INTLTOOL_MERGE@
--INTLTOOL_PERL = @INTLTOOL_PERL@
--INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
--INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
--INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
--INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
--INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
--KRB4_CFLAGS = @KRB4_CFLAGS@
--KRB4_LDFLAGS = @KRB4_LDFLAGS@
--KRB4_LIBS = @KRB4_LIBS@
--LD = @LD@
--LDADD = @LDADD@
--LDFLAGS = @LDFLAGS@
--LIBOBJS = @LIBOBJS@
--LIBPERL_A = @LIBPERL_A@
--LIBS = @LIBS@
--LIBTOOL = @LIBTOOL@
--LIBXML_CFLAGS = @LIBXML_CFLAGS@
--LIBXML_LIBS = @LIBXML_LIBS@
--LIPO = @LIPO@
--LN_S = @LN_S@
--LTLIBOBJS = @LTLIBOBJS@
--MAKEINFO = @MAKEINFO@
--MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
--MKDIR_P = @MKDIR_P@
--MKINSTALLDIRS = @MKINSTALLDIRS@
--MONO_CFLAGS = @MONO_CFLAGS@
--MONO_LIBS = @MONO_LIBS@
--MSGFMT = @MSGFMT@
--MSGFMT_OPTS = @MSGFMT_OPTS@
--MSGMERGE = @MSGMERGE@
--NETWORKMANAGER_CFLAGS = @NETWORKMANAGER_CFLAGS@
--NETWORKMANAGER_LIBS = @NETWORKMANAGER_LIBS@
--NM = @NM@
--NMEDIT = @NMEDIT@
--NSS_CFLAGS = @NSS_CFLAGS@
--NSS_LIBS = @NSS_LIBS@
--OBJDUMP = @OBJDUMP@
--OBJEXT = @OBJEXT@
--OTOOL = @OTOOL@
--OTOOL64 = @OTOOL64@
--PACKAGE = @PACKAGE@
--PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
--PACKAGE_NAME = @PACKAGE_NAME@
--PACKAGE_STRING = @PACKAGE_STRING@
--PACKAGE_TARNAME = @PACKAGE_TARNAME@
--PACKAGE_URL = @PACKAGE_URL@
--PACKAGE_VERSION = @PACKAGE_VERSION@
--PANGO_CFLAGS = @PANGO_CFLAGS@
--PANGO_LIBS = @PANGO_LIBS@
--PATH_SEPARATOR = @PATH_SEPARATOR@
--PERL = @PERL@
--PERL_CFLAGS = @PERL_CFLAGS@
--PERL_LIBS = @PERL_LIBS@
--PKG_CONFIG = @PKG_CONFIG@
--PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
--PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
--PLUGINS_DEFINE = @PLUGINS_DEFINE@
--POFILES = @POFILES@
--POSUB = @POSUB@
--PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
--PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
--PURPLE_LT_VERSION_INFO = @PURPLE_LT_VERSION_INFO@
--PURPLE_MAJOR_VERSION = @PURPLE_MAJOR_VERSION@
--PURPLE_MICRO_VERSION = @PURPLE_MICRO_VERSION@
--PURPLE_MINOR_VERSION = @PURPLE_MINOR_VERSION@
--PURPLE_VERSION = @PURPLE_VERSION@
--PYTHON = @PYTHON@
--PY_CFLAGS = @PY_CFLAGS@
--PY_LIBS = @PY_LIBS@
--RANLIB = @RANLIB@
--SASL_LIBS = @SASL_LIBS@
--SED = @SED@
--SET_MAKE = @SET_MAKE@
--SHELL = @SHELL@
--SILC_CFLAGS = @SILC_CFLAGS@
--SILC_LIBS = @SILC_LIBS@
--SM_LIBS = @SM_LIBS@
--SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
--SQLITE3_LIBS = @SQLITE3_LIBS@
--SSL_CERTIFICATES_DIR = @SSL_CERTIFICATES_DIR@
--STATIC_LINK_LIBS = @STATIC_LINK_LIBS@
--STATIC_PRPLS = @STATIC_PRPLS@
--STRIP = @STRIP@
--TCL_CFLAGS = @TCL_CFLAGS@
--TCL_LIBS = @TCL_LIBS@
--TK_LIBS = @TK_LIBS@
--USE_NLS = @USE_NLS@
--VERSION = @VERSION@
--X11_CFLAGS = @X11_CFLAGS@
--X11_LIBS = @X11_LIBS@
--XGETTEXT = @XGETTEXT@
--XMKMF = @XMKMF@
--XSLTPROC = @XSLTPROC@
--XSS_LIBS = @XSS_LIBS@
--X_CFLAGS = @X_CFLAGS@
--X_EXTRA_LIBS = @X_EXTRA_LIBS@
--X_LIBS = @X_LIBS@
--X_PRE_LIBS = @X_PRE_LIBS@
--ZEPHYR_CFLAGS = @ZEPHYR_CFLAGS@
--ZEPHYR_LDFLAGS = @ZEPHYR_LDFLAGS@
--ZEPHYR_LIBS = @ZEPHYR_LIBS@
--abs_builddir = @abs_builddir@
--abs_srcdir = @abs_srcdir@
--abs_top_builddir = @abs_top_builddir@
--abs_top_srcdir = @abs_top_srcdir@
--ac_ct_AR = @ac_ct_AR@
--ac_ct_CC = @ac_ct_CC@
--ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
--am__include = @am__include@
--am__leading_dot = @am__leading_dot@
--am__quote = @am__quote@
--am__tar = @am__tar@
--am__untar = @am__untar@
--bindir = @bindir@
--build = @build@
--build_alias = @build_alias@
--build_cpu = @build_cpu@
--build_os = @build_os@
--build_vendor = @build_vendor@
--builddir = @builddir@
--datadir = @datadir@
--datarootdir = @datarootdir@
--docdir = @docdir@
--dvidir = @dvidir@
--enable_dbus = @enable_dbus@
--enable_devhelp = @enable_devhelp@
--enable_dot = @enable_dot@
--enable_doxygen = @enable_doxygen@
--exec_prefix = @exec_prefix@
--host = @host@
--host_alias = @host_alias@
--host_cpu = @host_cpu@
--host_os = @host_os@
--host_vendor = @host_vendor@
--htmldir = @htmldir@
--includedir = @includedir@
--infodir = @infodir@
--install_sh = @install_sh@
--intltool__v_merge_options_ = @intltool__v_merge_options_@
--intltool__v_merge_options_0 = @intltool__v_merge_options_0@
--libdir = @libdir@
--libexecdir = @libexecdir@
--localedir = @localedir@
--localstatedir = @localstatedir@
--mandir = @mandir@
--mkdir_p = @mkdir_p@
--oldincludedir = @oldincludedir@
--pdfdir = @pdfdir@
--perlpath = @perlpath@
--pidginpath = @pidginpath@
--prefix = @prefix@
--program_transform_name = @program_transform_name@
--psdir = @psdir@
--sbindir = @sbindir@
--sedpath = @sedpath@
--sharedstatedir = @sharedstatedir@
--srcdir = @srcdir@
--sysconfdir = @sysconfdir@
--target_alias = @target_alias@
--top_build_prefix = @top_build_prefix@
--top_builddir = @top_builddir@
--top_srcdir = @top_srcdir@
--EXTRA_DIST = \
-- Makefile.mingw \
-- lib/common.c \
-- lib/compat.h \
-- lib/COPYING \
-- lib/dcc.c \
-- lib/dcc7.c \
-- lib/debug.c \
-- lib/deflate.c \
-- lib/deflate.h \
-- lib/encoding.c \
-- lib/encoding.h \
-- lib/events.c \
-- lib/handlers.c \
-- lib/http.c \
-- lib/libgadu.h \
-- lib/libgadu.c \
-- lib/libgadu-config.h \
-- lib/libgadu-debug.h \
-- lib/libgadu-internal.h \
-- lib/message.c \
-- lib/message.h \
-- lib/obsolete.c \
-- lib/protocol.h \
-- lib/pubdir.c \
-- lib/pubdir50.c \
-- lib/resolver.c \
-- lib/resolver.h \
-- lib/session.h \
-- lib/sha1.c
--
--pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
--@USE_INTERNAL_LIBGADU_TRUE@INTGGSOURCES = \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/common.c \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/compat.h \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/dcc.c \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/dcc7.c \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/debug.c \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/deflate.c \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/deflate.h \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/encoding.c \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/encoding.h \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/events.c \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/handlers.c \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/http.c \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/libgadu.h \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/libgadu.c \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/libgadu-config.h \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/libgadu-internal.h \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/message.c \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/message.h \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/obsolete.c \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/protocol.h \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/pubdir.c \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/pubdir50.c \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/resolver.c \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/resolver.h \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/session.h \
--@USE_INTERNAL_LIBGADU_TRUE@ lib/sha1.c
--
--@USE_INTERNAL_LIBGADU_TRUE@INTGG_CFLAGS = -I$(top_srcdir)/libpurple/protocols/gg/lib -DGG_IGNORE_DEPRECATED -DUSE_INTERNAL_LIBGADU
--GGSOURCES = \
-- $(INTGGSOURCES) \
-- gg-utils.h \
-- gg-utils.c \
-- confer.h \
-- confer.c \
-- search.h \
-- search.c \
-- buddylist.h \
-- buddylist.c \
-- gg.h \
-- gg.c
--
--AM_CFLAGS = $(st)
--libgg_la_LDFLAGS = -module -avoid-version
--@STATIC_GG_FALSE@st = $(GADU_CFLAGS)
--@STATIC_GG_TRUE@st = -DPURPLE_STATIC_PRPL $(GADU_CFLAGS)
--@STATIC_GG_TRUE@noinst_LTLIBRARIES = libgg.la
--@STATIC_GG_FALSE@libgg_la_SOURCES = $(GGSOURCES)
--@STATIC_GG_TRUE@libgg_la_SOURCES = $(GGSOURCES)
--@STATIC_GG_TRUE@libgg_la_CFLAGS = $(AM_CFLAGS)
--@STATIC_GG_FALSE@libgg_la_LIBADD = $(GLIB_LIBS) $(GADU_LIBS)
--@STATIC_GG_TRUE@libgg_la_LIBADD = $(GADU_LIBS)
--@STATIC_GG_FALSE@pkg_LTLIBRARIES = libgg.la
--AM_CPPFLAGS = \
-- -I$(top_srcdir)/libpurple \
-- -I$(top_builddir)/libpurple \
-- $(INTGG_CFLAGS) \
-- $(GLIB_CFLAGS) \
-- $(DEBUG_CFLAGS)
--
--all: all-am
--
--.SUFFIXES:
--.SUFFIXES: .c .lo .o .obj
--$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
-- @for dep in $?; do \
-- case '$(am__configure_deps)' in \
-- *$$dep*) \
-- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
-- && { if test -f $@; then exit 0; else break; fi; }; \
-- exit 1;; \
-- esac; \
-- done; \
-- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpurple/protocols/gg/Makefile'; \
-- $(am__cd) $(top_srcdir) && \
-- $(AUTOMAKE) --gnu libpurple/protocols/gg/Makefile
--.PRECIOUS: Makefile
--Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-- @case '$?' in \
-- *config.status*) \
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-- *) \
-- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-- esac;
--
--$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--
--$(top_srcdir)/configure: $(am__configure_deps)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--$(ACLOCAL_M4): $(am__aclocal_m4_deps)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--$(am__aclocal_m4_deps):
--
--clean-noinstLTLIBRARIES:
-- -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-- @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
-- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-- test "$$dir" != "$$p" || dir=.; \
-- echo "rm -f \"$${dir}/so_locations\""; \
-- rm -f "$${dir}/so_locations"; \
-- done
--install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES)
-- @$(NORMAL_INSTALL)
-- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
-- list2=; for p in $$list; do \
-- if test -f $$p; then \
-- list2="$$list2 $$p"; \
-- else :; fi; \
-- done; \
-- test -z "$$list2" || { \
-- echo " $(MKDIR_P) '$(DESTDIR)$(pkgdir)'"; \
-- $(MKDIR_P) "$(DESTDIR)$(pkgdir)" || exit 1; \
-- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgdir)'"; \
-- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgdir)"; \
-- }
--
--uninstall-pkgLTLIBRARIES:
-- @$(NORMAL_UNINSTALL)
-- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
-- for p in $$list; do \
-- $(am__strip_dir) \
-- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgdir)/$$f'"; \
-- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgdir)/$$f"; \
-- done
--
--clean-pkgLTLIBRARIES:
-- -test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES)
-- @list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
-- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-- test "$$dir" != "$$p" || dir=.; \
-- echo "rm -f \"$${dir}/so_locations\""; \
-- rm -f "$${dir}/so_locations"; \
-- done
--libgg.la: $(libgg_la_OBJECTS) $(libgg_la_DEPENDENCIES) $(EXTRA_libgg_la_DEPENDENCIES)
-- $(AM_V_CCLD)$(libgg_la_LINK) $(am_libgg_la_rpath) $(libgg_la_OBJECTS) $(libgg_la_LIBADD) $(LIBS)
--
--mostlyclean-compile:
-- -rm -f *.$(OBJEXT)
--
--distclean-compile:
-- -rm -f *.tab.c
--
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-buddylist.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-common.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-confer.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-dcc.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-dcc7.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-debug.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-deflate.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-encoding.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-events.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-gg-utils.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-gg.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-handlers.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-http.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-libgadu.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-message.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-obsolete.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-pubdir.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-pubdir50.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-resolver.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-search.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-sha1.Plo@am__quote@
--
--.c.o:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
--
--.c.obj:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
--
--.c.lo:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
--
--libgg_la-common.lo: lib/common.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-common.lo -MD -MP -MF $(DEPDIR)/libgg_la-common.Tpo -c -o libgg_la-common.lo `test -f 'lib/common.c' || echo '$(srcdir)/'`lib/common.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-common.Tpo $(DEPDIR)/libgg_la-common.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/common.c' object='libgg_la-common.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-common.lo `test -f 'lib/common.c' || echo '$(srcdir)/'`lib/common.c
--
--libgg_la-dcc.lo: lib/dcc.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-dcc.lo -MD -MP -MF $(DEPDIR)/libgg_la-dcc.Tpo -c -o libgg_la-dcc.lo `test -f 'lib/dcc.c' || echo '$(srcdir)/'`lib/dcc.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-dcc.Tpo $(DEPDIR)/libgg_la-dcc.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/dcc.c' object='libgg_la-dcc.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-dcc.lo `test -f 'lib/dcc.c' || echo '$(srcdir)/'`lib/dcc.c
--
--libgg_la-dcc7.lo: lib/dcc7.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-dcc7.lo -MD -MP -MF $(DEPDIR)/libgg_la-dcc7.Tpo -c -o libgg_la-dcc7.lo `test -f 'lib/dcc7.c' || echo '$(srcdir)/'`lib/dcc7.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-dcc7.Tpo $(DEPDIR)/libgg_la-dcc7.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/dcc7.c' object='libgg_la-dcc7.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-dcc7.lo `test -f 'lib/dcc7.c' || echo '$(srcdir)/'`lib/dcc7.c
--
--libgg_la-debug.lo: lib/debug.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-debug.lo -MD -MP -MF $(DEPDIR)/libgg_la-debug.Tpo -c -o libgg_la-debug.lo `test -f 'lib/debug.c' || echo '$(srcdir)/'`lib/debug.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-debug.Tpo $(DEPDIR)/libgg_la-debug.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/debug.c' object='libgg_la-debug.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-debug.lo `test -f 'lib/debug.c' || echo '$(srcdir)/'`lib/debug.c
--
--libgg_la-deflate.lo: lib/deflate.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-deflate.lo -MD -MP -MF $(DEPDIR)/libgg_la-deflate.Tpo -c -o libgg_la-deflate.lo `test -f 'lib/deflate.c' || echo '$(srcdir)/'`lib/deflate.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-deflate.Tpo $(DEPDIR)/libgg_la-deflate.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/deflate.c' object='libgg_la-deflate.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-deflate.lo `test -f 'lib/deflate.c' || echo '$(srcdir)/'`lib/deflate.c
--
--libgg_la-encoding.lo: lib/encoding.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-encoding.lo -MD -MP -MF $(DEPDIR)/libgg_la-encoding.Tpo -c -o libgg_la-encoding.lo `test -f 'lib/encoding.c' || echo '$(srcdir)/'`lib/encoding.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-encoding.Tpo $(DEPDIR)/libgg_la-encoding.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/encoding.c' object='libgg_la-encoding.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-encoding.lo `test -f 'lib/encoding.c' || echo '$(srcdir)/'`lib/encoding.c
--
--libgg_la-events.lo: lib/events.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-events.lo -MD -MP -MF $(DEPDIR)/libgg_la-events.Tpo -c -o libgg_la-events.lo `test -f 'lib/events.c' || echo '$(srcdir)/'`lib/events.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-events.Tpo $(DEPDIR)/libgg_la-events.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/events.c' object='libgg_la-events.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-events.lo `test -f 'lib/events.c' || echo '$(srcdir)/'`lib/events.c
--
--libgg_la-handlers.lo: lib/handlers.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-handlers.lo -MD -MP -MF $(DEPDIR)/libgg_la-handlers.Tpo -c -o libgg_la-handlers.lo `test -f 'lib/handlers.c' || echo '$(srcdir)/'`lib/handlers.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-handlers.Tpo $(DEPDIR)/libgg_la-handlers.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/handlers.c' object='libgg_la-handlers.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-handlers.lo `test -f 'lib/handlers.c' || echo '$(srcdir)/'`lib/handlers.c
--
--libgg_la-http.lo: lib/http.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-http.lo -MD -MP -MF $(DEPDIR)/libgg_la-http.Tpo -c -o libgg_la-http.lo `test -f 'lib/http.c' || echo '$(srcdir)/'`lib/http.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-http.Tpo $(DEPDIR)/libgg_la-http.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/http.c' object='libgg_la-http.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-http.lo `test -f 'lib/http.c' || echo '$(srcdir)/'`lib/http.c
--
--libgg_la-libgadu.lo: lib/libgadu.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-libgadu.lo -MD -MP -MF $(DEPDIR)/libgg_la-libgadu.Tpo -c -o libgg_la-libgadu.lo `test -f 'lib/libgadu.c' || echo '$(srcdir)/'`lib/libgadu.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-libgadu.Tpo $(DEPDIR)/libgg_la-libgadu.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/libgadu.c' object='libgg_la-libgadu.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-libgadu.lo `test -f 'lib/libgadu.c' || echo '$(srcdir)/'`lib/libgadu.c
--
--libgg_la-message.lo: lib/message.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-message.lo -MD -MP -MF $(DEPDIR)/libgg_la-message.Tpo -c -o libgg_la-message.lo `test -f 'lib/message.c' || echo '$(srcdir)/'`lib/message.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-message.Tpo $(DEPDIR)/libgg_la-message.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/message.c' object='libgg_la-message.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-message.lo `test -f 'lib/message.c' || echo '$(srcdir)/'`lib/message.c
--
--libgg_la-obsolete.lo: lib/obsolete.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-obsolete.lo -MD -MP -MF $(DEPDIR)/libgg_la-obsolete.Tpo -c -o libgg_la-obsolete.lo `test -f 'lib/obsolete.c' || echo '$(srcdir)/'`lib/obsolete.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-obsolete.Tpo $(DEPDIR)/libgg_la-obsolete.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/obsolete.c' object='libgg_la-obsolete.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-obsolete.lo `test -f 'lib/obsolete.c' || echo '$(srcdir)/'`lib/obsolete.c
--
--libgg_la-pubdir.lo: lib/pubdir.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-pubdir.lo -MD -MP -MF $(DEPDIR)/libgg_la-pubdir.Tpo -c -o libgg_la-pubdir.lo `test -f 'lib/pubdir.c' || echo '$(srcdir)/'`lib/pubdir.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-pubdir.Tpo $(DEPDIR)/libgg_la-pubdir.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/pubdir.c' object='libgg_la-pubdir.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-pubdir.lo `test -f 'lib/pubdir.c' || echo '$(srcdir)/'`lib/pubdir.c
--
--libgg_la-pubdir50.lo: lib/pubdir50.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-pubdir50.lo -MD -MP -MF $(DEPDIR)/libgg_la-pubdir50.Tpo -c -o libgg_la-pubdir50.lo `test -f 'lib/pubdir50.c' || echo '$(srcdir)/'`lib/pubdir50.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-pubdir50.Tpo $(DEPDIR)/libgg_la-pubdir50.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/pubdir50.c' object='libgg_la-pubdir50.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-pubdir50.lo `test -f 'lib/pubdir50.c' || echo '$(srcdir)/'`lib/pubdir50.c
--
--libgg_la-resolver.lo: lib/resolver.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-resolver.lo -MD -MP -MF $(DEPDIR)/libgg_la-resolver.Tpo -c -o libgg_la-resolver.lo `test -f 'lib/resolver.c' || echo '$(srcdir)/'`lib/resolver.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-resolver.Tpo $(DEPDIR)/libgg_la-resolver.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/resolver.c' object='libgg_la-resolver.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-resolver.lo `test -f 'lib/resolver.c' || echo '$(srcdir)/'`lib/resolver.c
--
--libgg_la-sha1.lo: lib/sha1.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-sha1.lo -MD -MP -MF $(DEPDIR)/libgg_la-sha1.Tpo -c -o libgg_la-sha1.lo `test -f 'lib/sha1.c' || echo '$(srcdir)/'`lib/sha1.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-sha1.Tpo $(DEPDIR)/libgg_la-sha1.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/sha1.c' object='libgg_la-sha1.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-sha1.lo `test -f 'lib/sha1.c' || echo '$(srcdir)/'`lib/sha1.c
--
--libgg_la-gg-utils.lo: gg-utils.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-gg-utils.lo -MD -MP -MF $(DEPDIR)/libgg_la-gg-utils.Tpo -c -o libgg_la-gg-utils.lo `test -f 'gg-utils.c' || echo '$(srcdir)/'`gg-utils.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-gg-utils.Tpo $(DEPDIR)/libgg_la-gg-utils.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gg-utils.c' object='libgg_la-gg-utils.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-gg-utils.lo `test -f 'gg-utils.c' || echo '$(srcdir)/'`gg-utils.c
--
--libgg_la-confer.lo: confer.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-confer.lo -MD -MP -MF $(DEPDIR)/libgg_la-confer.Tpo -c -o libgg_la-confer.lo `test -f 'confer.c' || echo '$(srcdir)/'`confer.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-confer.Tpo $(DEPDIR)/libgg_la-confer.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='confer.c' object='libgg_la-confer.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-confer.lo `test -f 'confer.c' || echo '$(srcdir)/'`confer.c
--
--libgg_la-search.lo: search.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-search.lo -MD -MP -MF $(DEPDIR)/libgg_la-search.Tpo -c -o libgg_la-search.lo `test -f 'search.c' || echo '$(srcdir)/'`search.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-search.Tpo $(DEPDIR)/libgg_la-search.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='search.c' object='libgg_la-search.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-search.lo `test -f 'search.c' || echo '$(srcdir)/'`search.c
--
--libgg_la-buddylist.lo: buddylist.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-buddylist.lo -MD -MP -MF $(DEPDIR)/libgg_la-buddylist.Tpo -c -o libgg_la-buddylist.lo `test -f 'buddylist.c' || echo '$(srcdir)/'`buddylist.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-buddylist.Tpo $(DEPDIR)/libgg_la-buddylist.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='buddylist.c' object='libgg_la-buddylist.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-buddylist.lo `test -f 'buddylist.c' || echo '$(srcdir)/'`buddylist.c
--
--libgg_la-gg.lo: gg.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-gg.lo -MD -MP -MF $(DEPDIR)/libgg_la-gg.Tpo -c -o libgg_la-gg.lo `test -f 'gg.c' || echo '$(srcdir)/'`gg.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-gg.Tpo $(DEPDIR)/libgg_la-gg.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gg.c' object='libgg_la-gg.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-gg.lo `test -f 'gg.c' || echo '$(srcdir)/'`gg.c
--
--mostlyclean-libtool:
-- -rm -f *.lo
--
--clean-libtool:
-- -rm -rf .libs _libs
--
--ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- mkid -fID $$unique
--tags: TAGS
--
--TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
-- $(TAGS_FILES) $(LISP)
-- set x; \
-- here=`pwd`; \
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- shift; \
-- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-- test -n "$$unique" || unique=$$empty_fix; \
-- if test $$# -gt 0; then \
-- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-- "$$@" $$unique; \
-- else \
-- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-- $$unique; \
-- fi; \
-- fi
--ctags: CTAGS
--CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
-- $(TAGS_FILES) $(LISP)
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- test -z "$(CTAGS_ARGS)$$unique" \
-- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-- $$unique
--
--GTAGS:
-- here=`$(am__cd) $(top_builddir) && pwd` \
-- && $(am__cd) $(top_srcdir) \
-- && gtags -i $(GTAGS_ARGS) "$$here"
--
--distclean-tags:
-- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
--
--distdir: $(DISTFILES)
-- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-- list='$(DISTFILES)'; \
-- dist_files=`for file in $$list; do echo $$file; done | \
-- sed -e "s|^$$srcdirstrip/||;t" \
-- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-- case $$dist_files in \
-- */*) $(MKDIR_P) `echo "$$dist_files" | \
-- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-- sort -u` ;; \
-- esac; \
-- for file in $$dist_files; do \
-- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-- if test -d $$d/$$file; then \
-- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-- if test -d "$(distdir)/$$file"; then \
-- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-- fi; \
-- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-- fi; \
-- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-- else \
-- test -f "$(distdir)/$$file" \
-- || cp -p $$d/$$file "$(distdir)/$$file" \
-- || exit 1; \
-- fi; \
-- done
--check-am: all-am
--check: check-am
--all-am: Makefile $(LTLIBRARIES)
--installdirs:
-- for dir in "$(DESTDIR)$(pkgdir)"; do \
-- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
-- done
--install: install-am
--install-exec: install-exec-am
--install-data: install-data-am
--uninstall: uninstall-am
--
--install-am: all-am
-- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
--
--installcheck: installcheck-am
--install-strip:
-- if test -z '$(STRIP)'; then \
-- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-- install; \
-- else \
-- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-- fi
--mostlyclean-generic:
--
--clean-generic:
--
--distclean-generic:
-- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
--
--maintainer-clean-generic:
-- @echo "This command is intended for maintainers to use"
-- @echo "it deletes files that may require special tools to rebuild."
--clean: clean-am
--
--clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
-- clean-pkgLTLIBRARIES mostlyclean-am
--
--distclean: distclean-am
-- -rm -rf ./$(DEPDIR)
-- -rm -f Makefile
--distclean-am: clean-am distclean-compile distclean-generic \
-- distclean-tags
--
--dvi: dvi-am
--
--dvi-am:
--
--html: html-am
--
--html-am:
--
--info: info-am
--
--info-am:
--
--install-data-am: install-pkgLTLIBRARIES
--
--install-dvi: install-dvi-am
--
--install-dvi-am:
--
--install-exec-am:
--
--install-html: install-html-am
--
--install-html-am:
--
--install-info: install-info-am
--
--install-info-am:
--
--install-man:
--
--install-pdf: install-pdf-am
--
--install-pdf-am:
--
--install-ps: install-ps-am
--
--install-ps-am:
--
--installcheck-am:
--
--maintainer-clean: maintainer-clean-am
-- -rm -rf ./$(DEPDIR)
-- -rm -f Makefile
--maintainer-clean-am: distclean-am maintainer-clean-generic
--
--mostlyclean: mostlyclean-am
--
--mostlyclean-am: mostlyclean-compile mostlyclean-generic \
-- mostlyclean-libtool
--
--pdf: pdf-am
--
--pdf-am:
--
--ps: ps-am
--
--ps-am:
--
--uninstall-am: uninstall-pkgLTLIBRARIES
--
--.MAKE: install-am install-strip
--
--.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
-- clean-libtool clean-noinstLTLIBRARIES clean-pkgLTLIBRARIES \
-- ctags distclean distclean-compile distclean-generic \
-- distclean-libtool distclean-tags distdir dvi dvi-am html \
-- html-am info info-am install install-am install-data \
-- install-data-am install-dvi install-dvi-am install-exec \
-- install-exec-am install-html install-html-am install-info \
-- install-info-am install-man install-pdf install-pdf-am \
-- install-pkgLTLIBRARIES install-ps install-ps-am install-strip \
-- installcheck installcheck-am installdirs maintainer-clean \
-- maintainer-clean-generic mostlyclean mostlyclean-compile \
-- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-- tags uninstall uninstall-am uninstall-pkgLTLIBRARIES
--
--
--# Tell versions [3.59,3.63) of GNU make to not export all variables.
--# Otherwise a system limit (for SysV at least) may be exceeded.
--.NOEXPORT:
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/gg/Makefile.mingw
---- pidgin-2.10.7/libpurple/protocols/gg/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,100 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of libgg
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = libgg
--CFLAGS += -include win32dep.h -DGG_IGNORE_DEPRECATED
--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./lib \
-- -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)
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP) \
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = \
-- lib/common.c \
-- lib/dcc.c \
-- lib/dcc7.c \
-- lib/debug.c \
-- lib/deflate.c \
-- lib/encoding.c \
-- lib/events.c \
-- lib/handlers.c \
-- lib/http.c \
-- lib/libgadu.c \
-- lib/message.c \
-- lib/obsolete.c \
-- lib/pubdir.c \
-- lib/pubdir50.c \
-- lib/resolver.c \
-- lib/sha1.c \
-- buddylist.c \
-- confer.c \
-- gg.c \
-- search.c \
-- gg-utils.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lintl \
-- -lpurple \
-- -lws2_32
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll
--
--install: all $(DLL_INSTALL_DIR)
-- cp $(TARGET).dll $(DLL_INSTALL_DIR)
--
--$(OBJECTS): $(PURPLE_CONFIG_H)
--
--$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -f $(OBJECTS)
-- rm -f $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/search.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/search.c
---- pidgin-2.10.7/libpurple/protocols/gg/search.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/search.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,223 +0,0 @@
--/**
-- * @file search.c
-- *
-- * purple
-- *
-- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--
--#include <libgadu.h>
--
--#include "gg-utils.h"
--#include "search.h"
--
--
--/* GGPSearchForm *ggp_search_form_new() {{{ */
--GGPSearchForm *ggp_search_form_new(GGPSearchType st)
--{
-- GGPSearchForm *form;
--
-- form = g_new0(GGPSearchForm, 1);
--
-- form->search_type = st;
-- form->window = NULL;
-- form->user_data = NULL;
-- form->seq = 0;
-- form->page_number = 0;
-- form->page_size = 0;
--
-- form->uin = NULL;
-- form->lastname = NULL;
-- form->firstname = NULL;
-- form->nickname = NULL;
-- form->city = NULL;
-- form->birthyear = NULL;
-- form->gender = NULL;
-- form->active = NULL;
--
-- return form;
--}
--/* }}} */
--
--/* void ggp_search_form_destroy(GGPSearchForm *form) {{{ */
--void ggp_search_form_destroy(GGPSearchForm *form)
--{
-- g_return_if_fail(form != NULL);
--
-- form->window = NULL;
-- form->user_data = NULL;
-- form->seq = 0;
-- form->page_number = 0;
-- form->page_size = 0;
--
-- g_free(form->uin);
-- g_free(form->lastname);
-- g_free(form->firstname);
-- g_free(form->nickname);
-- g_free(form->city);
-- g_free(form->birthyear);
-- g_free(form->gender);
-- g_free(form->active);
-- g_free(form);
--}
--/* }}} */
--
--/* void ggp_search_add(GGPSearches *searches, guint32 seq, GGPSearchForm *form) {{{ */
--void ggp_search_add(GGPSearches *searches, guint32 seq, GGPSearchForm *form)
--{
-- guint32 *tmp;
--
-- g_return_if_fail(searches != NULL);
-- g_return_if_fail(form != NULL);
--
-- tmp = g_new0(guint32, 1);
-- *tmp = seq;
-- form->seq = seq;
--
-- g_hash_table_insert(searches, tmp, form);
--}
--/* }}} */
--
--/* void ggp_search_remove(GGPSearches *searches, guint32 seq) {{{ */
--void ggp_search_remove(GGPSearches *searches, guint32 seq)
--{
-- g_return_if_fail(searches != NULL);
--
-- g_hash_table_remove(searches, &seq);
--}
--/* }}} */
--
--/* GGPSearchForm *ggp_search_get(GGPSearches *searches, seq) {{{ */
--GGPSearchForm *ggp_search_get(GGPSearches *searches, guint32 seq)
--{
-- g_return_val_if_fail(searches != NULL, NULL);
--
-- return g_hash_table_lookup(searches, &seq);
--}
--/* }}} */
--
--/* GGPSearches *ggp_search_new() {{{ */
--GGPSearches *ggp_search_new(void)
--{
-- GGPSearches *searches;
--
-- searches = g_hash_table_new_full(g_int_hash, g_int_equal,
-- g_free, NULL);
--
-- return searches;
--}
--/* }}} */
--
--/* void ggp_search_destroy(GGPSearches *searches) {{{ */
--void ggp_search_destroy(GGPSearches *searches)
--{
-- g_return_if_fail(searches != NULL);
--
-- g_hash_table_destroy(searches);
--}
--/* }}} */
--
--/* guint32 ggp_search_start(PurpleConnection *gc, GGPSearchForm *form) {{{ */
--guint32 ggp_search_start(PurpleConnection *gc, GGPSearchForm *form)
--{
-- GGPInfo *info = gc->proto_data;
-- gg_pubdir50_t req;
-- guint seq, offset;
-- gchar *tmp;
--
-- purple_debug_info("gg", "It's time to perform a search...\n");
--
-- if ((req = gg_pubdir50_new(GG_PUBDIR50_SEARCH)) == NULL) {
-- purple_debug_error("gg",
-- "ggp_bmenu_show_details: Unable to create req variable.\n");
-- return 0;
-- }
--
-- if (form->uin != NULL) {
-- purple_debug_info("gg", " uin: %s\n", form->uin);
-- gg_pubdir50_add(req, GG_PUBDIR50_UIN, form->uin);
-- } else {
-- if (form->lastname != NULL) {
-- purple_debug_info("gg", " lastname: %s\n", form->lastname);
-- gg_pubdir50_add(req, GG_PUBDIR50_LASTNAME, form->lastname);
-- }
--
-- if (form->firstname != NULL) {
-- purple_debug_info("gg", " firstname: %s\n", form->firstname);
-- gg_pubdir50_add(req, GG_PUBDIR50_FIRSTNAME, form->firstname);
-- }
--
-- if (form->nickname != NULL) {
-- purple_debug_info("gg", " nickname: %s\n", form->nickname);
-- gg_pubdir50_add(req, GG_PUBDIR50_NICKNAME, form->nickname);
-- }
--
-- if (form->city != NULL) {
-- purple_debug_info("gg", " city: %s\n", form->city);
-- gg_pubdir50_add(req, GG_PUBDIR50_CITY, form->city);
-- }
--
-- if (form->birthyear != NULL) {
-- purple_debug_info("gg", " birthyear: %s\n", form->birthyear);
-- gg_pubdir50_add(req, GG_PUBDIR50_BIRTHYEAR, form->birthyear);
-- }
--
-- if (form->gender != NULL) {
-- purple_debug_info("gg", " gender: %s\n", form->gender);
-- gg_pubdir50_add(req, GG_PUBDIR50_GENDER, form->gender);
-- }
--
-- if (form->active != NULL) {
-- purple_debug_info("gg", " active: %s\n", form->active);
-- gg_pubdir50_add(req, GG_PUBDIR50_ACTIVE, form->active);
-- }
-- }
--
-- offset = form->page_size * form->page_number;
-- purple_debug_info("gg", "page number: %u, page size: %u, offset: %u\n",
-- form->page_number, form->page_size, offset);
-- tmp = g_strdup_printf("%u", offset);
-- gg_pubdir50_add(req, GG_PUBDIR50_START, tmp);
-- g_free(tmp);
--
-- if ((seq = gg_pubdir50(info->session, req)) == 0) {
-- purple_debug_warning("gg", "ggp_bmenu_show_details: Search failed.\n");
-- gg_pubdir50_free(req);
-- return 0;
-- }
--
-- purple_debug_info("gg", "search sequence number: %d\n", seq);
-- gg_pubdir50_free(req);
--
-- return seq;
--}
--/* }}} */
--
--/* char *ggp_search_get_result(gg_pubdir50_t res, int num, const char *field) {{{ */
--char *ggp_search_get_result(gg_pubdir50_t res, int num, const char *field)
--{
-- char *tmp;
--
-- tmp = g_strdup(gg_pubdir50_get(res, num, field));
--
-- return (tmp == NULL) ? g_strdup("") : tmp;
--}
--/* }}} */
--
--
--/* vim: set ts=8 sts=0 sw=8 noet: */
-diff -Nur pidgin-2.10.7/libpurple/protocols/gg/search.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/search.h
---- pidgin-2.10.7/libpurple/protocols/gg/search.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/search.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,152 +0,0 @@
--/**
-- * @file search.h
-- *
-- * purple
-- *
-- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--
--#ifndef _PURPLE_GG_SEARCH_H
--#define _PURPLE_GG_SEARCH_H
--
--#include "connection.h"
--
--#include <libgadu.h>
--#include "gg.h"
--
--
--typedef enum {
-- GGP_SEARCH_TYPE_INFO,
-- GGP_SEARCH_TYPE_FULL
--
--} GGPSearchType;
--
--typedef struct {
--
-- char *uin;
-- char *lastname;
-- char *firstname;
-- char *nickname;
-- char *city;
-- char *birthyear;
-- char *gender;
-- char *active;
--
-- GGPSearchType search_type;
-- guint32 seq;
-- guint16 page_number;
-- guint16 page_size; /* how many contacts fits into one page of results */
--
-- void *user_data;
-- void *window;
--} GGPSearchForm;
--
--typedef GHashTable GGPSearches;
--
--
--/**
-- * Create a new GGPSearchForm structure, and set the fields
-- * to the sane defaults.
-- *
-- * @return Newly allocated GGPSearchForm.
-- */
--GGPSearchForm *
--ggp_search_form_new(GGPSearchType st);
--
--/**
-- * Destroy a Search Form.
-- *
-- * @param form Search Form to destroy.
-- */
--void
--ggp_search_form_destroy(GGPSearchForm *form);
--
--/**
-- * Add a search to the list of searches.
-- *
-- * @param searches The list of searches.
-- * @param seq Search (form) ID number.
-- * @param form The search form to add.
-- */
--void
--ggp_search_add(GGPSearches *searches, guint32 seq, GGPSearchForm *form);
--
--/**
-- * Remove a search from the list.
-- *
-- * If you want to destory the search completely also call:
-- * ggp_search_form_destroy().
-- *
-- * @param searches The list of searches.
-- * @param seq ID number of the search.
-- */
--void
--ggp_search_remove(GGPSearches *searches, guint32 seq);
--
--/**
-- * Return the search with the specified ID.
-- *
-- * @param searches The list of searches.
-- * @param seq ID number of the search.
-- */
--GGPSearchForm *
--ggp_search_get(GGPSearches *searches, guint32 seq);
--
--/**
-- * Create a new GGPSearches structure.
-- *
-- * @return GGPSearches instance.
-- */
--GGPSearches *
--ggp_search_new(void);
--
--/**
-- * Destroy GGPSearches instance.
-- *
-- * @param searches GGPSearches instance.
-- */
--void
--ggp_search_destroy(GGPSearches *searches);
--
--/**
-- * Initiate a search in the public directory.
-- *
-- * @param gc PurpleConnection.
-- * @param form Filled in GGPSearchForm.
-- *
-- * @return Sequence number of a search or 0 if an error occurred.
-- */
--guint32
--ggp_search_start(PurpleConnection *gc, GGPSearchForm *form);
--
--/*
-- * Return converted to the UTF-8 value of the specified field.
-- *
-- * @param res Public directory look-up result.
-- * @param num Id of the record.
-- * @param fileld Name of the field.
-- *
-- * @return UTF-8 encoded value of the field.
-- */
--char *
--ggp_search_get_result(gg_pubdir50_t res, int num, const char *field);
--
--
--#endif /* _PURPLE_GG_SEARCH_H */
--
--/* vim: set ts=8 sts=0 sw=8 noet: */
-diff -Nur pidgin-2.10.7/libpurple/protocols/irc/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/irc/Makefile.in
---- pidgin-2.10.7/libpurple/protocols/irc/Makefile.in 2013-02-11 07:17:20.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/irc/Makefile.in 2013-08-16 23:51:18.822722885 -0300
-@@ -190,8 +190,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -253,8 +251,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/libpurple/protocols/irc/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/irc/Makefile.mingw
---- pidgin-2.10.7/libpurple/protocols/irc/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/irc/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,92 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of libirc
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = libirc
--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)
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = cmds.c \
-- dcc_send.c \
-- irc.c \
-- msgs.c \
-- parse.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lws2_32 \
-- -lintl \
-- -lpurple
--
--
--ifeq ($(CYRUS_SASL), 1)
--INCLUDE_PATHS += -I$(CYRUS_SASL_TOP)/include
--LIB_PATHS += -L$(CYRUS_SASL_TOP)/bin
--LIBS += -llibsasl
--endif
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll
--
--install: all $(DLL_INSTALL_DIR)
-- cp $(TARGET).dll $(DLL_INSTALL_DIR)
--
--$(OBJECTS): $(PURPLE_CONFIG_H)
--
--##
--## BUILD DLL
--##
--$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--
--clean:
-- rm -f $(OBJECTS)
-- rm -f $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/auth_cyrus.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/auth_cyrus.c
---- pidgin-2.10.7/libpurple/protocols/jabber/auth_cyrus.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/auth_cyrus.c 2013-08-17 00:14:13.334946817 -0300
-@@ -320,7 +320,7 @@
- xmlnode_set_namespace(auth, NS_XMPP_SASL);
- xmlnode_set_attrib(auth, "mechanism", js->current_mech);
-
-- xmlnode_set_attrib(auth, "xmlns:ga", "http://www.google.com/talk/protocol/auth");
-+ xmlnode_set_attrib(auth, "xmlns:ga", "");
- xmlnode_set_attrib(auth, "ga:client-uses-full-bind-result", "true");
-
- if (clientout) {
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/auth_plain.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/auth_plain.c
---- pidgin-2.10.7/libpurple/protocols/jabber/auth_plain.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/auth_plain.c 2013-08-17 00:19:44.801822370 -0300
-@@ -40,7 +40,7 @@
- auth = xmlnode_new("auth");
- xmlnode_set_namespace(auth, NS_XMPP_SASL);
-
-- xmlnode_set_attrib(auth, "xmlns:ga", "http://www.google.com/talk/protocol/auth");
-+ xmlnode_set_attrib(auth, "xmlns:ga", "");
- xmlnode_set_attrib(auth, "ga:client-uses-full-bind-result", "true");
-
- response = g_string_new("");
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/buddy.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/buddy.c
---- pidgin-2.10.7/libpurple/protocols/jabber/buddy.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/buddy.c 2013-08-17 00:22:49.080836449 -0300
-@@ -38,7 +38,6 @@
- #include "xdata.h"
- #include "pep.h"
- #include "adhoccommands.h"
--#include "google/google.h"
-
- typedef struct {
- long idle_seconds;
-@@ -945,17 +944,7 @@
-
- /* Republish our vcard if the photo is different than the server's */
- if (js->initial_avatar_hash && !purple_strequal(vcard_hash, js->initial_avatar_hash)) {
-- /*
-- * Google Talk has developed the behavior that it will not accept
-- * a vcard set in the first 10 seconds (or so) of the connection;
-- * it returns an error (namespaces trimmed):
-- * <error code="500" type="wait"><internal-server-error/></error>.
-- */
-- if (js->googletalk)
-- js->vcard_timer = purple_timeout_add_seconds(10, set_own_vcard_cb,
-- js);
-- else
-- jabber_set_info(js->gc, purple_account_get_user_info(account));
-+ jabber_set_info(js->gc, purple_account_get_user_info(account));
- } else if (vcard_hash) {
- /* A photo is in the vCard. Advertise its hash */
- js->avatar_hash = vcard_hash;
-@@ -1861,13 +1850,6 @@
- NULL, NULL);
- m = g_list_append(m, act);
- }
--
-- if (js->googletalk) {
-- act = purple_menu_action_new(_("Initiate _Chat"),
-- PURPLE_CALLBACK(google_buddy_node_chat),
-- NULL, NULL);
-- m = g_list_append(m, act);
-- }
-
- /*
- * This if-condition implements parts of XEP-0100: Gateway Interaction
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/disco.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/disco.c
---- pidgin-2.10.7/libpurple/protocols/jabber/disco.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/disco.c 2013-08-27 22:49:34.275219711 -0300
-@@ -30,9 +30,6 @@
- #include "adhoccommands.h"
- #include "buddy.h"
- #include "disco.h"
--#include "google/google.h"
--#include "google/gmail.h"
--#include "google/jingleinfo.h"
- #include "iq.h"
- #include "jabber.h"
- #include "jingle/jingle.h"
-@@ -142,44 +139,6 @@
- xmlnode_set_attrib(feature, "var", feat->namespace);
- }
- }
--#ifdef USE_VV
-- } else if (g_str_equal(node, CAPS0115_NODE "#" "voice-v1")) {
-- /*
-- * HUGE HACK! We advertise this ext (see jabber_presence_create_js
-- * where we add <c/> to the <presence/>) for the Google Talk
-- * clients that don't actually check disco#info features.
-- *
-- * This specific feature is redundant but is what
-- * node='http://mail.google.com/xmpp/client/caps', ver='1.1'
-- * advertises as 'voice-v1'.
-- */
-- xmlnode *feature = xmlnode_new_child(query, "feature");
-- xmlnode_set_attrib(feature, "var", NS_GOOGLE_VOICE);
-- } else if (g_str_equal(node, CAPS0115_NODE "#" "video-v1")) {
-- /*
-- * HUGE HACK! We advertise this ext (see jabber_presence_create_js
-- * where we add <c/> to the <presence/>) for the Google Talk
-- * clients that don't actually check disco#info features.
-- *
-- * This specific feature is redundant but is what
-- * node='http://mail.google.com/xmpp/client/caps', ver='1.1'
-- * advertises as 'video-v1'.
-- */
-- xmlnode *feature = xmlnode_new_child(query, "feature");
-- xmlnode_set_attrib(feature, "var", NS_GOOGLE_VIDEO);
-- } else if (g_str_equal(node, CAPS0115_NODE "#" "camera-v1")) {
-- /*
-- * HUGE HACK! We advertise this ext (see jabber_presence_create_js
-- * where we add <c/> to the <presence/>) for the Google Talk
-- * clients that don't actually check disco#info features.
-- *
-- * This specific feature is redundant but is what
-- * node='http://mail.google.com/xmpp/client/caps', ver='1.1'
-- * advertises as 'camera-v1'.
-- */
-- xmlnode *feature = xmlnode_new_child(query, "feature");
-- xmlnode_set_attrib(feature, "var", NS_GOOGLE_CAMERA);
--#endif
- } else {
- xmlnode *error, *inf;
-
-@@ -419,7 +378,7 @@
-
- }
-
--/* should probably share this code with google.c, or maybe from 2.7.0
-+/* maybe from 2.7.0
- introduce an abstracted hostname -> IP function in dns.c */
- static void
- jabber_disco_stun_lookup_cb(GSList *hosts, gpointer data,
-@@ -538,16 +497,7 @@
-
- g_free(js->server_name);
- js->server_name = g_strdup(name);
-- if (!strcmp(name, "Google Talk")) {
-- purple_debug_info("jabber", "Google Talk!\n");
-- js->googletalk = TRUE;
--
-- /* autodiscover stun and relays */
-- if (purple_network_get_stun_ip() == NULL ||
-- purple_strequal(purple_network_get_stun_ip(), "")) {
-- jabber_google_send_jingle_info(js);
-- }
-- } else if (purple_network_get_stun_ip() == NULL ||
-+ if (purple_network_get_stun_ip() == NULL ||
- purple_strequal(purple_network_get_stun_ip(), "")) {
- js->srv_query_data =
- purple_srv_resolve_account(
-@@ -565,12 +515,7 @@
- if (!var)
- continue;
-
-- if (!strcmp(NS_GOOGLE_MAIL_NOTIFY, var)) {
-- js->server_caps |= JABBER_CAP_GMAIL_NOTIFY;
-- jabber_gmail_init(js);
-- } else if (!strcmp(NS_GOOGLE_ROSTER, var)) {
-- js->server_caps |= JABBER_CAP_GOOGLE_ROSTER;
-- } else if (!strcmp("http://jabber.org/protocol/commands", var)) {
-+ if (!strcmp("http://jabber.org/protocol/commands", var)) {
- js->server_caps |= JABBER_CAP_ADHOC;
- } else if (!strcmp(NS_SIMPLE_BLOCKING, var)) {
- js->server_caps |= JABBER_CAP_BLOCKING;
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/gmail.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/gmail.c
---- pidgin-2.10.7/libpurple/protocols/jabber/google/gmail.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/gmail.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,207 +0,0 @@
--/**
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--#include "jabber.h"
--#include "gmail.h"
--
--static void
--jabber_gmail_parse(JabberStream *js, const char *from,
-- JabberIqType type, const char *id,
-- xmlnode *packet, gpointer nul)
--{
-- xmlnode *child;
-- xmlnode *message;
-- const char *to, *url;
-- const char *in_str;
-- char *to_name;
--
-- int i, count = 1, returned_count;
--
-- const char **tos, **froms, **urls;
-- char **subjects;
--
-- if (type == JABBER_IQ_ERROR)
-- return;
--
-- child = xmlnode_get_child(packet, "mailbox");
-- if (!child)
-- return;
--
-- in_str = xmlnode_get_attrib(child, "total-matched");
-- if (in_str && *in_str)
-- count = atoi(in_str);
--
-- /* If Gmail doesn't tell us who the mail is to, let's use our JID */
-- to = xmlnode_get_attrib(packet, "to");
--
-- message = xmlnode_get_child(child, "mail-thread-info");
--
-- if (count == 0 || !message) {
-- if (count > 0) {
-- char *bare_jid = jabber_get_bare_jid(to);
-- const char *default_tos[2] = { bare_jid };
--
-- purple_notify_emails(js->gc, count, FALSE, NULL, NULL, default_tos, NULL, NULL, NULL);
-- g_free(bare_jid);
-- } else {
-- purple_notify_emails(js->gc, count, FALSE, NULL, NULL, NULL, NULL, NULL, NULL);
-- }
--
-- return;
-- }
--
-- /* Loop once to see how many messages were returned so we can allocate arrays
-- * accordingly */
-- for (returned_count = 0; message; returned_count++, message=xmlnode_get_next_twin(message));
--
-- froms = g_new0(const char* , returned_count + 1);
-- tos = g_new0(const char* , returned_count + 1);
-- subjects = g_new0(char* , returned_count + 1);
-- urls = g_new0(const char* , returned_count + 1);
--
-- to = xmlnode_get_attrib(packet, "to");
-- to_name = jabber_get_bare_jid(to);
-- url = xmlnode_get_attrib(child, "url");
-- if (!url || !*url)
-- url = "http://www.gmail.com";
--
-- message= xmlnode_get_child(child, "mail-thread-info");
-- for (i=0; message; message = xmlnode_get_next_twin(message), i++) {
-- xmlnode *sender_node, *subject_node;
-- const char *from, *tid;
-- char *subject;
--
-- subject_node = xmlnode_get_child(message, "subject");
-- sender_node = xmlnode_get_child(message, "senders");
-- sender_node = xmlnode_get_child(sender_node, "sender");
--
-- while (sender_node && (!xmlnode_get_attrib(sender_node, "unread") ||
-- !strcmp(xmlnode_get_attrib(sender_node, "unread"),"0")))
-- sender_node = xmlnode_get_next_twin(sender_node);
--
-- if (!sender_node) {
-- i--;
-- continue;
-- }
--
-- from = xmlnode_get_attrib(sender_node, "name");
-- if (!from || !*from)
-- from = xmlnode_get_attrib(sender_node, "address");
-- subject = xmlnode_get_data(subject_node);
-- /*
-- * url = xmlnode_get_attrib(message, "url");
-- */
-- tos[i] = (to_name != NULL ? to_name : "");
-- froms[i] = (from != NULL ? from : "");
-- subjects[i] = (subject != NULL ? subject : g_strdup(""));
-- urls[i] = url;
--
-- tid = xmlnode_get_attrib(message, "tid");
-- if (tid &&
-- (js->gmail_last_tid == NULL || strcmp(tid, js->gmail_last_tid) > 0)) {
-- g_free(js->gmail_last_tid);
-- js->gmail_last_tid = g_strdup(tid);
-- }
-- }
--
-- if (i>0)
-- purple_notify_emails(js->gc, count, count == i, (const char**) subjects, froms, tos,
-- urls, NULL, NULL);
--
-- g_free(to_name);
-- g_free(tos);
-- g_free(froms);
-- for (i = 0; i < returned_count; i++)
-- g_free(subjects[i]);
-- g_free(subjects);
-- g_free(urls);
--
-- in_str = xmlnode_get_attrib(child, "result-time");
-- if (in_str && *in_str) {
-- g_free(js->gmail_last_time);
-- js->gmail_last_time = g_strdup(in_str);
-- }
--}
--
--void
--jabber_gmail_poke(JabberStream *js, const char *from, JabberIqType type,
-- const char *id, xmlnode *new_mail)
--{
-- xmlnode *query;
-- JabberIq *iq;
--
-- /* bail if the user isn't interested */
-- if (!purple_account_get_check_mail(js->gc->account))
-- return;
--
-- /* Is this an initial incoming mail notification? If so, send a request for more info */
-- if (type != JABBER_IQ_SET)
-- return;
--
-- /* Acknowledge the notification */
-- iq = jabber_iq_new(js, JABBER_IQ_RESULT);
-- if (from)
-- xmlnode_set_attrib(iq->node, "to", from);
-- xmlnode_set_attrib(iq->node, "id", id);
-- jabber_iq_send(iq);
--
-- purple_debug_misc("jabber",
-- "Got new mail notification. Sending request for more info\n");
--
-- iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_GOOGLE_MAIL_NOTIFY);
-- jabber_iq_set_callback(iq, jabber_gmail_parse, NULL);
-- query = xmlnode_get_child(iq->node, "query");
--
-- if (js->gmail_last_time)
-- xmlnode_set_attrib(query, "newer-than-time", js->gmail_last_time);
-- if (js->gmail_last_tid)
-- xmlnode_set_attrib(query, "newer-than-tid", js->gmail_last_tid);
--
-- jabber_iq_send(iq);
-- return;
--}
--
--void jabber_gmail_init(JabberStream *js) {
-- JabberIq *iq;
-- xmlnode *usersetting, *mailnotifications;
--
-- if (!purple_account_get_check_mail(purple_connection_get_account(js->gc)))
-- return;
--
-- /*
-- * Quoting http://code.google.com/apis/talk/jep_extensions/usersettings.html:
-- * To ensure better compatibility with other clients, rather than
-- * setting this value to "false" to turn off notifications, it is
-- * recommended that a client set this to "true" and filter incoming
-- * email notifications itself.
-- */
-- iq = jabber_iq_new(js, JABBER_IQ_SET);
-- usersetting = xmlnode_new_child(iq->node, "usersetting");
-- xmlnode_set_namespace(usersetting, "google:setting");
-- mailnotifications = xmlnode_new_child(usersetting, "mailnotifications");
-- xmlnode_set_attrib(mailnotifications, "value", "true");
-- jabber_iq_send(iq);
--
-- iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_GOOGLE_MAIL_NOTIFY);
-- jabber_iq_set_callback(iq, jabber_gmail_parse, NULL);
-- jabber_iq_send(iq);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/gmail.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/gmail.h
---- pidgin-2.10.7/libpurple/protocols/jabber/google/gmail.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/gmail.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,30 +0,0 @@
--/**
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef PURPLE_JABBER_GOOGLE_GMAIL_H_
--#define PURPLE_JABBER_GOOGLE_GMAIL_H_
--
--#include "jabber.h"
--
--void jabber_gmail_init(JabberStream *js);
--void jabber_gmail_poke(JabberStream *js, const char *from, JabberIqType type,
-- const char *id, xmlnode *new_mail);
--
--#endif /* PURPLE_JABBER_GOOGLE_GMAIL_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/google.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google.c
---- pidgin-2.10.7/libpurple/protocols/jabber/google/google.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,172 +0,0 @@
--/**
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "google.h"
--#include "jabber.h"
--#include "chat.h"
--
--/* This does two passes on the string. The first pass goes through
-- * and determine if all the structured text is properly balanced, and
-- * how many instances of each there is. The second pass goes and converts
-- * everything to HTML, depending on what's figured out by the first pass.
-- * It will short circuit once it knows it has no more replacements to make
-- */
--char *jabber_google_format_to_html(const char *text)
--{
-- const char *p;
--
-- /* The start of the screen may be consdiered a space for this purpose */
-- gboolean preceding_space = TRUE;
--
-- gboolean in_bold = FALSE, in_italic = FALSE;
-- gboolean in_tag = FALSE;
--
-- gint bold_count = 0, italic_count = 0;
--
-- GString *str;
--
-- for (p = text; *p != '\0'; p = g_utf8_next_char(p)) {
-- gunichar c = g_utf8_get_char(p);
-- if (c == '*' && !in_tag) {
-- if (in_bold && (g_unichar_isspace(*(p+1)) ||
-- *(p+1) == '\0' ||
-- *(p+1) == '<')) {
-- bold_count++;
-- in_bold = FALSE;
-- } else if (preceding_space && !in_bold && !g_unichar_isspace(*(p+1))) {
-- bold_count++;
-- in_bold = TRUE;
-- }
-- preceding_space = TRUE;
-- } else if (c == '_' && !in_tag) {
-- if (in_italic && (g_unichar_isspace(*(p+1)) ||
-- *(p+1) == '\0' ||
-- *(p+1) == '<')) {
-- italic_count++;
-- in_italic = FALSE;
-- } else if (preceding_space && !in_italic && !g_unichar_isspace(*(p+1))) {
-- italic_count++;
-- in_italic = TRUE;
-- }
-- preceding_space = TRUE;
-- } else if (c == '<' && !in_tag) {
-- in_tag = TRUE;
-- } else if (c == '>' && in_tag) {
-- in_tag = FALSE;
-- } else if (!in_tag) {
-- if (g_unichar_isspace(c))
-- preceding_space = TRUE;
-- else
-- preceding_space = FALSE;
-- }
-- }
--
-- str = g_string_new(NULL);
-- in_bold = in_italic = in_tag = FALSE;
-- preceding_space = TRUE;
--
-- for (p = text; *p != '\0'; p = g_utf8_next_char(p)) {
-- gunichar c = g_utf8_get_char(p);
--
-- if (bold_count < 2 && italic_count < 2 && !in_bold && !in_italic) {
-- g_string_append(str, p);
-- return g_string_free(str, FALSE);
-- }
--
--
-- if (c == '*' && !in_tag) {
-- if (in_bold &&
-- (g_unichar_isspace(*(p+1))||*(p+1)=='<')) { /* This is safe in UTF-8 */
-- str = g_string_append(str, "</b>");
-- in_bold = FALSE;
-- bold_count--;
-- } else if (preceding_space && bold_count > 1 && !g_unichar_isspace(*(p+1))) {
-- str = g_string_append(str, "<b>");
-- bold_count--;
-- in_bold = TRUE;
-- } else {
-- str = g_string_append_unichar(str, c);
-- }
-- preceding_space = TRUE;
-- } else if (c == '_' && !in_tag) {
-- if (in_italic &&
-- (g_unichar_isspace(*(p+1))||*(p+1)=='<')) {
-- str = g_string_append(str, "</i>");
-- italic_count--;
-- in_italic = FALSE;
-- } else if (preceding_space && italic_count > 1 && !g_unichar_isspace(*(p+1))) {
-- str = g_string_append(str, "<i>");
-- italic_count--;
-- in_italic = TRUE;
-- } else {
-- str = g_string_append_unichar(str, c);
-- }
-- preceding_space = TRUE;
-- } else if (c == '<' && !in_tag) {
-- str = g_string_append_unichar(str, c);
-- in_tag = TRUE;
-- } else if (c == '>' && in_tag) {
-- str = g_string_append_unichar(str, c);
-- in_tag = FALSE;
-- } else if (!in_tag) {
-- str = g_string_append_unichar(str, c);
-- if (g_unichar_isspace(c))
-- preceding_space = TRUE;
-- else
-- preceding_space = FALSE;
-- } else {
-- str = g_string_append_unichar(str, c);
-- }
-- }
-- return g_string_free(str, FALSE);
--}
--
--
--
--void google_buddy_node_chat(PurpleBlistNode *node, gpointer data)
--{
-- PurpleBuddy *buddy;
-- PurpleConnection *gc;
-- JabberStream *js;
-- JabberChat *chat;
-- gchar *room;
-- gchar *uuid = purple_uuid_random();
--
-- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
--
-- buddy = PURPLE_BUDDY(node);
-- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-- g_return_if_fail(gc != NULL);
-- js = purple_connection_get_protocol_data(gc);
--
-- room = g_strdup_printf("private-chat-%s", uuid);
-- chat = jabber_join_chat(js, room, GOOGLE_GROUPCHAT_SERVER, js->user->node,
-- NULL, NULL);
-- if (chat) {
-- chat->muc = TRUE;
-- jabber_chat_invite(gc, chat->id, "", purple_buddy_get_name(buddy));
-- }
--
-- g_free(room);
-- g_free(uuid);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/google.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google.h
---- pidgin-2.10.7/libpurple/protocols/jabber/google/google.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,35 +0,0 @@
--/**
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef PURPLE_JABBER_GOOGLE_H_
--#define PURPLE_JABBER_GOOGLE_H_
--
--/* This is a place for Google Talk-specific XMPP extensions to live
-- * such that they don't intermingle with code for the XMPP RFCs and XEPs :) */
--
--#include "jabber.h"
--
--#define GOOGLE_GROUPCHAT_SERVER "groupchat.google.com"
--
--char *jabber_google_format_to_html(const char *text);
--
--void google_buddy_node_chat(PurpleBlistNode *node, gpointer data);
--
--#endif /* PURPLE_JABBER_GOOGLE_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/google_presence.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_presence.c
---- pidgin-2.10.7/libpurple/protocols/jabber/google/google_presence.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_presence.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,43 +0,0 @@
--/**
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--#include "google_presence.h"
--
--void jabber_google_presence_incoming(JabberStream *js, const char *user, JabberBuddyResource *jbr)
--{
-- if (!js->googletalk)
-- return;
-- if (jbr->status && purple_str_has_prefix(jbr->status, "♫ ")) {
-- purple_prpl_got_user_status(js->gc->account, user, "tune",
-- PURPLE_TUNE_TITLE, jbr->status + strlen("♫ "), NULL);
-- g_free(jbr->status);
-- jbr->status = NULL;
-- } else {
-- purple_prpl_got_user_status_deactive(js->gc->account, user, "tune");
-- }
--}
--
--char *jabber_google_presence_outgoing(PurpleStatus *tune)
--{
-- const char *attr = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE);
-- return attr ? g_strdup_printf("♫ %s", attr) : g_strdup("");
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/google_presence.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_presence.h
---- pidgin-2.10.7/libpurple/protocols/jabber/google/google_presence.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_presence.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,32 +0,0 @@
--/**
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef PURPLE_JABBER_GOOGLE_PRESENCE_H_
--#define PURPLE_JABBER_GOOGLE_PRESENCE_H_
--
--#include "jabber.h"
--#include "buddy.h"
--#include "status.h"
--
--void jabber_google_presence_incoming(JabberStream *js, const char *who, JabberBuddyResource *jbr);
--char *jabber_google_presence_outgoing(PurpleStatus *tune);
--
--
--#endif /* PURPLE_JABBER_GOOGLE_PRESENCE_H_ */
-\ No newline at end of file
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/google_roster.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_roster.c
---- pidgin-2.10.7/libpurple/protocols/jabber/google/google_roster.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_roster.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,206 +0,0 @@
--/**
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "google_roster.h"
--#include "jabber.h"
--#include "presence.h"
--#include "debug.h"
--#include "xmlnode.h"
--
--void jabber_google_roster_outgoing(JabberStream *js, xmlnode *query, xmlnode *item)
--{
-- PurpleAccount *account = purple_connection_get_account(js->gc);
-- GSList *list = account->deny;
-- const char *jid = xmlnode_get_attrib(item, "jid");
-- char *jid_norm = (char *)jabber_normalize(account, jid);
--
-- while (list) {
-- if (!strcmp(jid_norm, (char*)list->data)) {
-- xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER);
-- xmlnode_set_attrib(query, "gr:ext", "2");
-- xmlnode_set_attrib(item, "gr:t", "B");
-- return;
-- }
-- list = list->next;
-- }
--}
--
--gboolean jabber_google_roster_incoming(JabberStream *js, xmlnode *item)
--{
-- PurpleAccount *account = purple_connection_get_account(js->gc);
-- const char *jid = xmlnode_get_attrib(item, "jid");
-- gboolean on_block_list = FALSE;
--
-- char *jid_norm;
--
-- const char *grt = xmlnode_get_attrib_with_namespace(item, "t", NS_GOOGLE_ROSTER);
-- const char *subscription = xmlnode_get_attrib(item, "subscription");
-- const char *ask = xmlnode_get_attrib(item, "ask");
--
-- if ((!subscription || !strcmp(subscription, "none")) && !ask) {
-- /* The Google Talk servers will automatically add people from your Gmail address book
-- * with subscription=none. If we see someone with subscription=none, ignore them.
-- */
-- return FALSE;
-- }
--
-- jid_norm = g_strdup(jabber_normalize(account, jid));
--
-- on_block_list = NULL != g_slist_find_custom(account->deny, jid_norm,
-- (GCompareFunc)strcmp);
--
-- if (grt && (*grt == 'H' || *grt == 'h')) {
-- /* Hidden; don't show this buddy. */
-- GSList *buddies = purple_find_buddies(account, jid_norm);
-- if (buddies)
-- purple_debug_info("jabber", "Removing %s from local buddy list\n",
-- jid_norm);
--
-- for ( ; buddies; buddies = g_slist_delete_link(buddies, buddies)) {
-- purple_blist_remove_buddy(buddies->data);
-- }
--
-- g_free(jid_norm);
-- return FALSE;
-- }
--
-- if (!on_block_list && (grt && (*grt == 'B' || *grt == 'b'))) {
-- purple_debug_info("jabber", "Blocking %s\n", jid_norm);
-- purple_privacy_deny_add(account, jid_norm, TRUE);
-- } else if (on_block_list && (!grt || (*grt != 'B' && *grt != 'b' ))){
-- purple_debug_info("jabber", "Unblocking %s\n", jid_norm);
-- purple_privacy_deny_remove(account, jid_norm, TRUE);
-- }
--
-- g_free(jid_norm);
-- return TRUE;
--}
--
--void jabber_google_roster_add_deny(JabberStream *js, const char *who)
--{
-- PurpleAccount *account;
-- GSList *buddies;
-- JabberIq *iq;
-- xmlnode *query;
-- xmlnode *item;
-- xmlnode *group;
-- PurpleBuddy *b;
-- JabberBuddy *jb;
-- const char *balias;
--
-- jb = jabber_buddy_find(js, who, TRUE);
--
-- account = purple_connection_get_account(js->gc);
-- buddies = purple_find_buddies(account, who);
-- if(!buddies)
-- return;
--
-- b = buddies->data;
--
-- iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster");
--
-- query = xmlnode_get_child(iq->node, "query");
-- item = xmlnode_new_child(query, "item");
--
-- while(buddies) {
-- PurpleGroup *g;
--
-- b = buddies->data;
-- g = purple_buddy_get_group(b);
--
-- group = xmlnode_new_child(item, "group");
-- xmlnode_insert_data(group, purple_group_get_name(g), -1);
--
-- buddies = buddies->next;
-- }
--
-- balias = purple_buddy_get_local_buddy_alias(b);
-- xmlnode_set_attrib(item, "jid", who);
-- xmlnode_set_attrib(item, "name", balias ? balias : "");
-- xmlnode_set_attrib(item, "gr:t", "B");
-- xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER);
-- xmlnode_set_attrib(query, "gr:ext", "2");
--
-- jabber_iq_send(iq);
--
-- /* Synthesize a sign-off */
-- if (jb) {
-- JabberBuddyResource *jbr;
-- GList *l = jb->resources;
-- while (l) {
-- jbr = l->data;
-- if (jbr && jbr->name)
-- {
-- purple_debug_misc("jabber", "Removing resource %s\n", jbr->name);
-- jabber_buddy_remove_resource(jb, jbr->name);
-- }
-- l = l->next;
-- }
-- }
--
-- purple_prpl_got_user_status(account, who, "offline", NULL);
--}
--
--void jabber_google_roster_rem_deny(JabberStream *js, const char *who)
--{
-- GSList *buddies;
-- JabberIq *iq;
-- xmlnode *query;
-- xmlnode *item;
-- xmlnode *group;
-- PurpleBuddy *b;
-- const char *balias;
--
-- buddies = purple_find_buddies(purple_connection_get_account(js->gc), who);
-- if(!buddies)
-- return;
--
-- b = buddies->data;
--
-- iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster");
--
-- query = xmlnode_get_child(iq->node, "query");
-- item = xmlnode_new_child(query, "item");
--
-- while(buddies) {
-- PurpleGroup *g;
--
-- b = buddies->data;
-- g = purple_buddy_get_group(b);
--
-- group = xmlnode_new_child(item, "group");
-- xmlnode_insert_data(group, purple_group_get_name(g), -1);
--
-- buddies = buddies->next;
-- }
--
-- balias = purple_buddy_get_local_buddy_alias(b);
-- xmlnode_set_attrib(item, "jid", who);
-- xmlnode_set_attrib(item, "name", balias ? balias : "");
-- xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER);
-- xmlnode_set_attrib(query, "gr:ext", "2");
--
-- jabber_iq_send(iq);
--
-- /* See if he's online */
-- jabber_presence_subscription_set(js, who, "probe");
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/google_roster.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_roster.h
---- pidgin-2.10.7/libpurple/protocols/jabber/google/google_roster.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_roster.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,37 +0,0 @@
--/**
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef PURPLE_JABBER_GOOGLE_ROSTER_H_
--#define PURPLE_JABBER_GOOGLE_ROSTER_H_
--
--#include "jabber.h"
--
--void jabber_google_roster_outgoing(JabberStream *js, xmlnode *query, xmlnode *item);
--
--/* Returns FALSE if this should short-circuit processing of this roster item, or TRUE
-- * if this roster item should continue to be processed
-- */
--gboolean jabber_google_roster_incoming(JabberStream *js, xmlnode *item);
--
--void jabber_google_roster_add_deny(JabberStream *js, const char *who);
--void jabber_google_roster_rem_deny(JabberStream *js, const char *who);
--
--
--#endif /* PURPLE_JABBER_GOOGLE_ROSTER_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/google_session.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_session.c
---- pidgin-2.10.7/libpurple/protocols/jabber/google/google_session.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_session.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,866 +0,0 @@
--/**
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--#include "google_session.h"
--#include "relay.h"
--
--#include "jingle/jingle.h"
--
--#ifdef USE_VV
--
--typedef struct {
-- PurpleMedia *media;
-- gboolean video;
-- GList *remote_audio_candidates; /* list of PurpleMediaCandidate */
-- GList *remote_video_candidates; /* list of PurpleMediaCandidate */
-- gboolean added_streams; /* this indicates if the streams have been
-- to media (ie. after getting relay credentials */
--} GoogleAVSessionData;
--
--static gboolean
--google_session_id_equal(gconstpointer a, gconstpointer b)
--{
-- GoogleSessionId *c = (GoogleSessionId*)a;
-- GoogleSessionId *d = (GoogleSessionId*)b;
--
-- return !strcmp(c->id, d->id) && !strcmp(c->initiator, d->initiator);
--}
--
--static void
--google_session_destroy(GoogleSession *session)
--{
-- GoogleAVSessionData *session_data =
-- (GoogleAVSessionData *) session->session_data;
-- g_free(session->id.id);
-- g_free(session->id.initiator);
-- g_free(session->remote_jid);
--
-- if (session_data->remote_audio_candidates)
-- purple_media_candidate_list_free(session_data->remote_audio_candidates);
--
-- if (session_data->remote_video_candidates)
-- purple_media_candidate_list_free(session_data->remote_video_candidates);
--
-- if (session->description)
-- xmlnode_free(session->description);
--
-- g_free(session->session_data);
-- g_free(session);
--}
--
--static xmlnode *
--google_session_create_xmlnode(GoogleSession *session, const char *type)
--{
-- xmlnode *node = xmlnode_new("session");
-- xmlnode_set_namespace(node, NS_GOOGLE_SESSION);
-- xmlnode_set_attrib(node, "id", session->id.id);
-- xmlnode_set_attrib(node, "initiator", session->id.initiator);
-- xmlnode_set_attrib(node, "type", type);
-- return node;
--}
--
--static void
--google_session_send_candidates(PurpleMedia *media, gchar *session_id,
-- gchar *participant, GoogleSession *session)
--{
-- PurpleMedia *session_media =
-- ((GoogleAVSessionData *) session->session_data)->media;
-- GList *candidates =
-- purple_media_get_local_candidates(session_media, session_id,
-- session->remote_jid);
-- GList *iter;
-- PurpleMediaCandidate *transport;
-- gboolean video = FALSE;
--
-- if (!strcmp(session_id, "google-video"))
-- video = TRUE;
--
-- for (iter = candidates; iter; iter = iter->next) {
-- JabberIq *iq;
-- gchar *ip, *port, *username, *password;
-- gchar pref[16];
-- PurpleMediaCandidateType type;
-- xmlnode *sess;
-- xmlnode *candidate;
-- guint component_id;
-- transport = PURPLE_MEDIA_CANDIDATE(iter->data);
-- component_id = purple_media_candidate_get_component_id(
-- transport);
--
-- iq = jabber_iq_new(session->js, JABBER_IQ_SET);
-- sess = google_session_create_xmlnode(session, "candidates");
-- xmlnode_insert_child(iq->node, sess);
-- xmlnode_set_attrib(iq->node, "to", session->remote_jid);
--
-- candidate = xmlnode_new("candidate");
--
-- ip = purple_media_candidate_get_ip(transport);
-- port = g_strdup_printf("%d",
-- purple_media_candidate_get_port(transport));
-- g_ascii_dtostr(pref, 16,
-- purple_media_candidate_get_priority(transport) / 1000.0);
-- username = purple_media_candidate_get_username(transport);
-- password = purple_media_candidate_get_password(transport);
-- type = purple_media_candidate_get_candidate_type(transport);
--
-- xmlnode_set_attrib(candidate, "address", ip);
-- xmlnode_set_attrib(candidate, "port", port);
-- xmlnode_set_attrib(candidate, "name",
-- component_id == PURPLE_MEDIA_COMPONENT_RTP ?
-- video ? "video_rtp" : "rtp" :
-- component_id == PURPLE_MEDIA_COMPONENT_RTCP ?
-- video ? "video_rtcp" : "rtcp" : "none");
-- xmlnode_set_attrib(candidate, "username", username);
-- /*
-- * As of this writing, Farsight 2 in Google compatibility
-- * mode doesn't provide a password. The Gmail client
-- * requires this to be set.
-- */
-- xmlnode_set_attrib(candidate, "password",
-- password != NULL ? password : "");
-- xmlnode_set_attrib(candidate, "preference", pref);
-- xmlnode_set_attrib(candidate, "protocol",
-- purple_media_candidate_get_protocol(transport)
-- == PURPLE_MEDIA_NETWORK_PROTOCOL_UDP ?
-- "udp" : "tcp");
-- xmlnode_set_attrib(candidate, "type", type ==
-- PURPLE_MEDIA_CANDIDATE_TYPE_HOST ? "local" :
-- type ==
-- PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX ? "stun" :
-- type ==
-- PURPLE_MEDIA_CANDIDATE_TYPE_RELAY ? "relay" :
-- NULL);
-- xmlnode_set_attrib(candidate, "generation", "0");
-- xmlnode_set_attrib(candidate, "network", "0");
-- xmlnode_insert_child(sess, candidate);
--
-- g_free(ip);
-- g_free(port);
-- g_free(username);
-- g_free(password);
--
-- jabber_iq_send(iq);
-- }
-- purple_media_candidate_list_free(candidates);
--}
--
--static void
--google_session_ready(GoogleSession *session)
--{
-- PurpleMedia *media =
-- ((GoogleAVSessionData *)session->session_data)->media;
-- gboolean video =
-- ((GoogleAVSessionData *)session->session_data)->video;
-- if (purple_media_codecs_ready(media, NULL) &&
-- purple_media_candidates_prepared(media, NULL, NULL)) {
-- gchar *me = g_strdup_printf("%s@%s/%s",
-- session->js->user->node,
-- session->js->user->domain,
-- session->js->user->resource);
-- JabberIq *iq;
-- xmlnode *sess, *desc, *payload;
-- GList *codecs, *iter;
-- gboolean is_initiator = !strcmp(session->id.initiator, me);
--
-- if (!is_initiator &&
-- !purple_media_accepted(media, NULL, NULL)) {
-- g_free(me);
-- return;
-- }
--
-- iq = jabber_iq_new(session->js, JABBER_IQ_SET);
--
-- if (is_initiator) {
-- xmlnode_set_attrib(iq->node, "to", session->remote_jid);
-- xmlnode_set_attrib(iq->node, "from", session->id.initiator);
-- sess = google_session_create_xmlnode(session, "initiate");
-- } else {
-- google_session_send_candidates(media,
-- "google-voice", session->remote_jid,
-- session);
-- google_session_send_candidates(media,
-- "google-video", session->remote_jid,
-- session);
-- xmlnode_set_attrib(iq->node, "to", session->remote_jid);
-- xmlnode_set_attrib(iq->node, "from", me);
-- sess = google_session_create_xmlnode(session, "accept");
-- }
-- xmlnode_insert_child(iq->node, sess);
-- desc = xmlnode_new_child(sess, "description");
-- if (video)
-- xmlnode_set_namespace(desc, NS_GOOGLE_SESSION_VIDEO);
-- else
-- xmlnode_set_namespace(desc, NS_GOOGLE_SESSION_PHONE);
--
-- codecs = purple_media_get_codecs(media, "google-video");
--
-- for (iter = codecs; iter; iter = g_list_next(iter)) {
-- PurpleMediaCodec *codec = (PurpleMediaCodec*)iter->data;
-- gchar *id = g_strdup_printf("%d",
-- purple_media_codec_get_id(codec));
-- gchar *encoding_name =
-- purple_media_codec_get_encoding_name(codec);
-- payload = xmlnode_new_child(desc, "payload-type");
-- xmlnode_set_attrib(payload, "id", id);
-- xmlnode_set_attrib(payload, "name", encoding_name);
-- xmlnode_set_attrib(payload, "width", "320");
-- xmlnode_set_attrib(payload, "height", "200");
-- xmlnode_set_attrib(payload, "framerate", "30");
-- g_free(encoding_name);
-- g_free(id);
-- }
-- purple_media_codec_list_free(codecs);
--
-- codecs = purple_media_get_codecs(media, "google-voice");
--
-- for (iter = codecs; iter; iter = g_list_next(iter)) {
-- PurpleMediaCodec *codec = (PurpleMediaCodec*)iter->data;
-- gchar *id = g_strdup_printf("%d",
-- purple_media_codec_get_id(codec));
-- gchar *encoding_name =
-- purple_media_codec_get_encoding_name(codec);
-- gchar *clock_rate = g_strdup_printf("%d",
-- purple_media_codec_get_clock_rate(codec));
-- payload = xmlnode_new_child(desc, "payload-type");
-- if (video)
-- xmlnode_set_namespace(payload, NS_GOOGLE_SESSION_PHONE);
-- xmlnode_set_attrib(payload, "id", id);
-- /*
-- * Hack to make Gmail accept speex as the codec.
-- * It shouldn't have to be case sensitive.
-- */
-- if (purple_strequal(encoding_name, "SPEEX"))
-- xmlnode_set_attrib(payload, "name", "speex");
-- else
-- xmlnode_set_attrib(payload, "name", encoding_name);
-- xmlnode_set_attrib(payload, "clockrate", clock_rate);
-- g_free(clock_rate);
-- g_free(encoding_name);
-- g_free(id);
-- }
-- purple_media_codec_list_free(codecs);
--
-- jabber_iq_send(iq);
--
-- if (is_initiator) {
-- google_session_send_candidates(media,
-- "google-voice", session->remote_jid,
-- session);
-- google_session_send_candidates(media,
-- "google-video", session->remote_jid,
-- session);
-- }
--
-- g_signal_handlers_disconnect_by_func(G_OBJECT(media),
-- G_CALLBACK(google_session_ready), session);
-- }
--}
--
--static void
--google_session_state_changed_cb(PurpleMedia *media, PurpleMediaState state,
-- gchar *sid, gchar *name, GoogleSession *session)
--{
-- if (sid == NULL && name == NULL) {
-- if (state == PURPLE_MEDIA_STATE_END) {
-- google_session_destroy(session);
-- }
-- }
--}
--
--static void
--google_session_stream_info_cb(PurpleMedia *media, PurpleMediaInfoType type,
-- gchar *sid, gchar *name, gboolean local,
-- GoogleSession *session)
--{
-- if (sid != NULL || name != NULL)
-- return;
--
-- if (type == PURPLE_MEDIA_INFO_HANGUP) {
-- xmlnode *sess;
-- JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);
--
-- xmlnode_set_attrib(iq->node, "to", session->remote_jid);
-- sess = google_session_create_xmlnode(session, "terminate");
-- xmlnode_insert_child(iq->node, sess);
--
-- jabber_iq_send(iq);
-- } else if (type == PURPLE_MEDIA_INFO_REJECT) {
-- xmlnode *sess;
-- JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);
--
-- xmlnode_set_attrib(iq->node, "to", session->remote_jid);
-- sess = google_session_create_xmlnode(session, "reject");
-- xmlnode_insert_child(iq->node, sess);
--
-- jabber_iq_send(iq);
-- } else if (type == PURPLE_MEDIA_INFO_ACCEPT && local == TRUE) {
-- google_session_ready(session);
-- }
--}
--
--static GParameter *
--jabber_google_session_get_params(JabberStream *js, const gchar *relay_ip,
-- guint16 relay_udp, guint16 relay_tcp, guint16 relay_ssltcp,
-- const gchar *relay_username, const gchar *relay_password, guint *num)
--{
-- guint num_params;
-- GParameter *params =
-- jingle_get_params(js, relay_ip, relay_udp, relay_tcp, relay_ssltcp,
-- relay_username, relay_password, &num_params);
-- GParameter *new_params = g_new0(GParameter, num_params + 1);
--
-- memcpy(new_params, params, sizeof(GParameter) * num_params);
--
-- purple_debug_info("jabber", "setting Google jingle compatibility param\n");
-- new_params[num_params].name = "compatibility-mode";
-- g_value_init(&new_params[num_params].value, G_TYPE_UINT);
-- g_value_set_uint(&new_params[num_params].value, 1); /* NICE_COMPATIBILITY_GOOGLE */
--
-- g_free(params);
-- *num = num_params + 1;
-- return new_params;
--}
--
--
--static void
--jabber_google_relay_response_session_initiate_cb(GoogleSession *session,
-- const gchar *relay_ip, guint relay_udp, guint relay_tcp, guint relay_ssltcp,
-- const gchar *relay_username, const gchar *relay_password)
--{
-- GParameter *params;
-- guint num_params;
-- JabberStream *js = session->js;
-- GoogleAVSessionData *session_data =
-- (GoogleAVSessionData *) session->session_data;
--
-- session_data->media = purple_media_manager_create_media(
-- purple_media_manager_get(),
-- purple_connection_get_account(js->gc),
-- "fsrtpconference", session->remote_jid, TRUE);
--
-- purple_media_set_prpl_data(session_data->media, session);
--
-- g_signal_connect_swapped(G_OBJECT(session_data->media),
-- "candidates-prepared",
-- G_CALLBACK(google_session_ready), session);
-- g_signal_connect_swapped(G_OBJECT(session_data->media), "codecs-changed",
-- G_CALLBACK(google_session_ready), session);
-- g_signal_connect(G_OBJECT(session_data->media), "state-changed",
-- G_CALLBACK(google_session_state_changed_cb), session);
-- g_signal_connect(G_OBJECT(session_data->media), "stream-info",
-- G_CALLBACK(google_session_stream_info_cb), session);
--
-- params =
-- jabber_google_session_get_params(js, relay_ip, relay_udp, relay_tcp,
-- relay_ssltcp, relay_username, relay_password, &num_params);
--
-- if (purple_media_add_stream(session_data->media, "google-voice",
-- session->remote_jid, PURPLE_MEDIA_AUDIO,
-- TRUE, "nice", num_params, params) == FALSE ||
-- (session_data->video && purple_media_add_stream(
-- session_data->media, "google-video",
-- session->remote_jid, PURPLE_MEDIA_VIDEO,
-- TRUE, "nice", num_params, params) == FALSE)) {
-- purple_media_error(session_data->media, "Error adding stream.");
-- purple_media_end(session_data->media, NULL, NULL);
-- } else {
-- session_data->added_streams = TRUE;
-- }
--
-- g_free(params);
--}
--
--
--gboolean
--jabber_google_session_initiate(JabberStream *js, const gchar *who, PurpleMediaSessionType type)
--{
-- GoogleSession *session;
-- JabberBuddy *jb;
-- JabberBuddyResource *jbr;
-- gchar *jid;
-- GoogleAVSessionData *session_data = NULL;
--
-- /* construct JID to send to */
-- jb = jabber_buddy_find(js, who, FALSE);
-- if (!jb) {
-- purple_debug_error("jingle-rtp",
-- "Could not find Jabber buddy\n");
-- return FALSE;
-- }
-- jbr = jabber_buddy_find_resource(jb, NULL);
-- if (!jbr) {
-- purple_debug_error("jingle-rtp",
-- "Could not find buddy's resource\n");
-- }
--
-- if ((strchr(who, '/') == NULL) && jbr && (jbr->name != NULL)) {
-- jid = g_strdup_printf("%s/%s", who, jbr->name);
-- } else {
-- jid = g_strdup(who);
-- }
--
-- session = g_new0(GoogleSession, 1);
-- session->id.id = jabber_get_next_id(js);
-- session->id.initiator = g_strdup_printf("%s@%s/%s", js->user->node,
-- js->user->domain, js->user->resource);
-- session->state = SENT_INITIATE;
-- session->js = js;
-- session->remote_jid = jid;
-- session_data = g_new0(GoogleAVSessionData, 1);
-- session->session_data = session_data;
--
-- if (type & PURPLE_MEDIA_VIDEO)
-- session_data->video = TRUE;
--
-- /* if we got a relay token and relay host in google:jingleinfo, issue an
-- HTTP request to get that data */
-- if (js->google_relay_host && js->google_relay_token) {
-- jabber_google_do_relay_request(js, session,
-- jabber_google_relay_response_session_initiate_cb);
-- } else {
-- jabber_google_relay_response_session_initiate_cb(session, NULL, 0, 0, 0,
-- NULL, NULL);
-- }
--
-- /* we don't actually know yet wether it succeeded... maybe this is very
-- wrong... */
-- return TRUE;
--}
--
--static void
--jabber_google_relay_response_session_handle_initiate_cb(GoogleSession *session,
-- const gchar *relay_ip, guint relay_udp, guint relay_tcp, guint relay_ssltcp,
-- const gchar *relay_username, const gchar *relay_password)
--{
-- GParameter *params;
-- guint num_params;
-- JabberStream *js = session->js;
-- xmlnode *codec_element;
-- const gchar *xmlns;
-- PurpleMediaCodec *codec;
-- GList *video_codecs = NULL;
-- GList *codecs = NULL;
-- JabberIq *result;
-- GoogleAVSessionData *session_data =
-- (GoogleAVSessionData *) session->session_data;
--
-- params =
-- jabber_google_session_get_params(js, relay_ip, relay_udp, relay_tcp,
-- relay_ssltcp, relay_username, relay_password, &num_params);
--
-- if (purple_media_add_stream(session_data->media, "google-voice",
-- session->remote_jid, PURPLE_MEDIA_AUDIO, FALSE,
-- "nice", num_params, params) == FALSE ||
-- (session_data->video && purple_media_add_stream(
-- session_data->media, "google-video",
-- session->remote_jid, PURPLE_MEDIA_VIDEO,
-- FALSE, "nice", num_params, params) == FALSE)) {
-- purple_media_error(session_data->media, "Error adding stream.");
-- purple_media_stream_info(session_data->media,
-- PURPLE_MEDIA_INFO_REJECT, NULL, NULL, TRUE);
-- } else {
-- /* successfully added stream(s) */
-- session_data->added_streams = TRUE;
--
-- if (session_data->remote_audio_candidates) {
-- purple_media_add_remote_candidates(session_data->media,
-- "google-voice", session->remote_jid,
-- session_data->remote_audio_candidates);
-- purple_media_candidate_list_free(session_data->remote_audio_candidates);
-- session_data->remote_audio_candidates = NULL;
-- }
-- if (session_data->remote_video_candidates) {
-- purple_media_add_remote_candidates(session_data->media,
-- "google-video", session->remote_jid,
-- session_data->remote_video_candidates);
-- purple_media_candidate_list_free(session_data->remote_video_candidates);
-- session_data->remote_video_candidates = NULL;
-- }
-- }
--
-- g_free(params);
--
-- for (codec_element = xmlnode_get_child(session->description, "payload-type");
-- codec_element; codec_element = codec_element->next) {
-- const char *id, *encoding_name, *clock_rate,
-- *width, *height, *framerate;
-- gboolean video;
-- if (codec_element->name &&
-- strcmp(codec_element->name, "payload-type"))
-- continue;
--
-- xmlns = xmlnode_get_namespace(codec_element);
-- encoding_name = xmlnode_get_attrib(codec_element, "name");
-- id = xmlnode_get_attrib(codec_element, "id");
--
-- if (!session_data->video ||
-- (xmlns && !strcmp(xmlns, NS_GOOGLE_SESSION_PHONE))) {
-- clock_rate = xmlnode_get_attrib(
-- codec_element, "clockrate");
-- video = FALSE;
-- } else {
-- width = xmlnode_get_attrib(codec_element, "width");
-- height = xmlnode_get_attrib(codec_element, "height");
-- framerate = xmlnode_get_attrib(
-- codec_element, "framerate");
-- clock_rate = "90000";
-- video = TRUE;
-- }
--
-- if (id) {
-- codec = purple_media_codec_new(atoi(id), encoding_name,
-- video ? PURPLE_MEDIA_VIDEO :
-- PURPLE_MEDIA_AUDIO,
-- clock_rate ? atoi(clock_rate) : 0);
-- if (video)
-- video_codecs = g_list_append(
-- video_codecs, codec);
-- else
-- codecs = g_list_append(codecs, codec);
-- }
-- }
--
-- if (codecs)
-- purple_media_set_remote_codecs(session_data->media, "google-voice",
-- session->remote_jid, codecs);
-- if (video_codecs)
-- purple_media_set_remote_codecs(session_data->media, "google-video",
-- session->remote_jid, video_codecs);
--
-- purple_media_codec_list_free(codecs);
-- purple_media_codec_list_free(video_codecs);
--
-- result = jabber_iq_new(js, JABBER_IQ_RESULT);
-- jabber_iq_set_id(result, session->iq_id);
-- xmlnode_set_attrib(result->node, "to", session->remote_jid);
-- jabber_iq_send(result);
--}
--
--static gboolean
--google_session_handle_initiate(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id)
--{
-- const gchar *xmlns;
-- GoogleAVSessionData *session_data =
-- (GoogleAVSessionData *) session->session_data;
--
-- if (session->state != UNINIT) {
-- purple_debug_error("jabber", "Received initiate for active session.\n");
-- return FALSE;
-- }
--
-- session->description = xmlnode_copy(xmlnode_get_child(sess, "description"));
-- xmlns = xmlnode_get_namespace(session->description);
--
-- if (purple_strequal(xmlns, NS_GOOGLE_SESSION_PHONE))
-- session_data->video = FALSE;
-- else if (purple_strequal(xmlns, NS_GOOGLE_SESSION_VIDEO))
-- session_data->video = TRUE;
-- else {
-- purple_debug_error("jabber", "Received initiate with "
-- "invalid namespace %s.\n", xmlns);
-- return FALSE;
-- }
--
-- session_data->media = purple_media_manager_create_media(
-- purple_media_manager_get(),
-- purple_connection_get_account(js->gc),
-- "fsrtpconference", session->remote_jid, FALSE);
--
-- purple_media_set_prpl_data(session_data->media, session);
--
-- g_signal_connect_swapped(G_OBJECT(session_data->media),
-- "candidates-prepared",
-- G_CALLBACK(google_session_ready), session);
-- g_signal_connect_swapped(G_OBJECT(session_data->media), "codecs-changed",
-- G_CALLBACK(google_session_ready), session);
-- g_signal_connect(G_OBJECT(session_data->media), "state-changed",
-- G_CALLBACK(google_session_state_changed_cb), session);
-- g_signal_connect(G_OBJECT(session_data->media), "stream-info",
-- G_CALLBACK(google_session_stream_info_cb), session);
--
-- session->iq_id = g_strdup(iq_id);
--
-- if (js->google_relay_host && js->google_relay_token) {
-- jabber_google_do_relay_request(js, session,
-- jabber_google_relay_response_session_handle_initiate_cb);
-- } else {
-- jabber_google_relay_response_session_handle_initiate_cb(session, NULL,
-- 0, 0, 0, NULL, NULL);
-- }
--
-- return TRUE;
--}
--
--
--static void
--google_session_handle_candidates(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id)
--{
-- JabberIq *result;
-- GList *list = NULL, *video_list = NULL;
-- xmlnode *cand;
-- static int name = 0;
-- char n[4];
-- GoogleAVSessionData *session_data =
-- (GoogleAVSessionData *) session->session_data;
--
-- for (cand = xmlnode_get_child(sess, "candidate"); cand;
-- cand = xmlnode_get_next_twin(cand)) {
-- PurpleMediaCandidate *info;
-- const gchar *cname = xmlnode_get_attrib(cand, "name");
-- const gchar *type = xmlnode_get_attrib(cand, "type");
-- const gchar *protocol = xmlnode_get_attrib(cand, "protocol");
-- const gchar *address = xmlnode_get_attrib(cand, "address");
-- const gchar *port = xmlnode_get_attrib(cand, "port");
-- const gchar *preference = xmlnode_get_attrib(cand, "preference");
-- guint component_id;
--
-- if (cname && type && address && port) {
-- PurpleMediaCandidateType candidate_type;
-- guint prio = preference ? g_ascii_strtod(preference, NULL) * 1000 : 0;
--
-- g_snprintf(n, sizeof(n), "S%d", name++);
--
-- if (g_str_equal(type, "local"))
-- candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_HOST;
-- else if (g_str_equal(type, "stun"))
-- candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX;
-- else if (g_str_equal(type, "relay"))
-- candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_RELAY;
-- else
-- candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_HOST;
--
-- if (purple_strequal(cname, "rtcp") ||
-- purple_strequal(cname, "video_rtcp"))
-- component_id = PURPLE_MEDIA_COMPONENT_RTCP;
-- else
-- component_id = PURPLE_MEDIA_COMPONENT_RTP;
--
-- info = purple_media_candidate_new(n, component_id,
-- candidate_type,
-- purple_strequal(protocol, "udp") ?
-- PURPLE_MEDIA_NETWORK_PROTOCOL_UDP :
-- PURPLE_MEDIA_NETWORK_PROTOCOL_TCP,
-- address,
-- atoi(port));
-- g_object_set(info, "username", xmlnode_get_attrib(cand, "username"),
-- "password", xmlnode_get_attrib(cand, "password"),
-- "priority", prio, NULL);
-- if (!strncmp(cname, "video_", 6)) {
-- if (session_data->added_streams) {
-- video_list = g_list_append(video_list, info);
-- } else {
-- session_data->remote_video_candidates =
-- g_list_append(session_data->remote_video_candidates,
-- info);
-- }
-- } else {
-- if (session_data->added_streams) {
-- list = g_list_append(list, info);
-- } else {
-- session_data->remote_audio_candidates =
-- g_list_append(session_data->remote_audio_candidates,
-- info);
-- }
-- }
-- }
-- }
--
-- if (list) {
-- purple_media_add_remote_candidates(session_data->media, "google-voice",
-- session->remote_jid, list);
-- purple_media_candidate_list_free(list);
-- }
-- if (video_list) {
-- purple_media_add_remote_candidates(session_data->media, "google-video",
-- session->remote_jid, video_list);
-- purple_media_candidate_list_free(video_list);
-- }
--
-- result = jabber_iq_new(js, JABBER_IQ_RESULT);
-- jabber_iq_set_id(result, iq_id);
-- xmlnode_set_attrib(result->node, "to", session->remote_jid);
-- jabber_iq_send(result);
--}
--
--static void
--google_session_handle_accept(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id)
--{
-- xmlnode *desc_element = xmlnode_get_child(sess, "description");
-- xmlnode *codec_element = xmlnode_get_child(
-- desc_element, "payload-type");
-- GList *codecs = NULL, *video_codecs = NULL;
-- JabberIq *result = NULL;
-- const gchar *xmlns = xmlnode_get_namespace(desc_element);
-- gboolean video = (xmlns && !strcmp(xmlns, NS_GOOGLE_SESSION_VIDEO));
-- GoogleAVSessionData *session_data =
-- (GoogleAVSessionData *) session->session_data;
--
-- for (; codec_element; codec_element = codec_element->next) {
-- const gchar *xmlns, *encoding_name, *id,
-- *clock_rate, *width, *height, *framerate;
-- gboolean video_codec = FALSE;
--
-- if (!purple_strequal(codec_element->name, "payload-type"))
-- continue;
--
-- xmlns = xmlnode_get_namespace(codec_element);
-- encoding_name = xmlnode_get_attrib(codec_element, "name");
-- id = xmlnode_get_attrib(codec_element, "id");
--
-- if (!video || purple_strequal(xmlns, NS_GOOGLE_SESSION_PHONE))
-- clock_rate = xmlnode_get_attrib(
-- codec_element, "clockrate");
-- else {
-- clock_rate = "90000";
-- width = xmlnode_get_attrib(codec_element, "width");
-- height = xmlnode_get_attrib(codec_element, "height");
-- framerate = xmlnode_get_attrib(
-- codec_element, "framerate");
-- video_codec = TRUE;
-- }
--
-- if (id && encoding_name) {
-- PurpleMediaCodec *codec = purple_media_codec_new(
-- atoi(id), encoding_name,
-- video_codec ? PURPLE_MEDIA_VIDEO :
-- PURPLE_MEDIA_AUDIO,
-- clock_rate ? atoi(clock_rate) : 0);
-- if (video_codec)
-- video_codecs = g_list_append(
-- video_codecs, codec);
-- else
-- codecs = g_list_append(codecs, codec);
-- }
-- }
--
-- if (codecs)
-- purple_media_set_remote_codecs(session_data->media, "google-voice",
-- session->remote_jid, codecs);
-- if (video_codecs)
-- purple_media_set_remote_codecs(session_data->media, "google-video",
-- session->remote_jid, video_codecs);
--
-- purple_media_stream_info(session_data->media, PURPLE_MEDIA_INFO_ACCEPT,
-- NULL, NULL, FALSE);
--
-- result = jabber_iq_new(js, JABBER_IQ_RESULT);
-- jabber_iq_set_id(result, iq_id);
-- xmlnode_set_attrib(result->node, "to", session->remote_jid);
-- jabber_iq_send(result);
--}
--
--static void
--google_session_handle_reject(JabberStream *js, GoogleSession *session, xmlnode *sess)
--{
-- GoogleAVSessionData *session_data =
-- (GoogleAVSessionData *) session->session_data;
-- purple_media_end(session_data->media, NULL, NULL);
--}
--
--static void
--google_session_handle_terminate(JabberStream *js, GoogleSession *session, xmlnode *sess)
--{
-- GoogleAVSessionData *session_data =
-- (GoogleAVSessionData *) session->session_data;
-- purple_media_end(session_data->media, NULL, NULL);
--}
--
--static void
--google_session_parse_iq(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id)
--{
-- const char *type = xmlnode_get_attrib(sess, "type");
--
-- if (!strcmp(type, "initiate")) {
-- google_session_handle_initiate(js, session, sess, iq_id);
-- } else if (!strcmp(type, "accept")) {
-- google_session_handle_accept(js, session, sess, iq_id);
-- } else if (!strcmp(type, "reject")) {
-- google_session_handle_reject(js, session, sess);
-- } else if (!strcmp(type, "terminate")) {
-- google_session_handle_terminate(js, session, sess);
-- } else if (!strcmp(type, "candidates")) {
-- google_session_handle_candidates(js, session, sess, iq_id);
-- }
--}
--
--void
--jabber_google_session_parse(JabberStream *js, const char *from,
-- JabberIqType type, const char *iq_id,
-- xmlnode *session_node)
--{
-- GoogleSession *session = NULL;
-- GoogleSessionId id;
--
-- xmlnode *desc_node;
--
-- GList *iter = NULL;
--
-- if (type != JABBER_IQ_SET)
-- return;
--
-- id.id = (gchar*)xmlnode_get_attrib(session_node, "id");
-- if (!id.id)
-- return;
--
-- id.initiator = (gchar*)xmlnode_get_attrib(session_node, "initiator");
-- if (!id.initiator)
-- return;
--
-- iter = purple_media_manager_get_media_by_account(
-- purple_media_manager_get(),
-- purple_connection_get_account(js->gc));
-- for (; iter; iter = g_list_delete_link(iter, iter)) {
-- GoogleSession *gsession =
-- purple_media_get_prpl_data(iter->data);
-- if (google_session_id_equal(&(gsession->id), &id)) {
-- session = gsession;
-- break;
-- }
-- }
-- if (iter != NULL) {
-- g_list_free(iter);
-- }
--
-- if (session) {
-- google_session_parse_iq(js, session, session_node, iq_id);
-- return;
-- }
--
-- /* If the session doesn't exist, this has to be an initiate message */
-- if (strcmp(xmlnode_get_attrib(session_node, "type"), "initiate"))
-- return;
-- desc_node = xmlnode_get_child(session_node, "description");
-- if (!desc_node)
-- return;
-- session = g_new0(GoogleSession, 1);
-- session->id.id = g_strdup(id.id);
-- session->id.initiator = g_strdup(id.initiator);
-- session->state = UNINIT;
-- session->js = js;
-- session->remote_jid = g_strdup(session->id.initiator);
-- session->session_data = g_new0(GoogleAVSessionData, 1);
--
-- google_session_handle_initiate(js, session, session_node, iq_id);
--}
--#endif /* USE_VV */
--
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/google_session.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_session.h
---- pidgin-2.10.7/libpurple/protocols/jabber/google/google_session.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_session.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,56 +0,0 @@
--/**
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef PURPLE_JABBER_GOOGLE_SESSION_H_
--#define PURPLE_JABBER_GOOGLE_SESSION_H_
--
--#include "jabber.h"
--
--typedef struct {
-- char *id;
-- char *initiator;
--} GoogleSessionId;
--
--typedef enum {
-- UNINIT,
-- SENT_INITIATE,
-- RECEIVED_INITIATE,
-- IN_PRORESS,
-- TERMINATED
--} GoogleSessionState;
--
--typedef struct {
-- GoogleSessionId id;
-- GoogleSessionState state;
-- JabberStream *js;
-- char *remote_jid;
-- char *iq_id;
-- xmlnode *description; /* store incoming description through
-- relay credential fetching */
-- gpointer session_data;
--} GoogleSession;
--
--gboolean jabber_google_session_initiate(JabberStream *js, const gchar *who,
-- PurpleMediaSessionType type);
--
--void jabber_google_session_parse(JabberStream *js, const char *from,
-- JabberIqType type, const char *iq, xmlnode *session);
--
--#endif /* PURPLE_JABBER_GOOGLE_SESSION_H_ */
-\ No newline at end of file
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/jingleinfo.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/jingleinfo.c
---- pidgin-2.10.7/libpurple/protocols/jabber/google/jingleinfo.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/jingleinfo.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,176 +0,0 @@
--/**
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--#include "jingleinfo.h"
--
--static void
--jabber_google_stun_lookup_cb(GSList *hosts, gpointer data,
-- const char *error_message)
--{
-- JabberStream *js = (JabberStream *) data;
--
-- if (error_message) {
-- purple_debug_error("jabber", "Google STUN lookup failed: %s\n",
-- error_message);
-- g_slist_free(hosts);
-- js->stun_query = NULL;
-- return;
-- }
--
-- if (hosts && g_slist_next(hosts)) {
-- struct sockaddr *addr = g_slist_next(hosts)->data;
-- char dst[INET6_ADDRSTRLEN];
-- int port;
--
-- if (addr->sa_family == AF_INET6) {
-- inet_ntop(addr->sa_family, &((struct sockaddr_in6 *) addr)->sin6_addr,
-- dst, sizeof(dst));
-- port = ntohs(((struct sockaddr_in6 *) addr)->sin6_port);
-- } else {
-- inet_ntop(addr->sa_family, &((struct sockaddr_in *) addr)->sin_addr,
-- dst, sizeof(dst));
-- port = ntohs(((struct sockaddr_in *) addr)->sin_port);
-- }
--
-- if (js->stun_ip)
-- g_free(js->stun_ip);
-- js->stun_ip = g_strdup(dst);
-- js->stun_port = port;
--
-- purple_debug_info("jabber", "set Google STUN IP/port address: "
-- "%s:%d\n", dst, port);
--
-- /* unmark ongoing query */
-- js->stun_query = NULL;
-- }
--
-- while (hosts != NULL) {
-- hosts = g_slist_delete_link(hosts, hosts);
-- /* Free the address */
-- g_free(hosts->data);
-- hosts = g_slist_delete_link(hosts, hosts);
-- }
--}
--
--static void
--jabber_google_jingle_info_common(JabberStream *js, const char *from,
-- JabberIqType type, xmlnode *query)
--{
-- const xmlnode *stun = xmlnode_get_child(query, "stun");
-- const xmlnode *relay = xmlnode_get_child(query, "relay");
-- gchar *my_bare_jid;
--
-- /*
-- * Make sure that random people aren't sending us STUN servers. Per
-- * http://code.google.com/apis/talk/jep_extensions/jingleinfo.html, these
-- * stanzas are stamped from our bare JID.
-- */
-- if (from) {
-- my_bare_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain);
-- if (!purple_strequal(from, my_bare_jid)) {
-- purple_debug_warning("jabber", "got google:jingleinfo with invalid from (%s)\n",
-- from);
-- g_free(my_bare_jid);
-- return;
-- }
--
-- g_free(my_bare_jid);
-- }
--
-- if (type == JABBER_IQ_ERROR || type == JABBER_IQ_GET)
-- return;
--
-- purple_debug_info("jabber", "got google:jingleinfo\n");
--
-- if (stun) {
-- xmlnode *server = xmlnode_get_child(stun, "server");
--
-- if (server) {
-- const gchar *host = xmlnode_get_attrib(server, "host");
-- const gchar *udp = xmlnode_get_attrib(server, "udp");
--
-- if (host && udp) {
-- PurpleAccount *account;
-- int port = atoi(udp);
-- /* if there, would already be an ongoing query,
-- cancel it */
-- if (js->stun_query)
-- purple_dnsquery_destroy(js->stun_query);
--
-- account = purple_connection_get_account(js->gc);
-- js->stun_query = purple_dnsquery_a_account(account, host, port,
-- jabber_google_stun_lookup_cb, js);
-- }
-- }
-- }
--
-- if (relay) {
-- xmlnode *token = xmlnode_get_child(relay, "token");
-- xmlnode *server = xmlnode_get_child(relay, "server");
--
-- if (token) {
-- gchar *relay_token = xmlnode_get_data(token);
--
-- /* we let js own the string returned from xmlnode_get_data */
-- js->google_relay_token = relay_token;
-- }
--
-- if (server) {
-- js->google_relay_host =
-- g_strdup(xmlnode_get_attrib(server, "host"));
-- }
-- }
--}
--
--static void
--jabber_google_jingle_info_cb(JabberStream *js, const char *from,
-- JabberIqType type, const char *id,
-- xmlnode *packet, gpointer data)
--{
-- xmlnode *query = xmlnode_get_child_with_namespace(packet, "query",
-- NS_GOOGLE_JINGLE_INFO);
--
-- if (query)
-- jabber_google_jingle_info_common(js, from, type, query);
-- else
-- purple_debug_warning("jabber", "Got invalid google:jingleinfo\n");
--}
--
--void
--jabber_google_handle_jingle_info(JabberStream *js, const char *from,
-- JabberIqType type, const char *id,
-- xmlnode *child)
--{
-- jabber_google_jingle_info_common(js, from, type, child);
--}
--
--void
--jabber_google_send_jingle_info(JabberStream *js)
--{
-- JabberIq *jingle_info =
-- jabber_iq_new_query(js, JABBER_IQ_GET, NS_GOOGLE_JINGLE_INFO);
--
-- jabber_iq_set_callback(jingle_info, jabber_google_jingle_info_cb,
-- NULL);
-- purple_debug_info("jabber", "sending google:jingleinfo query\n");
-- jabber_iq_send(jingle_info);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/jingleinfo.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/jingleinfo.h
---- pidgin-2.10.7/libpurple/protocols/jabber/google/jingleinfo.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/jingleinfo.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,32 +0,0 @@
--/**
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef PURPLE_JABBER_GOOGLE_ROSTER_H_
--#define PURPLE_JABBER_GOOGLE_ROSTER_H_
--
--#include "jabber.h"
--
--void jabber_google_handle_jingle_info(JabberStream *js, const char *from,
-- JabberIqType type, const char *id,
-- xmlnode *child);
--void jabber_google_send_jingle_info(JabberStream *js);
--
--
--#endif /* PURPLE_JABBER_GOOGLE_ROSTER_H_ */
-\ No newline at end of file
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/relay.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/relay.c
---- pidgin-2.10.7/libpurple/protocols/jabber/google/relay.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/relay.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,151 +0,0 @@
--/**
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "relay.h"
--
--typedef struct {
-- GoogleSession *session;
-- JabberGoogleRelayCallback *cb;
--} JabberGoogleRelayCallbackData;
--
--static void
--jabber_google_relay_parse_response(const gchar *response, gchar **ip,
-- guint *udp, guint *tcp, guint *ssltcp, gchar **username, gchar **password)
--{
-- gchar **lines = g_strsplit(response, "\n", -1);
-- int i = 0;
--
-- for (; lines[i] ; i++) {
-- gchar *line = lines[i];
-- gchar **parts = g_strsplit(line, "=", 2);
--
-- if (parts[0] && parts[1]) {
-- if (purple_strequal(parts[0], "relay.ip")) {
-- *ip = g_strdup(parts[1]);
-- } else if (purple_strequal(parts[0], "relay.udp_port")) {
-- *udp = atoi(parts[1]);
-- } else if (purple_strequal(parts[0], "relay.tcp_port")) {
-- *tcp = atoi(parts[1]);
-- } else if (purple_strequal(parts[0], "relay.ssltcp_port")) {
-- *ssltcp = atoi(parts[1]);
-- } else if (purple_strequal(parts[0], "username")) {
-- *username = g_strdup(parts[1]);
-- } else if (purple_strequal(parts[0], "password")) {
-- *password = g_strdup(parts[1]);
-- }
-- }
-- g_strfreev(parts);
-- }
--
-- g_strfreev(lines);
--}
--
--static void
--jabber_google_relay_remove_url_data(JabberStream *js,
-- PurpleUtilFetchUrlData *url_data)
--{
-- GList *iter = js->google_relay_requests;
--
-- while (iter) {
-- if (iter->data == url_data) {
-- js->google_relay_requests =
-- g_list_delete_link(js->google_relay_requests, iter);
-- break;
-- }
-- }
--}
--
--static void
--jabber_google_relay_fetch_cb(PurpleUtilFetchUrlData *url_data,
-- gpointer user_data, const gchar *url_text, gsize len,
-- const gchar *error_message)
--{
-- JabberGoogleRelayCallbackData *data =
-- (JabberGoogleRelayCallbackData *) user_data;
-- GoogleSession *session = data->session;
-- JabberStream *js = session->js;
-- JabberGoogleRelayCallback *cb = data->cb;
-- gchar *relay_ip = NULL;
-- guint relay_udp = 0;
-- guint relay_tcp = 0;
-- guint relay_ssltcp = 0;
-- gchar *relay_username = NULL;
-- gchar *relay_password = NULL;
--
-- g_free(data);
--
-- if (url_data) {
-- jabber_google_relay_remove_url_data(js, url_data);
-- }
--
-- purple_debug_info("jabber", "got response on HTTP request to relay server\n");
--
-- if (url_text && len > 0) {
-- purple_debug_info("jabber", "got Google relay request response:\n%s\n",
-- url_text);
-- jabber_google_relay_parse_response(url_text, &relay_ip, &relay_udp,
-- &relay_tcp, &relay_ssltcp, &relay_username, &relay_password);
-- }
--
-- if (cb)
-- cb(session, relay_ip, relay_udp, relay_tcp, relay_ssltcp,
-- relay_username, relay_password);
--
-- g_free(relay_ip);
-- g_free(relay_username);
-- g_free(relay_password);
--}
--
--void
--jabber_google_do_relay_request(JabberStream *js, GoogleSession *session,
-- JabberGoogleRelayCallback cb)
--{
-- PurpleUtilFetchUrlData *url_data = NULL;
-- gchar *url = g_strdup_printf("http://%s", js->google_relay_host);
-- /* yes, the relay token is included twice as different request headers,
-- this is apparently needed to make Google's relay servers work... */
-- gchar *request =
-- g_strdup_printf("GET /create_session HTTP/1.0\r\n"
-- "Host: %s\r\n"
-- "X-Talk-Google-Relay-Auth: %s\r\n"
-- "X-Google-Relay-Auth: %s\r\n\r\n",
-- js->google_relay_host, js->google_relay_token, js->google_relay_token);
-- JabberGoogleRelayCallbackData *data = g_new0(JabberGoogleRelayCallbackData, 1);
--
-- data->session = session;
-- data->cb = cb;
-- purple_debug_info("jabber",
-- "sending Google relay request %s to %s\n", request, url);
-- url_data =
-- purple_util_fetch_url_request(url, FALSE, NULL, FALSE, request, FALSE,
-- jabber_google_relay_fetch_cb, data);
-- if (url_data) {
-- js->google_relay_requests =
-- g_list_prepend(js->google_relay_requests, url_data);
-- } else {
-- purple_debug_error("jabber", "unable to create Google relay request\n");
-- jabber_google_relay_fetch_cb(NULL, data, NULL, 0, NULL);
-- }
-- g_free(url);
-- g_free(request);
--}
-\ No newline at end of file
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/relay.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/relay.h
---- pidgin-2.10.7/libpurple/protocols/jabber/google/relay.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/relay.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,33 +0,0 @@
--/**
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef JABBER_GOOGLE_RELAY
--#define JABBER_GOOGLE_RELAY
--
--#include "google_session.h"
--
--typedef void (JabberGoogleRelayCallback)(GoogleSession *session, const gchar *ip,
-- guint udp_port, guint tcp_port, guint tls_port,
-- const gchar *username, const gchar *password);
--
--void jabber_google_do_relay_request(JabberStream *js, GoogleSession *session,
-- JabberGoogleRelayCallback cb);
--
--#endif /* JABBER_GOOGLE_RELAY */
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/iq.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/iq.c
---- pidgin-2.10.7/libpurple/protocols/jabber/iq.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/iq.c 2013-08-17 00:19:05.943958296 -0300
-@@ -28,10 +28,6 @@
-
- #include "buddy.h"
- #include "disco.h"
--#include "google/gmail.h"
--#include "google/google.h"
--#include "google/jingleinfo.h"
--#include "google/google_session.h"
- #include "iq.h"
- #include "jingle/jingle.h"
- #include "oob.h"
-@@ -461,13 +457,7 @@
- signal_iq_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-
- jabber_iq_register_handler("jingle", JINGLE, jingle_parse);
-- jabber_iq_register_handler("mailbox", NS_GOOGLE_MAIL_NOTIFY,
-- jabber_gmail_poke);
-- jabber_iq_register_handler("new-mail", NS_GOOGLE_MAIL_NOTIFY,
-- jabber_gmail_poke);
- jabber_iq_register_handler("ping", NS_PING, jabber_ping_parse);
-- jabber_iq_register_handler("query", NS_GOOGLE_JINGLE_INFO,
-- jabber_google_handle_jingle_info);
- jabber_iq_register_handler("query", NS_BYTESTREAMS,
- jabber_bytestreams_parse);
- jabber_iq_register_handler("query", NS_DISCO_INFO, jabber_disco_info_parse);
-@@ -481,8 +471,6 @@
- jabber_iq_register_handler("query", "jabber:iq:version",
- jabber_iq_version_parse);
- #ifdef USE_VV
-- jabber_iq_register_handler("session", NS_GOOGLE_SESSION,
-- jabber_google_session_parse);
- #endif
- jabber_iq_register_handler("block", NS_SIMPLE_BLOCKING, jabber_blocklist_parse_push);
- jabber_iq_register_handler("unblock", NS_SIMPLE_BLOCKING, jabber_blocklist_parse_push);
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/jabber.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/jabber.c
---- pidgin-2.10.7/libpurple/protocols/jabber/jabber.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/jabber.c 2013-08-27 23:23:55.191865468 -0300
-@@ -51,9 +51,6 @@
- #include "chat.h"
- #include "data.h"
- #include "disco.h"
--#include "google/google.h"
--#include "google/google_roster.h"
--#include "google/google_session.h"
- #include "ibb.h"
- #include "iq.h"
- #include "jutil.h"
-@@ -1003,9 +1000,6 @@
- js->stun_ip = NULL;
- js->stun_port = 0;
- js->stun_query = NULL;
-- js->google_relay_token = NULL;
-- js->google_relay_host = NULL;
-- js->google_relay_requests = NULL;
-
- /* if we are idle, set idle-ness on the stream (this could happen if we get
- disconnected and the reconnects while being idle. I don't think it makes
-@@ -1679,8 +1673,6 @@
- }
- g_free(js->server_name);
- g_free(js->certificate_CN);
-- g_free(js->gmail_last_time);
-- g_free(js->gmail_last_tid);
- g_free(js->old_msg);
- g_free(js->old_avatarhash);
- g_free(js->old_artist);
-@@ -1709,21 +1701,6 @@
- js->stun_query = NULL;
- }
-
-- /* remove Google relay-related stuff */
-- g_free(js->google_relay_token);
-- g_free(js->google_relay_host);
-- if (js->google_relay_requests) {
-- while (js->google_relay_requests) {
-- PurpleUtilFetchUrlData *url_data =
-- (PurpleUtilFetchUrlData *) js->google_relay_requests->data;
-- purple_util_fetch_url_cancel(url_data);
-- g_free(url_data);
-- js->google_relay_requests =
-- g_list_delete_link(js->google_relay_requests,
-- js->google_relay_requests);
-- }
-- }
--
- g_free(js);
-
- gc->proto_data = NULL;
-@@ -1916,12 +1893,6 @@
- if (js == NULL)
- return;
-
-- if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER)
-- {
-- jabber_google_roster_add_deny(js, who);
-- return;
-- }
--
- if (!(js->server_caps & JABBER_CAP_BLOCKING))
- {
- purple_notify_error(NULL, _("Server doesn't support blocking"),
-@@ -1952,12 +1923,6 @@
- if (js == NULL)
- return;
-
-- if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER)
-- {
-- jabber_google_roster_rem_deny(js, who);
-- return;
-- }
--
- if (!(js->server_caps & JABBER_CAP_BLOCKING))
- return;
-
-@@ -3310,13 +3275,7 @@
- jbr = jabber_buddy_find_resource(jb, resource);
- g_free(resource);
-
-- if (type & PURPLE_MEDIA_AUDIO &&
-- !jabber_resource_has_capability(jbr,
-- JINGLE_APP_RTP_SUPPORT_AUDIO) &&
-- jabber_resource_has_capability(jbr, NS_GOOGLE_VOICE))
-- return jabber_google_session_initiate(js, who, type);
-- else
-- return jingle_rtp_initiate_media(js, who, type);
-+ return jingle_rtp_initiate_media(js, who, type);
- }
-
- jb = jabber_buddy_find(js, who, FALSE);
-@@ -3500,11 +3459,6 @@
- caps |= PURPLE_MEDIA_CAPS_MODIFY_SESSION |
- PURPLE_MEDIA_CAPS_CHANGE_DIRECTION;
- }
-- if (jabber_resource_has_capability(jbr, NS_GOOGLE_VOICE)) {
-- caps |= PURPLE_MEDIA_CAPS_AUDIO;
-- if (jabber_resource_has_capability(jbr, NS_GOOGLE_VIDEO))
-- caps |= PURPLE_MEDIA_CAPS_AUDIO_VIDEO;
-- }
-
- total |= caps;
- }
-@@ -3869,10 +3823,6 @@
- jabber_add_feature(JINGLE, 0);
-
- #ifdef USE_VV
-- jabber_add_feature(NS_GOOGLE_PROTOCOL_SESSION, jabber_audio_enabled);
-- jabber_add_feature(NS_GOOGLE_VOICE, jabber_audio_enabled);
-- jabber_add_feature(NS_GOOGLE_VIDEO, jabber_video_enabled);
-- jabber_add_feature(NS_GOOGLE_CAMERA, jabber_video_enabled);
- jabber_add_feature(JINGLE_APP_RTP, 0);
- jabber_add_feature(JINGLE_APP_RTP_SUPPORT_AUDIO, jabber_audio_enabled);
- jabber_add_feature(JINGLE_APP_RTP_SUPPORT_VIDEO, jabber_video_enabled);
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/jabber.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/jabber.h
---- pidgin-2.10.7/libpurple/protocols/jabber/jabber.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/jabber.h 2013-08-17 00:10:38.778345348 -0300
-@@ -36,12 +36,6 @@
- JABBER_CAP_IQ_SEARCH = 1 << 7,
- JABBER_CAP_IQ_REGISTER = 1 << 8,
-
-- /* Google Talk extensions:
-- * http://code.google.com/apis/talk/jep_extensions/extensions.html
-- */
-- JABBER_CAP_GMAIL_NOTIFY = 1 << 9,
-- JABBER_CAP_GOOGLE_ROSTER = 1 << 10,
--
- JABBER_CAP_PING = 1 << 11,
- JABBER_CAP_ADHOC = 1 << 12,
- JABBER_CAP_BLOCKING = 1 << 13,
-@@ -195,12 +189,8 @@
- gboolean reinit;
-
- JabberCapabilities server_caps;
-- gboolean googletalk;
- char *server_name;
-
-- char *gmail_last_time;
-- char *gmail_last_tid;
--
- char *serverFQDN;
-
- #ifdef HAVE_CYRUS_SASL
-@@ -276,12 +266,6 @@
- gchar *stun_ip;
- int stun_port;
- PurpleDnsQueryData *stun_query;
--
-- /* stuff for Google's relay handling */
-- gchar *google_relay_token;
-- gchar *google_relay_host;
-- GList *google_relay_requests; /* the HTTP requests to get */
-- /* relay info */
- };
-
- typedef gboolean (JabberFeatureEnabled)(JabberStream *js, const gchar *namespace);
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/jingle/jingle.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/jingle/jingle.c
---- pidgin-2.10.7/libpurple/protocols/jabber/jingle/jingle.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/jingle/jingle.c 2013-08-17 00:17:51.991679891 -0300
-@@ -486,13 +486,11 @@
-
- if (has_account_stun) {
- purple_debug_info("jabber",
-- "setting param stun-ip for stream using Google auto-config: %s\n",
- js->stun_ip);
- params[next_index].name = "stun-ip";
- g_value_init(&params[next_index].value, G_TYPE_STRING);
- g_value_set_string(&params[next_index].value, js->stun_ip);
- purple_debug_info("jabber",
-- "setting param stun-port for stream using Google auto-config: %d\n",
- js->stun_port);
- next_index++;
- params[next_index].name = "stun-port";
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/jingle/jingle.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/jingle/jingle.h
---- pidgin-2.10.7/libpurple/protocols/jabber/jingle/jingle.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/jingle/jingle.h 2013-08-27 23:02:43.456476444 -0300
-@@ -79,8 +79,7 @@
- void jingle_terminate_sessions(JabberStream *js);
-
- #ifdef USE_VV
--/* create a GParam array given autoconfigured STUN (and later perhaps TURN).
-- if google_talk is TRUE, set compatability mode to GOOGLE_TALK */
-+/* create a GParam array given autoconfigured STUN (and later perhaps TURN).*/
- GParameter *jingle_get_params(JabberStream *js, const gchar *relay_ip,
- guint relay_udp, guint relay_tcp, guint relay_ssltcp,
- const gchar *relay_username, const gchar *relay_password, guint *num_params);
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/libxmpp.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/libxmpp.c
---- pidgin-2.10.7/libpurple/protocols/jabber/libxmpp.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/libxmpp.c 2013-08-17 00:13:06.222881329 -0300
-@@ -41,7 +41,6 @@
- #include "si.h"
- #include "message.h"
- #include "presence.h"
--#include "google/google.h"
- #include "pep.h"
- #include "usermood.h"
- #include "usertune.h"
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/jabber/Makefile.am
---- pidgin-2.10.7/libpurple/protocols/jabber/Makefile.am 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/Makefile.am 2013-08-17 00:18:17.592468560 -0300
-@@ -27,20 +27,6 @@
- data.h \
- disco.c \
- disco.h \
-- google/gmail.c \
-- google/gmail.h \
-- google/google.c \
-- google/google.h \
-- google/google_presence.c \
-- google/google_presence.h \
-- google/google_roster.c \
-- google/google_roster.h \
-- google/google_session.c \
-- google/google_session.h \
-- google/jingleinfo.c \
-- google/jingleinfo.h \
-- google/relay.c \
-- google/relay.h \
- ibb.c \
- ibb.h \
- iq.c \
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/jabber/Makefile.in
---- pidgin-2.10.7/libpurple/protocols/jabber/Makefile.in 2013-02-11 07:17:20.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/Makefile.in 2013-08-17 00:12:44.605549467 -0300
-@@ -104,12 +104,7 @@
- auth.h auth_digest_md5.c auth_digest_md5.h auth_plain.c \
- auth_scram.c auth_scram.h buddy.c buddy.h bosh.c bosh.h caps.c \
- caps.h chat.c chat.h data.c data.h disco.c disco.h \
-- google/gmail.c google/gmail.h google/google.c google/google.h \
-- google/google_presence.c google/google_presence.h \
-- google/google_roster.c google/google_roster.h \
-- google/google_session.c google/google_session.h \
-- google/jingleinfo.c google/jingleinfo.h google/relay.c \
-- google/relay.h ibb.c ibb.h iq.c iq.h jabber.c jabber.h \
-+ ibb.c ibb.h iq.c iq.h jabber.c jabber.h \
- jingle/jingle.c jingle/jingle.h jingle/content.c \
- jingle/content.h jingle/iceudp.c jingle/iceudp.h \
- jingle/rawudp.c jingle/rawudp.h jingle/rtp.c jingle/rtp.h \
-@@ -126,9 +121,7 @@
- libjabber_la-auth_scram.lo libjabber_la-buddy.lo \
- libjabber_la-bosh.lo libjabber_la-caps.lo libjabber_la-chat.lo \
- libjabber_la-data.lo libjabber_la-disco.lo \
-- libjabber_la-gmail.lo libjabber_la-google.lo \
-- libjabber_la-google_presence.lo libjabber_la-google_roster.lo \
-- libjabber_la-google_session.lo libjabber_la-jingleinfo.lo \
-+ libjabber_la-jingleinfo.lo \
- libjabber_la-relay.lo libjabber_la-ibb.lo libjabber_la-iq.lo \
- libjabber_la-jabber.lo libjabber_la-jingle.lo \
- libjabber_la-content.lo libjabber_la-iceudp.lo \
-@@ -244,8 +237,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -307,8 +298,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-@@ -457,13 +446,8 @@
- JABBERSOURCES = adhoccommands.c adhoccommands.h auth.c auth.h \
- auth_digest_md5.c auth_digest_md5.h auth_plain.c auth_scram.c \
- auth_scram.h buddy.c buddy.h bosh.c bosh.h caps.c caps.h \
-- chat.c chat.h data.c data.h disco.c disco.h google/gmail.c \
-- google/gmail.h google/google.c google/google.h \
-- google/google_presence.c google/google_presence.h \
-- google/google_roster.c google/google_roster.h \
-- google/google_session.c google/google_session.h \
-- google/jingleinfo.c google/jingleinfo.h google/relay.c \
-- google/relay.h ibb.c ibb.h iq.c iq.h jabber.c jabber.h \
-+ chat.c chat.h data.c data.h disco.c disco.h \
-+ ibb.c ibb.h iq.c iq.h jabber.c jabber.h \
- jingle/jingle.c jingle/jingle.h jingle/content.c \
- jingle/content.h jingle/iceudp.c jingle/iceudp.h \
- jingle/rawudp.c jingle/rawudp.h jingle/rtp.c jingle/rtp.h \
-@@ -600,11 +584,6 @@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-content.Plo@am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-data.Plo@am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-disco.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-gmail.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-google.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-google_presence.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-google_roster.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-google_session.Plo@am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-ibb.Plo@am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-iceudp.Plo@am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-iq.Plo@am__quote@
-@@ -731,55 +710,6 @@
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -c -o libjabber_la-disco.lo `test -f 'disco.c' || echo '$(srcdir)/'`disco.c
-
--libjabber_la-gmail.lo: google/gmail.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -MT libjabber_la-gmail.lo -MD -MP -MF $(DEPDIR)/libjabber_la-gmail.Tpo -c -o libjabber_la-gmail.lo `test -f 'google/gmail.c' || echo '$(srcdir)/'`google/gmail.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libjabber_la-gmail.Tpo $(DEPDIR)/libjabber_la-gmail.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='google/gmail.c' object='libjabber_la-gmail.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -c -o libjabber_la-gmail.lo `test -f 'google/gmail.c' || echo '$(srcdir)/'`google/gmail.c
--
--libjabber_la-google.lo: google/google.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -MT libjabber_la-google.lo -MD -MP -MF $(DEPDIR)/libjabber_la-google.Tpo -c -o libjabber_la-google.lo `test -f 'google/google.c' || echo '$(srcdir)/'`google/google.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libjabber_la-google.Tpo $(DEPDIR)/libjabber_la-google.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='google/google.c' object='libjabber_la-google.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -c -o libjabber_la-google.lo `test -f 'google/google.c' || echo '$(srcdir)/'`google/google.c
--
--libjabber_la-google_presence.lo: google/google_presence.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -MT libjabber_la-google_presence.lo -MD -MP -MF $(DEPDIR)/libjabber_la-google_presence.Tpo -c -o libjabber_la-google_presence.lo `test -f 'google/google_presence.c' || echo '$(srcdir)/'`google/google_presence.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libjabber_la-google_presence.Tpo $(DEPDIR)/libjabber_la-google_presence.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='google/google_presence.c' object='libjabber_la-google_presence.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -c -o libjabber_la-google_presence.lo `test -f 'google/google_presence.c' || echo '$(srcdir)/'`google/google_presence.c
--
--libjabber_la-google_roster.lo: google/google_roster.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -MT libjabber_la-google_roster.lo -MD -MP -MF $(DEPDIR)/libjabber_la-google_roster.Tpo -c -o libjabber_la-google_roster.lo `test -f 'google/google_roster.c' || echo '$(srcdir)/'`google/google_roster.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libjabber_la-google_roster.Tpo $(DEPDIR)/libjabber_la-google_roster.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='google/google_roster.c' object='libjabber_la-google_roster.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -c -o libjabber_la-google_roster.lo `test -f 'google/google_roster.c' || echo '$(srcdir)/'`google/google_roster.c
--
--libjabber_la-google_session.lo: google/google_session.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -MT libjabber_la-google_session.lo -MD -MP -MF $(DEPDIR)/libjabber_la-google_session.Tpo -c -o libjabber_la-google_session.lo `test -f 'google/google_session.c' || echo '$(srcdir)/'`google/google_session.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libjabber_la-google_session.Tpo $(DEPDIR)/libjabber_la-google_session.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='google/google_session.c' object='libjabber_la-google_session.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -c -o libjabber_la-google_session.lo `test -f 'google/google_session.c' || echo '$(srcdir)/'`google/google_session.c
--
--libjabber_la-jingleinfo.lo: google/jingleinfo.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -MT libjabber_la-jingleinfo.lo -MD -MP -MF $(DEPDIR)/libjabber_la-jingleinfo.Tpo -c -o libjabber_la-jingleinfo.lo `test -f 'google/jingleinfo.c' || echo '$(srcdir)/'`google/jingleinfo.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libjabber_la-jingleinfo.Tpo $(DEPDIR)/libjabber_la-jingleinfo.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='google/jingleinfo.c' object='libjabber_la-jingleinfo.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -c -o libjabber_la-jingleinfo.lo `test -f 'google/jingleinfo.c' || echo '$(srcdir)/'`google/jingleinfo.c
--
--libjabber_la-relay.lo: google/relay.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -MT libjabber_la-relay.lo -MD -MP -MF $(DEPDIR)/libjabber_la-relay.Tpo -c -o libjabber_la-relay.lo `test -f 'google/relay.c' || echo '$(srcdir)/'`google/relay.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libjabber_la-relay.Tpo $(DEPDIR)/libjabber_la-relay.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='google/relay.c' object='libjabber_la-relay.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -c -o libjabber_la-relay.lo `test -f 'google/relay.c' || echo '$(srcdir)/'`google/relay.c
--
- libjabber_la-ibb.lo: ibb.c
- @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -MT libjabber_la-ibb.lo -MD -MP -MF $(DEPDIR)/libjabber_la-ibb.Tpo -c -o libjabber_la-ibb.lo `test -f 'ibb.c' || echo '$(srcdir)/'`ibb.c
- @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libjabber_la-ibb.Tpo $(DEPDIR)/libjabber_la-ibb.Plo
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/jabber/Makefile.mingw
---- pidgin-2.10.7/libpurple/protocols/jabber/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,141 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of libjabber
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = libjabber
--XMPP_TARGET = libxmpp
--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./win32 \
-- -I$(GTK_TOP)/include \
-- -I$(GTK_TOP)/include/glib-2.0 \
-- -I$(GTK_TOP)/lib/glib-2.0/include \
-- -I$(LIBXML2_TOP)/include/libxml2 \
-- -I$(PURPLE_TOP) \
-- -I$(PURPLE_TOP)/win32 \
-- -I$(PIDGIN_TREE_TOP)
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(LIBXML2_TOP)/lib \
-- -L$(PURPLE_TOP) \
-- -L.
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = \
-- adhoccommands.c \
-- auth.c \
-- auth_cyrus.c \
-- auth_digest_md5.c \
-- auth_plain.c \
-- auth_scram.c \
-- buddy.c \
-- bosh.c \
-- caps.c \
-- chat.c \
-- data.c \
-- disco.c \
-- google/gmail.c \
-- google/google.c \
-- google/google_presence.c \
-- google/google_roster.c \
-- google/google_session.c \
-- google/jingleinfo.c \
-- google/relay.c \
-- ibb.c \
-- iq.c \
-- jabber.c \
-- jingle/jingle.c \
-- jingle/content.c \
-- jingle/iceudp.c \
-- jingle/rawudp.c \
-- jingle/rtp.c \
-- jingle/session.c \
-- jingle/transport.c \
-- jutil.c \
-- message.c \
-- oob.c \
-- parser.c \
-- pep.c \
-- ping.c \
-- presence.c \
-- roster.c \
-- si.c \
-- useravatar.c \
-- usermood.c \
-- usernick.c \
-- usertune.c \
-- xdata.c \
-- win32/posix.uname.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--XMPP_C_SRC = libxmpp.c
--XMPP_OBJECTS = $(XMPP_C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lgobject-2.0 \
-- -lxml2 \
-- -lws2_32 \
-- -lintl \
-- -lpurple
--
--ifeq ($(CYRUS_SASL), 1)
--INCLUDE_PATHS += -I$(CYRUS_SASL_TOP)/include
--LIB_PATHS += -L$(CYRUS_SASL_TOP)/bin
--LIBS += -llibsasl
--endif
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll $(XMPP_TARGET).dll
--
--install: all $(DLL_INSTALL_DIR)
-- cp $(XMPP_TARGET).dll $(DLL_INSTALL_DIR)
-- cp $(TARGET).dll $(PURPLE_INSTALL_DIR)
--
--$(OBJECTS): $(PURPLE_CONFIG_H)
--
--$(TARGET).dll $(TARGET).dll.a: $(PURPLE_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--out-implib,$(TARGET).dll.a -o $(TARGET).dll
--
--$(XMPP_TARGET).dll: $(TARGET).dll.a $(XMPP_OBJECTS)
-- $(CC) -shared $(XMPP_OBJECTS) $(LIB_PATHS) $(LIBS) -ljabber $(DLL_LD_FLAGS) -o $(XMPP_TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -f $(OBJECTS) $(TARGET).dll $(TARGET).dll.a
-- rm -f $(XMPP_OBJECTS) $(XMPP_TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/message.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/message.c
---- pidgin-2.10.7/libpurple/protocols/jabber/message.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/message.c 2013-08-17 00:20:08.115874207 -0300
-@@ -30,7 +30,6 @@
- #include "buddy.h"
- #include "chat.h"
- #include "data.h"
--#include "google/google.h"
- #include "message.h"
- #include "xmlnode.h"
- #include "pep.h"
-@@ -151,11 +150,6 @@
- jbr->thread_id = g_strdup(jbr->thread_id);
- }
-
-- if (jm->js->googletalk && jm->xhtml == NULL) {
-- char *tmp = jm->body;
-- jm->body = jabber_google_format_to_html(jm->body);
-- g_free(tmp);
-- }
- serv_got_im(gc, jm->from, jm->xhtml ? jm->xhtml : jm->body, 0, jm->sent);
- }
-
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/namespaces.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/namespaces.h
---- pidgin-2.10.7/libpurple/protocols/jabber/namespaces.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/namespaces.h 2013-08-17 00:11:17.449534779 -0300
-@@ -95,18 +95,4 @@
- /* XEP-0264 File Transfer Thumbnails (Thumbs) */
- #define NS_THUMBS "urn:xmpp:thumbs:0"
-
--/* Google extensions */
--#define NS_GOOGLE_CAMERA "http://www.google.com/xmpp/protocol/camera/v1"
--#define NS_GOOGLE_VIDEO "http://www.google.com/xmpp/protocol/video/v1"
--#define NS_GOOGLE_VOICE "http://www.google.com/xmpp/protocol/voice/v1"
--#define NS_GOOGLE_JINGLE_INFO "google:jingleinfo"
--
--#define NS_GOOGLE_MAIL_NOTIFY "google:mail:notify"
--#define NS_GOOGLE_ROSTER "google:roster"
--
--#define NS_GOOGLE_PROTOCOL_SESSION "http://www.google.com/xmpp/protocol/session"
--#define NS_GOOGLE_SESSION "http://www.google.com/session"
--#define NS_GOOGLE_SESSION_PHONE "http://www.google.com/session/phone"
--#define NS_GOOGLE_SESSION_VIDEO "http://www.google.com/session/video"
--
- #endif /* PURPLE_JABBER_NAMESPACES_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/presence.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/presence.c
---- pidgin-2.10.7/libpurple/protocols/jabber/presence.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/presence.c 2013-08-17 00:16:58.436696950 -0300
-@@ -34,8 +34,6 @@
-
- #include "buddy.h"
- #include "chat.h"
--#include "google/google.h"
--#include "google/google_presence.h"
- #include "presence.h"
- #include "iq.h"
- #include "jutil.h"
-@@ -208,9 +206,6 @@
- /* changing the buzz state has to trigger a re-broadcasting of the presence for caps */
-
- tune = purple_presence_get_status(p, "tune");
-- if (js->googletalk && !stripped && purple_status_is_active(tune)) {
-- stripped = jabber_google_presence_outgoing(tune);
-- }
-
- #define CHANGED(a,b) ((!a && b) || (a && a[0] == '\0' && b && b[0] != '\0') || \
- (a && !b) || (a && a[0] != '\0' && b && b[0] == '\0') || (a && b && strcmp(a,b)))
-@@ -361,11 +356,6 @@
- #ifdef USE_VV
- /*
- * MASSIVE HUGE DISGUSTING HACK
-- * This is a huge hack. As far as I can tell, Google Talk's gmail client
-- * doesn't bother to check the actual features we advertise; they
-- * just assume that if we specify a 'voice-v1' ext (ignoring that
-- * these are to be assigned no semantic value), we support receiving voice
-- * calls.
- *
- * Ditto for 'video-v1'.
- */
-@@ -883,7 +873,6 @@
-
- jbr = jabber_buddy_find_resource(presence->jb, NULL);
- if (jbr) {
-- jabber_google_presence_incoming(js, buddy_name, jbr);
- purple_prpl_got_user_status(account, buddy_name,
- jabber_buddy_state_get_status_id(jbr->state),
- "priority", jbr->priority,
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/roster.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/roster.c
---- pidgin-2.10.7/libpurple/protocols/jabber/roster.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/roster.c 2013-08-17 00:09:16.245807467 -0300
-@@ -27,8 +27,6 @@
-
- #include "buddy.h"
- #include "chat.h"
--#include "google/google.h"
--#include "google/google_roster.h"
- #include "presence.h"
- #include "roster.h"
- #include "iq.h"
-@@ -83,11 +81,6 @@
- iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:roster");
- query = xmlnode_get_child(iq->node, "query");
-
-- if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) {
-- xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER);
-- xmlnode_set_attrib(query, "gr:ext", "2");
-- }
--
- jabber_iq_set_callback(iq, roster_request_cb, NULL);
- jabber_iq_send(iq);
- }
-@@ -244,10 +237,6 @@
- } else {
- GSList *groups = NULL;
-
-- if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER)
-- if (!jabber_google_roster_incoming(js, item))
-- continue;
--
- for(group = xmlnode_get_child(item, "group"); group; group = xmlnode_get_next_twin(group)) {
- char *group_name = xmlnode_get_data(group);
-
-@@ -349,11 +338,6 @@
-
- g_slist_free(groups);
-
-- if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) {
-- jabber_google_roster_outgoing(js, query, item);
-- xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER);
-- xmlnode_set_attrib(query, "gr:ext", "2");
-- }
- jabber_iq_send(iq);
- }
-
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/win32/posix.uname.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/win32/posix.uname.c
---- pidgin-2.10.7/libpurple/protocols/jabber/win32/posix.uname.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/win32/posix.uname.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,141 +0,0 @@
--/*
-- posix.uname.c - version 1.1
-- Copyright (C) 1999, 2000
-- Earnie Boyd and assigns
--
-- Fills the utsname structure with the appropriate values.
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU Lesser General Public License as published
-- by the Free Software Foundation; either version 2.1, or (at your option)
-- any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICUALR PURPOSE. See the
-- GNU Lesser General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software Foundation,
-- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
-- */
--
--/*
-- Send bug reports to Earnie Boyd <earnie_boyd@yahoo.com>
-- */
--
--#include "utsname.h"
--#include <string.h>
--#include <stdio.h>
--
--#include <glib.h>
--
--/* ANONYMOUS unions and structs are used from the windows header definitions.
-- These need to be defined for them to work correctly with gcc2.95.2-mingw. */
--/*#define _ANONYMOUS_STRUCT*/
--/*#define _ANONYMOUS_UNION*/
--#include <windows.h>
--#ifdef __MINGW32__
--#include <_mingw.h>
--#endif
--
--int
--jabber_win32_uname( struct utsname *uts )
--{
-- DWORD sLength;
-- OSVERSIONINFO OS_version;
-- SYSTEM_INFO System_Info;
--
--/* XXX Should these be in the global runtime */
-- enum WinOS {Win95, Win98, WinNT, unknown};
-- int MingwOS;
--
-- memset( uts, 0, sizeof ( *uts ) );
-- OS_version.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
--
-- GetVersionEx ( &OS_version );
-- GetSystemInfo ( &System_Info );
--
-- g_strlcpy( uts->sysname, "WIN32_" , sizeof(uts->sysname));
-- switch( OS_version.dwPlatformId )
-- {
-- case VER_PLATFORM_WIN32_NT:
-- g_strlcat( uts->sysname, "WinNT", sizeof(uts->sysname) );
-- MingwOS = WinNT;
-- break;
-- case VER_PLATFORM_WIN32_WINDOWS:
-- switch ( OS_version.dwMinorVersion )
-- {
-- case 0:
-- g_strlcat( uts->sysname, "Win95", sizeof(uts->sysname) );
-- MingwOS = Win95;
-- break;
-- case 10:
-- g_strlcat( uts->sysname, "Win98", sizeof(uts->sysname) );
-- MingwOS = Win98;
-- break;
-- default:
-- g_strlcat( uts->sysname, "Win??", sizeof(uts->sysname) );
-- MingwOS = unknown;
-- break;
-- }
-- break;
-- default:
-- g_strlcat( uts->sysname, "Win??", sizeof(uts->sysname) );
-- MingwOS = unknown;
-- break;
-- }
--
--#ifdef __MINGW32__
-- sprintf( uts->version, "%i", __MINGW32_MAJOR_VERSION );
-- sprintf( uts->release, "%i", __MINGW32_MINOR_VERSION );
--#endif
--
-- switch( System_Info.wProcessorArchitecture )
-- {
-- case PROCESSOR_ARCHITECTURE_PPC:
-- g_strlcpy( uts->machine, "ppc" , sizeof( uts->machine ) );
-- break;
-- case PROCESSOR_ARCHITECTURE_ALPHA:
-- g_strlcpy( uts->machine, "alpha" , sizeof( uts->machine ) );
-- break;
-- case PROCESSOR_ARCHITECTURE_MIPS:
-- g_strlcpy( uts->machine, "mips" , sizeof( uts->machine ) );
-- break;
-- case PROCESSOR_ARCHITECTURE_INTEL:
-- /* dwProcessorType is only valid in Win95 and Win98
-- wProcessorLevel is only valid in WinNT */
-- switch( MingwOS )
-- {
-- case Win95:
-- case Win98:
-- switch( System_Info.dwProcessorType )
-- {
-- case PROCESSOR_INTEL_386:
-- case PROCESSOR_INTEL_486:
-- case PROCESSOR_INTEL_PENTIUM:
-- sprintf( uts->machine, "i%ld", System_Info.dwProcessorType );
-- break;
-- default:
-- g_strlcpy( uts->machine, "i386" , sizeof( uts->machine ) );
-- break;
-- }
-- break;
-- case WinNT:
-- sprintf( uts->machine, "i%d86", System_Info.wProcessorLevel );
-- break;
-- default:
-- g_strlcpy( uts->machine, "unknown" , sizeof( uts->machine ) );
-- break;
-- }
-- break;
-- default:
-- g_strlcpy( uts->machine, "unknown" , sizeof( uts->machine ) );
-- break;
-- }
--
-- sLength = sizeof ( uts->nodename ) - 1;
-- GetComputerNameA( uts->nodename, &sLength );
-- return 1;
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/win32/utsname.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/win32/utsname.h
---- pidgin-2.10.7/libpurple/protocols/jabber/win32/utsname.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/win32/utsname.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,24 +0,0 @@
--#ifndef _SYS_UTSNAME_H
--#define _SYS_UTSNAME_H
--
--#ifdef __cplusplus
--extern "C" {
--#endif
--
--struct utsname
--{
-- char sysname[20];
-- char nodename[20];
-- char release[20];
-- char version[20];
-- char machine[20];
--};
--
--int jabber_win32_uname (struct utsname *);
--#define uname(utsname) jabber_win32_uname(utsname)
--
--#ifdef __cplusplus
--}
--#endif
--
--#endif
diff -Nur pidgin-2.10.7/libpurple/protocols/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/Makefile.am
--- pidgin-2.10.7/libpurple/protocols/Makefile.am 2013-02-11 07:16:51.000000000 -0200
+++ pidgin-2.10.7-nonprism/libpurple/protocols/Makefile.am 2013-08-16 22:37:55.011207011 -0300
@@ -28713,121448 +1418,6 @@ diff -Nur pidgin-2.10.7/libpurple/protocols/Makefile.in pidgin-2.10.7-nonprism/l
SUBDIRS = $(DYNAMIC_PRPLS) $(STATIC_PRPLS)
all: all-recursive
-diff -Nur pidgin-2.10.7/libpurple/protocols/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/Makefile.mingw
---- pidgin-2.10.7/libpurple/protocols/Makefile.mingw 2013-02-11 07:16:51.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,29 +0,0 @@
--# Makefile.mingw
--#
--# Author: hermanator12002@yahoo.com
--# Date 9/11/02
--# Description: Protocols Makefile for win32 (mingw) port of libpurple
--#
--
--PIDGIN_TREE_TOP := ../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--SUBDIRS = gg irc jabber msn mxit novell null oscar sametime silc simple yahoo bonjour myspace
--
--.PHONY: all install clean
--
--all:
-- for subdir in $(SUBDIRS); do \
-- $(MAKE) -C $$subdir -f $(MINGW_MAKEFILE) || exit 1; \
-- done;
--
--install: all
-- for subdir in $(SUBDIRS); do \
-- $(MAKE) -C $$subdir -f $(MINGW_MAKEFILE) install || exit 1; \
-- done;
--
--clean:
-- for subdir in $(SUBDIRS); do \
-- $(MAKE) -C $$subdir -f $(MINGW_MAKEFILE) clean || exit 1; \
-- done;
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/cmdproc.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/cmdproc.c
---- pidgin-2.10.7/libpurple/protocols/msn/cmdproc.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/cmdproc.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,339 +0,0 @@
--/**
-- * @file cmdproc.c MSN command processor functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "cmdproc.h"
--#include "error.h"
--
--MsnCmdProc *
--msn_cmdproc_new(MsnSession *session)
--{
-- MsnCmdProc *cmdproc;
--
-- cmdproc = g_new0(MsnCmdProc, 1);
--
-- cmdproc->session = session;
-- cmdproc->txqueue = g_queue_new();
-- cmdproc->history = msn_history_new();
--
-- cmdproc->multiparts = g_hash_table_new_full(g_str_hash, g_str_equal,
-- NULL, (GDestroyNotify)msn_message_unref);
--
-- return cmdproc;
--}
--
--void
--msn_cmdproc_destroy(MsnCmdProc *cmdproc)
--{
-- MsnTransaction *trans;
--
-- while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL)
-- msn_transaction_destroy(trans);
--
-- g_queue_free(cmdproc->txqueue);
--
-- msn_history_destroy(cmdproc->history);
--
-- if (cmdproc->last_cmd != NULL)
-- msn_command_unref(cmdproc->last_cmd);
--
-- g_hash_table_destroy(cmdproc->multiparts);
--
-- g_free(cmdproc);
--}
--
--void
--msn_cmdproc_process_queue(MsnCmdProc *cmdproc)
--{
-- MsnTransaction *trans;
--
-- while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL)
-- msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--void
--msn_cmdproc_queue_trans(MsnCmdProc *cmdproc, MsnTransaction *trans)
--{
-- g_return_if_fail(cmdproc != NULL);
-- g_return_if_fail(trans != NULL);
--
-- g_queue_push_tail(cmdproc->txqueue, trans);
--}
--
--static void
--show_debug_cmd(MsnCmdProc *cmdproc, gboolean incoming, const char *command)
--{
-- MsnServConn *servconn;
-- const char *names[] = { "NS", "SB" };
-- char *show;
-- char tmp;
-- size_t len;
--
-- servconn = cmdproc->servconn;
-- len = strlen(command);
-- show = g_strdup(command);
--
-- tmp = (incoming) ? 'S' : 'C';
--
-- if ((show[len - 1] == '\n') && (show[len - 2] == '\r'))
-- {
-- show[len - 2] = '\0';
-- }
--
-- purple_debug_misc("msn", "%c: %s %03d: %s\n", tmp,
-- names[servconn->type], servconn->num, show);
--
-- g_free(show);
--}
--
--gboolean
--msn_cmdproc_send_trans(MsnCmdProc *cmdproc, MsnTransaction *trans)
--{
-- MsnServConn *servconn;
-- char *data;
-- size_t len;
-- gboolean ret;
--
-- g_return_val_if_fail(cmdproc != NULL, TRUE);
-- g_return_val_if_fail(trans != NULL, TRUE);
--
-- servconn = cmdproc->servconn;
--
-- if (!servconn->connected) {
-- msn_transaction_destroy(trans);
-- return FALSE;
-- }
--
-- if (trans->saveable)
-- msn_history_add(cmdproc->history, trans);
--
-- data = msn_transaction_to_string(trans);
--
-- len = strlen(data);
--
-- show_debug_cmd(cmdproc, FALSE, data);
--
-- if (trans->callbacks == NULL)
-- trans->callbacks = g_hash_table_lookup(cmdproc->cbs_table->cmds,
-- trans->command);
--
-- if (trans->payload != NULL)
-- {
-- data = g_realloc(data, len + trans->payload_len);
-- memcpy(data + len, trans->payload, trans->payload_len);
-- len += trans->payload_len;
--
-- /*
-- * We're done with trans->payload. Free it so that the memory
-- * doesn't sit around in cmdproc->history.
-- */
-- g_free(trans->payload);
-- trans->payload = NULL;
-- trans->payload_len = 0;
-- }
--
-- ret = msn_servconn_write(servconn, data, len) != -1;
--
-- if (!trans->saveable)
-- msn_transaction_destroy(trans);
-- g_free(data);
-- return ret;
--}
--
--void
--msn_cmdproc_process_payload(MsnCmdProc *cmdproc, char *payload,
-- int payload_len)
--{
-- MsnCommand *last;
--
-- g_return_if_fail(cmdproc != NULL);
--
-- last = cmdproc->last_cmd;
-- last->payload = g_memdup(payload, payload_len);
-- last->payload_len = payload_len;
--
-- if (last->payload_cb != NULL)
-- last->payload_cb(cmdproc, last, payload, payload_len);
--}
--
--void
--msn_cmdproc_process_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
--{
-- MsnMsgTypeCb cb;
-- const char *message_id = NULL;
--
-- /* Multi-part messages */
-- message_id = msn_message_get_header_value(msg, "Message-ID");
-- if (message_id != NULL) {
-- /* This is the first in a series of chunks */
--
-- const char *chunk_text = msn_message_get_header_value(msg, "Chunks");
-- guint chunk;
-- if (chunk_text != NULL) {
-- chunk = strtol(chunk_text, NULL, 10);
-- /* 1024 chunks of ~1300 bytes is ~1MB, which seems OK to prevent
-- some random client causing pidgin to hog a ton of memory.
-- Probably should figure out the maximum that the official client
-- actually supports, though. */
-- if (chunk > 0 && chunk < 1024) {
-- msg->total_chunks = chunk;
-- msg->received_chunks = 1;
-- g_hash_table_insert(cmdproc->multiparts, (gpointer)message_id, msn_message_ref(msg));
-- purple_debug_info("msn", "Received chunked message, message_id: '%s', total chunks: %d\n",
-- message_id, chunk);
-- } else {
-- purple_debug_error("msn", "MessageId '%s' has too many chunks: %d\n", message_id, chunk);
-- }
-- return;
-- } else {
-- chunk_text = msn_message_get_header_value(msg, "Chunk");
-- if (chunk_text != NULL) {
-- /* This is one chunk in a series of chunks */
--
-- MsnMessage *first = g_hash_table_lookup(cmdproc->multiparts, message_id);
-- chunk = strtol(chunk_text, NULL, 10);
-- if (first != NULL) {
-- if (first->received_chunks != chunk) {
-- /*
-- * We received an out of order chunk number (i.e. not the
-- * next one in the sequence). Not sure if this can happen
-- * legitimately, but we definitely don't handle it right
-- * now.
-- */
-- g_hash_table_remove(cmdproc->multiparts, message_id);
-- return;
-- }
--
-- /* Chunk is from 1 to total-1 (doesn't count first one) */
-- purple_debug_info("msn", "Received chunk %d of %d, message_id: '%s'\n",
-- chunk + 1, first->total_chunks, message_id);
-- first->body = g_realloc(first->body, first->body_len + msg->body_len);
-- memcpy(first->body + first->body_len, msg->body, msg->body_len);
-- first->body_len += msg->body_len;
-- first->received_chunks++;
-- if (first->received_chunks != first->total_chunks)
-- /* We're waiting for more chunks */
-- return;
--
-- /*
-- * We have all the chunks for this message, great! Send
-- * it along... The caller takes care of freeing the old one.
-- */
-- msg = first;
-- } else {
-- purple_debug_error("msn",
-- "Unable to find first chunk of message_id '%s' to correspond with chunk %d.\n",
-- message_id, chunk + 1);
-- }
-- } else {
-- purple_debug_error("msn", "Received MessageId '%s' with no chunk number!\n", message_id);
-- }
-- }
-- }
--
-- if (msn_message_get_content_type(msg) == NULL)
-- {
-- purple_debug_misc("msn", "failed to find message content\n");
-- return;
-- }
--
-- cb = g_hash_table_lookup(cmdproc->cbs_table->msgs,
-- msn_message_get_content_type(msg));
--
-- if (cb != NULL)
-- cb(cmdproc, msg);
-- else
-- purple_debug_warning("msn", "Unhandled content-type '%s'\n",
-- msn_message_get_content_type(msg));
--
-- if (message_id != NULL)
-- g_hash_table_remove(cmdproc->multiparts, message_id);
--}
--
--void
--msn_cmdproc_process_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnTransCb cb = NULL;
-- MsnTransaction *trans = NULL;
--
-- if (cmd->trId)
-- cmd->trans = trans = msn_history_find(cmdproc->history, cmd->trId);
--
-- if (trans != NULL)
-- if (trans->timer) {
-- purple_timeout_remove(trans->timer);
-- trans->timer = 0;
-- }
--
-- if (g_ascii_isdigit(cmd->command[0]) && trans != NULL)
-- {
-- MsnErrorCb error_cb;
-- int error;
--
-- error = atoi(cmd->command);
--
-- error_cb = trans->error_cb;
-- if (error_cb == NULL)
-- error_cb = g_hash_table_lookup(cmdproc->cbs_table->errors, trans->command);
--
-- if (error_cb != NULL)
-- error_cb(cmdproc, trans, error);
-- else
-- msn_error_handle(cmdproc->session, error);
--
-- return;
-- }
--
-- cb = g_hash_table_lookup(cmdproc->cbs_table->async, cmd->command);
--
-- if (cb == NULL && trans != NULL && trans->callbacks != NULL)
-- cb = g_hash_table_lookup(trans->callbacks, cmd->command);
--
-- if (cb == NULL)
-- cb = g_hash_table_lookup(cmdproc->cbs_table->fallback, cmd->command);
--
-- if (cb != NULL)
-- cb(cmdproc, cmd);
-- else
-- purple_debug_warning("msn", "Unhandled command '%s'\n",
-- cmd->command);
--
-- if (trans != NULL && trans->pendent_cmd != NULL)
-- msn_transaction_unqueue_cmd(trans, cmdproc);
--}
--
--void
--msn_cmdproc_process_cmd_text(MsnCmdProc *cmdproc, const char *command)
--{
-- show_debug_cmd(cmdproc, TRUE, command);
--
-- if (cmdproc->last_cmd != NULL)
-- msn_command_unref(cmdproc->last_cmd);
--
-- cmdproc->last_cmd = msn_command_from_string(command);
--
-- msn_cmdproc_process_cmd(cmdproc, cmdproc->last_cmd);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/cmdproc.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/cmdproc.h
---- pidgin-2.10.7/libpurple/protocols/msn/cmdproc.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/cmdproc.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,100 +0,0 @@
--/**
-- * @file cmdproc.h MSN command processor functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_CMDPROC_H
--#define MSN_CMDPROC_H
--
--typedef struct _MsnCmdProc MsnCmdProc;
--
--#include "command.h"
--#include "history.h"
--#include "servconn.h"
--#include "session.h"
--#include "table.h"
--
--struct _MsnCmdProc
--{
-- MsnSession *session;
-- MsnServConn *servconn;
--
-- GQueue *txqueue;
--
-- MsnCommand *last_cmd;
--
-- MsnTable *cbs_table;
--
-- MsnHistory *history;
--
-- GHashTable *multiparts; /**< Multi-part message ID's */
--
-- void *data; /**< Extra data, like the switchboard. */
--};
--
--/**
-- * Creates a MsnCmdProc structure.
-- *
-- * @param session The session to associate with.
-- *
-- * @return A new MsnCmdProc structure.
-- */
--MsnCmdProc *msn_cmdproc_new(MsnSession *session);
--
--/**
-- * Destroys an MsnCmdProc.
-- *
-- * @param cmdproc The object structure.
-- */
--void msn_cmdproc_destroy(MsnCmdProc *cmdproc);
--
--/**
-- * Process the queued transactions.
-- *
-- * @param cmdproc The MsnCmdProc.
-- */
--void msn_cmdproc_process_queue(MsnCmdProc *cmdproc);
--
--/**
-- * Sends transaction using this servconn.
-- *
-- * @param cmdproc The MsnCmdProc to be used.
-- * @param trans The MsnTransaction to be sent.
-- */
--gboolean msn_cmdproc_send_trans(MsnCmdProc *cmdproc, MsnTransaction *trans);
--
--/**
-- * Add a transaction to the queue to be processed latter.
-- *
-- * @param cmdproc The MsnCmdProc in which the transaction will be queued.
-- * @param trans The MsnTransaction to be queued.
-- */
--void msn_cmdproc_queue_trans(MsnCmdProc *cmdproc,
-- MsnTransaction *trans);
--
--void msn_cmdproc_process_msg(MsnCmdProc *cmdproc,
-- MsnMessage *msg);
--void msn_cmdproc_process_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd);
--void msn_cmdproc_process_cmd_text(MsnCmdProc *cmdproc, const char *command);
--void msn_cmdproc_process_payload(MsnCmdProc *cmdproc,
-- char *payload, int payload_len);
--
--#endif /* MSN_CMDPROC_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/command.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/command.c
---- pidgin-2.10.7/libpurple/protocols/msn/command.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/command.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,113 +0,0 @@
--/**
-- * @file command.c MSN command functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#include "internal.h"
--
--#include "command.h"
--
--static gboolean
--is_num(const char *str)
--{
-- const char *c;
-- for (c = str; *c; c++) {
-- if (!(g_ascii_isdigit(*c)))
-- return FALSE;
-- }
--
-- return TRUE;
--}
--
--MsnCommand *
--msn_command_from_string(const char *string)
--{
-- MsnCommand *cmd;
-- char *param_start;
--
-- g_return_val_if_fail(string != NULL, NULL);
--
-- cmd = g_new0(MsnCommand, 1);
-- cmd->command = g_strdup(string);
-- param_start = strchr(cmd->command, ' ');
--
-- if (param_start)
-- {
-- *param_start++ = '\0';
-- cmd->params = g_strsplit_set(param_start, " ", 0);
-- }
--
-- if (cmd->params != NULL)
-- {
-- int c;
--
-- for (c = 0; cmd->params[c] && cmd->params[c][0]; c++);
-- cmd->param_count = c;
--
-- if (cmd->param_count) {
-- char *param = cmd->params[0];
-- cmd->trId = is_num(param) ? atoi(param) : 0;
-- } else {
-- cmd->trId = 0;
-- }
-- }
-- else
-- {
-- cmd->trId = 0;
-- }
--
-- msn_command_ref(cmd);
--
-- return cmd;
--}
--
--static void
--msn_command_destroy(MsnCommand *cmd)
--{
-- g_free(cmd->payload);
-- g_free(cmd->command);
-- g_strfreev(cmd->params);
-- g_free(cmd);
--}
--
--MsnCommand *
--msn_command_ref(MsnCommand *cmd)
--{
-- g_return_val_if_fail(cmd != NULL, NULL);
--
-- cmd->ref_count++;
-- return cmd;
--}
--
--void
--msn_command_unref(MsnCommand *cmd)
--{
-- g_return_if_fail(cmd != NULL);
-- g_return_if_fail(cmd->ref_count > 0);
--
-- cmd->ref_count--;
--
-- if (cmd->ref_count == 0)
-- {
-- msn_command_destroy(cmd);
-- }
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/command.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/command.h
---- pidgin-2.10.7/libpurple/protocols/msn/command.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/command.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,84 +0,0 @@
--/**
-- * @file command.h MSN command functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_COMMAND_H
--#define MSN_COMMAND_H
--
--typedef struct _MsnCommand MsnCommand;
--
--#include "cmdproc.h"
--#include "transaction.h"
--
--typedef void (*MsnPayloadCb)(MsnCmdProc *cmdproc, MsnCommand *cmd,
-- char *payload, size_t len);
--
--/**
-- * A received command.
-- */
--struct _MsnCommand
--{
-- unsigned int trId;
--
-- char *command;
-- char **params;
-- int param_count;
--
-- guint ref_count;
--
-- MsnTransaction *trans;
--
-- char *payload;
-- size_t payload_len;
--
-- MsnPayloadCb payload_cb;
-- void *payload_cbdata;
--};
--
--/**
-- * Create a command object from the incoming string and ref it.
-- *
-- * @param string The incoming string.
-- *
-- * @return A MsnCommand object.
-- */
--MsnCommand *msn_command_from_string(const char *string);
--
--/**
-- * Increment the ref count.
-- *
-- * @param cmd The MsnCommand to be ref.
-- *
-- * @return The ref command.
-- */
--MsnCommand *msn_command_ref(MsnCommand *cmd);
--
--/**
-- * Decrement the ref count. If the count goes to 0, destroy it.
-- *
-- * @param cmd The MsnCommand to be unref.
-- *
-- */
--void msn_command_unref(MsnCommand *cmd);
--
--#endif /* MSN_COMMAND_H */
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/contact.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/contact.c
---- pidgin-2.10.7/libpurple/protocols/msn/contact.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/contact.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,2044 +0,0 @@
--/**
-- * @file contact.c
-- * get MSN contacts via SOAP request
-- * created by MaYuan<mayuan2006@gmail.com>
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "contact.h"
--#include "xmlnode.h"
--#include "group.h"
--#include "msnutils.h"
--#include "soap.h"
--#include "nexus.h"
--#include "user.h"
--
--const char *MsnSoapPartnerScenarioText[] =
--{
-- "Initial",
-- "ContactSave",
-- "MessengerPendingList",
-- "ContactMsgrAPI",
-- "BlockUnblock",
-- "Timer"
--};
--
--const char *MsnMemberRole[] =
--{
-- "Forward",
-- "Allow",
-- "Block",
-- "Reverse",
-- "Pending"
--};
--
--typedef struct {
-- MsnSession *session;
-- MsnSoapPartnerScenario which;
--} GetContactListCbData;
--
--MsnCallbackState *
--msn_callback_state_new(MsnSession *session)
--{
-- MsnCallbackState *state = g_new0(MsnCallbackState, 1);
--
-- state->session = session;
--
-- return state;
--}
--
--MsnCallbackState *
--msn_callback_state_dup(MsnCallbackState *state)
--{
-- MsnCallbackState *new_state = g_new0(MsnCallbackState, 1);
--
-- new_state->session = state->session;
-- new_state->who = g_strdup(state->who);
-- new_state->uid = g_strdup(state->uid);
-- new_state->old_group_name = g_strdup(state->old_group_name);
-- new_state->new_group_name = g_strdup(state->new_group_name);
-- new_state->guid = g_strdup(state->guid);
-- /* The rest should be made new */
--
-- return new_state;
--}
--
--void
--msn_callback_state_free(MsnCallbackState *state)
--{
-- if (state == NULL)
-- return;
--
-- g_free(state->who);
-- g_free(state->uid);
-- g_free(state->old_group_name);
-- g_free(state->new_group_name);
-- g_free(state->guid);
-- xmlnode_free(state->body);
--
-- g_free(state);
--}
--
--void
--msn_callback_state_set_who(MsnCallbackState *state, const gchar *who)
--{
-- g_return_if_fail(state != NULL);
--
-- g_free(state->who);
-- state->who = g_strdup(who);
--}
--
--void
--msn_callback_state_set_uid(MsnCallbackState *state, const gchar *uid)
--{
-- g_return_if_fail(state != NULL);
--
-- g_free(state->uid);
-- state->uid = g_strdup(uid);
--}
--
--void
--msn_callback_state_set_old_group_name(MsnCallbackState *state, const gchar *old_group_name)
--{
-- g_return_if_fail(state != NULL);
--
-- g_free(state->old_group_name);
-- state->old_group_name = g_strdup(old_group_name);
--}
--
--void
--msn_callback_state_set_new_group_name(MsnCallbackState *state, const gchar *new_group_name)
--{
-- g_return_if_fail(state != NULL);
--
-- g_free(state->new_group_name);
-- state->new_group_name = g_strdup(new_group_name);
--}
--
--void
--msn_callback_state_set_guid(MsnCallbackState *state, const gchar *guid)
--{
-- g_return_if_fail(state != NULL);
--
-- g_free(state->guid);
-- state->guid = g_strdup(guid);
--}
--
--
--void
--msn_callback_state_set_list_id(MsnCallbackState *state, MsnListId list_id)
--{
-- g_return_if_fail(state != NULL);
--
-- state->list_id = list_id;
--}
--
--void
--msn_callback_state_set_action(MsnCallbackState *state, MsnCallbackAction action)
--{
-- g_return_if_fail(state != NULL);
--
-- state->action |= action;
--}
--
--/***************************************************************
-- * General SOAP handling
-- ***************************************************************/
--
--static const char *
--msn_contact_operation_str(MsnCallbackAction action)
--{
-- /* Make sure this is large enough when adding more */
-- static char buf[BUF_LEN];
-- buf[0] = '\0';
--
-- if (action & MSN_ADD_BUDDY)
-- strcat(buf, "Adding Buddy,");
-- if (action & MSN_MOVE_BUDDY)
-- strcat(buf, "Moving Buddy,");
-- if (action & MSN_ACCEPTED_BUDDY)
-- strcat(buf, "Accepted Buddy,");
-- if (action & MSN_DENIED_BUDDY)
-- strcat(buf, "Denied Buddy,");
-- if (action & MSN_ADD_GROUP)
-- strcat(buf, "Adding Group,");
-- if (action & MSN_DEL_GROUP)
-- strcat(buf, "Deleting Group,");
-- if (action & MSN_RENAME_GROUP)
-- strcat(buf, "Renaming Group,");
-- if (action & MSN_UPDATE_INFO)
-- strcat(buf, "Updating Contact Info,");
-- if (action & MSN_ANNOTATE_USER)
-- strcat(buf, "Annotating Contact,");
--
-- return buf;
--}
--
--static gboolean msn_contact_request(MsnCallbackState *state);
--
--static void
--msn_contact_request_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-- gpointer data)
--{
-- MsnCallbackState *state = data;
-- xmlnode *fault;
-- char *faultcode_str;
-- xmlnode *cachekey;
-- char *changed;
--
-- if (resp == NULL) {
-- purple_debug_error("msn",
-- "Operation {%s} failed. No response received from server.\n",
-- msn_contact_operation_str(state->action));
-- msn_session_set_error(state->session, MSN_ERROR_BAD_BLIST, NULL);
-- msn_callback_state_free(state);
-- return;
-- }
--
-- /* Update CacheKey if necessary */
-- cachekey = xmlnode_get_child(resp->xml, "Header/ServiceHeader/CacheKeyChanged");
-- if (cachekey != NULL) {
-- changed = xmlnode_get_data(cachekey);
-- if (changed && !strcmp(changed, "true")) {
-- cachekey = xmlnode_get_child(resp->xml, "Header/ServiceHeader/CacheKey");
-- g_free(state->session->abch_cachekey);
-- state->session->abch_cachekey = xmlnode_get_data(cachekey);
-- purple_debug_info("msn", "Updated CacheKey for %s to '%s'.\n",
-- purple_account_get_username(state->session->account),
-- state->session->abch_cachekey);
-- }
-- g_free(changed);
-- }
--
-- fault = xmlnode_get_child(resp->xml, "Body/Fault");
--
-- if (fault == NULL) {
-- /* No errors */
-- if (state->cb)
-- state->cb(req, resp, data);
-- msn_callback_state_free(state);
-- return;
-- }
--
-- faultcode_str = xmlnode_get_data(xmlnode_get_child(fault, "faultcode"));
--
-- if (faultcode_str && g_str_equal(faultcode_str, "q0:BadContextToken")) {
-- purple_debug_info("msn",
-- "Contact Operation {%s} failed because of bad token."
-- " Updating token now and retrying operation.\n",
-- msn_contact_operation_str(state->action));
-- /* Token has expired, so renew it, and try again later */
-- msn_nexus_update_token(state->session->nexus, MSN_AUTH_CONTACTS,
-- (GSourceFunc)msn_contact_request, data);
-- }
-- else
-- {
-- if (state->cb) {
-- state->cb(req, resp, data);
-- } else {
-- /* We don't know how to respond to this faultcode, so log it */
-- char *str = xmlnode_to_str(fault, NULL);
-- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-- msn_contact_operation_str(state->action), str);
-- g_free(str);
-- }
-- msn_callback_state_free(state);
-- }
--
-- g_free(faultcode_str);
--}
--
--static gboolean
--msn_contact_request(MsnCallbackState *state)
--{
-- xmlnode *cachekey = xmlnode_get_child(state->body,
-- "Header/ABApplicationHeader/CacheKey");
-- if (cachekey != NULL)
-- xmlnode_free(cachekey);
-- if (state->session->abch_cachekey != NULL) {
-- cachekey = xmlnode_new_child(xmlnode_get_child(state->body, "Header/ABApplicationHeader"), "CacheKey");
-- xmlnode_insert_data(cachekey, state->session->abch_cachekey, -1);
-- }
-- if (state->token == NULL)
-- state->token = xmlnode_get_child(state->body,
-- "Header/ABAuthHeader/TicketToken");
-- /* delete old & replace with new token */
-- xmlnode_free(state->token->child);
-- xmlnode_insert_data(state->token,
-- msn_nexus_get_token_str(state->session->nexus, MSN_AUTH_CONTACTS), -1);
-- msn_soap_message_send(state->session,
-- msn_soap_message_new(state->post_action, xmlnode_copy(state->body)),
-- MSN_CONTACT_SERVER, state->post_url, FALSE,
-- msn_contact_request_cb, state);
-- return FALSE;
--}
--
--/***************************************************************
-- * Address Book and Membership List Operations
-- ***************************************************************/
--
--/*get MSN member role utility*/
--static MsnListId
--msn_get_memberrole(const char *role)
--{
-- g_return_val_if_fail(role != NULL, 0);
--
-- if (!strcmp(role,"Allow")) {
-- return MSN_LIST_AL;
-- } else if (!strcmp(role,"Block")) {
-- return MSN_LIST_BL;
-- } else if (!strcmp(role,"Reverse")) {
-- return MSN_LIST_RL;
-- } else if (!strcmp(role,"Pending")) {
-- return MSN_LIST_PL;
-- }
-- return 0;
--}
--
--/* Create the AddressBook in the server, if we don't have one */
--static void
--msn_create_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
--{
-- MsnCallbackState *state = data;
-- if (resp && xmlnode_get_child(resp->xml, "Body/Fault") == NULL) {
-- purple_debug_info("msn", "Address Book successfully created!\n");
-- msn_get_address_book(state->session, MSN_PS_INITIAL, NULL, NULL);
-- } else {
-- purple_debug_info("msn", "Address Book creation failed!\n");
-- }
--}
--
--static void
--msn_create_address_book(MsnSession *session)
--{
-- gchar *body;
-- MsnCallbackState *state;
--
-- g_return_if_fail(session != NULL);
-- g_return_if_fail(session->user != NULL);
-- g_return_if_fail(session->user->passport != NULL);
--
-- purple_debug_info("msn", "Creating an Address Book.\n");
--
-- body = g_strdup_printf(MSN_ADD_ADDRESSBOOK_TEMPLATE,
-- session->user->passport);
--
-- state = msn_callback_state_new(session);
-- state->body = xmlnode_from_str(body, -1);
-- state->post_action = MSN_ADD_ADDRESSBOOK_SOAP_ACTION;
-- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-- state->cb = msn_create_address_cb;
-- msn_contact_request(state);
--
-- g_free(body);
--}
--
--static void
--msn_parse_each_member(MsnSession *session, xmlnode *member, const char *node,
-- MsnListId list)
--{
-- char *passport;
-- char *type;
-- char *member_id;
-- MsnUser *user;
-- xmlnode *annotation;
-- guint nid = MSN_NETWORK_UNKNOWN;
-- char *invite = NULL;
--
-- passport = xmlnode_get_data(xmlnode_get_child(member, node));
-- if (!msn_email_is_valid(passport)) {
-- g_free(passport);
-- return;
-- }
--
-- type = xmlnode_get_data(xmlnode_get_child(member, "Type"));
-- member_id = xmlnode_get_data(xmlnode_get_child(member, "MembershipId"));
--
-- user = msn_userlist_find_add_user(session->userlist, passport, NULL);
--
-- for (annotation = xmlnode_get_child(member, "Annotations/Annotation");
-- annotation;
-- annotation = xmlnode_get_next_twin(annotation)) {
-- char *name = xmlnode_get_data(xmlnode_get_child(annotation, "Name"));
-- char *value = xmlnode_get_data(xmlnode_get_child(annotation, "Value"));
-- if (name && value) {
-- if (!strcmp(name, "MSN.IM.BuddyType")) {
-- nid = strtoul(value, NULL, 10);
-- }
-- else if (!strcmp(name, "MSN.IM.InviteMessage")) {
-- invite = value;
-- value = NULL;
-- }
-- }
-- g_free(name);
-- g_free(value);
-- }
--
-- /* For EmailMembers, the network must be found in the annotations, above.
-- Otherwise, PassportMembers are on the Passport network. */
-- if (!strcmp(node, "PassportName"))
-- nid = MSN_NETWORK_PASSPORT;
--
-- purple_debug_info("msn", "CL: %s name: %s, Type: %s, MembershipID: %s, NetworkID: %u\n",
-- node, passport, type, member_id == NULL ? "(null)" : member_id, nid);
--
-- msn_user_set_network(user, nid);
-- msn_user_set_invite_message(user, invite);
--
-- if (list == MSN_LIST_PL && member_id) {
-- user->member_id_on_pending_list = atoi(member_id);
-- }
--
-- msn_got_lst_user(session, user, 1 << list, NULL);
--
-- g_free(passport);
-- g_free(type);
-- g_free(member_id);
-- g_free(invite);
--}
--
--static void
--msn_parse_each_service(MsnSession *session, xmlnode *service)
--{
-- xmlnode *type;
--
-- if ((type = xmlnode_get_child(service, "Info/Handle/Type"))) {
-- char *type_str = xmlnode_get_data(type);
--
-- if (g_str_equal(type_str, "Profile")) {
-- /* Process Windows Live 'Messenger Roaming Identity' */
-- } else if (g_str_equal(type_str, "Messenger")) {
-- xmlnode *lastchange = xmlnode_get_child(service, "LastChange");
-- char *lastchange_str = xmlnode_get_data(lastchange);
-- xmlnode *membership;
--
-- purple_debug_info("msn", "CL last change: %s\n", lastchange_str);
-- purple_account_set_string(session->account, "CLLastChange",
-- lastchange_str);
--
-- for (membership = xmlnode_get_child(service,
-- "Memberships/Membership");
-- membership; membership = xmlnode_get_next_twin(membership)) {
--
-- xmlnode *role = xmlnode_get_child(membership, "MemberRole");
-- char *role_str = xmlnode_get_data(role);
-- MsnListId list = msn_get_memberrole(role_str);
-- xmlnode *member;
--
-- purple_debug_info("msn", "CL MemberRole role: %s, list: %d\n",
-- role_str, list);
--
-- for (member = xmlnode_get_child(membership, "Members/Member");
-- member; member = xmlnode_get_next_twin(member)) {
-- const char *member_type = xmlnode_get_attrib(member, "type");
-- if (g_str_equal(member_type, "PassportMember")) {
-- msn_parse_each_member(session, member, "PassportName",
-- list);
-- } else if (g_str_equal(member_type, "PhoneMember")) {
--
-- } else if (g_str_equal(member_type, "EmailMember")) {
-- msn_parse_each_member(session, member, "Email", list);
-- }
-- }
--
-- g_free(role_str);
-- }
--
-- g_free(lastchange_str);
-- }
--
-- g_free(type_str);
-- }
--}
--
--/*parse contact list*/
--static gboolean
--msn_parse_contact_list(MsnSession *session, xmlnode *node)
--{
-- xmlnode *fault, *faultnode;
--
-- /* we may get a response if our cache data is too old:
-- *
-- * <faultstring>Need to do full sync. Can't sync deltas Client
-- * has too old a copy for us to do a delta sync</faultstring>
-- *
-- * this is not handled yet
-- */
-- if ((fault = xmlnode_get_child(node, "Body/Fault"))) {
-- if ((faultnode = xmlnode_get_child(fault, "faultstring"))) {
-- char *faultstring = xmlnode_get_data(faultnode);
-- purple_debug_info("msn", "Retrieving contact list failed: %s\n",
-- faultstring);
-- g_free(faultstring);
-- }
-- if ((faultnode = xmlnode_get_child(fault, "detail/errorcode"))) {
-- char *errorcode = xmlnode_get_data(faultnode);
--
-- if (g_str_equal(errorcode, "ABDoesNotExist")) {
-- msn_create_address_book(session);
-- g_free(errorcode);
-- return FALSE;
-- }
--
-- g_free(errorcode);
-- }
--
-- msn_get_contact_list(session, MSN_PS_INITIAL, NULL);
-- return FALSE;
-- } else {
-- xmlnode *service;
--
-- for (service = xmlnode_get_child(node, "Body/FindMembershipResponse/"
-- "FindMembershipResult/Services/Service");
-- service; service = xmlnode_get_next_twin(service)) {
-- msn_parse_each_service(session, service);
-- }
-- return TRUE;
-- }
--}
--
--static void
--msn_get_contact_list_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-- gpointer data)
--{
-- MsnCallbackState *state = data;
-- MsnSession *session = state->session;
--
-- g_return_if_fail(session != NULL);
--
-- if (resp != NULL) {
--#ifdef MSN_PARTIAL_LISTS
-- const char *abLastChange;
-- const char *dynamicItemLastChange;
--#endif
--
-- purple_debug_misc("msn", "Got the contact list!\n");
--
-- if (msn_parse_contact_list(session, resp->xml)) {
--#ifdef MSN_PARTIAL_LISTS
-- abLastChange = purple_account_get_string(session->account,
-- "ablastChange", NULL);
-- dynamicItemLastChange = purple_account_get_string(session->account,
-- "DynamicItemLastChanged", NULL);
--#endif
--
-- if (state->partner_scenario == MSN_PS_INITIAL) {
--#ifdef MSN_PARTIAL_LISTS
-- /* XXX: this should be enabled when we can correctly do partial
-- syncs with the server. Currently we need to retrieve the whole
-- list to detect sync issues */
-- msn_get_address_book(session, MSN_PS_INITIAL, abLastChange, dynamicItemLastChange);
--#else
-- msn_get_address_book(session, MSN_PS_INITIAL, NULL, NULL);
--#endif
-- }
-- }
-- }
--}
--
--/*SOAP get contact list*/
--void
--msn_get_contact_list(MsnSession *session,
-- const MsnSoapPartnerScenario partner_scenario, const char *update_time)
--{
-- gchar *body = NULL;
-- gchar *update_str = NULL;
-- MsnCallbackState *state;
-- const gchar *partner_scenario_str = MsnSoapPartnerScenarioText[partner_scenario];
--
-- purple_debug_misc("msn", "Getting Contact List.\n");
--
-- if (update_time != NULL) {
-- purple_debug_info("msn", "CL Last update time: %s\n", update_time);
-- update_str = g_strdup_printf(MSN_GET_CONTACT_UPDATE_XML, update_time);
-- }
--
-- body = g_strdup_printf(MSN_GET_CONTACT_TEMPLATE, partner_scenario_str,
-- update_str ? update_str : "");
--
-- state = msn_callback_state_new(session);
-- state->partner_scenario = partner_scenario;
-- state->body = xmlnode_from_str(body, -1);
-- state->post_action = MSN_GET_CONTACT_SOAP_ACTION;
-- state->post_url = MSN_GET_CONTACT_POST_URL;
-- state->cb = msn_get_contact_list_cb;
-- msn_contact_request(state);
--
-- g_free(update_str);
-- g_free(body);
--}
--
--static void
--msn_parse_addressbook_groups(MsnSession *session, xmlnode *node)
--{
-- xmlnode *group;
--
-- purple_debug_info("msn", "msn_parse_addressbook_groups()\n");
--
-- for(group = xmlnode_get_child(node, "Group"); group;
-- group = xmlnode_get_next_twin(group)){
-- xmlnode *groupId, *groupInfo, *groupname;
-- char *group_id = NULL, *group_name = NULL;
--
-- if ((groupId = xmlnode_get_child(group, "groupId")))
-- group_id = xmlnode_get_data(groupId);
-- if ((groupInfo = xmlnode_get_child(group, "groupInfo")) && (groupname = xmlnode_get_child(groupInfo, "name")))
-- group_name = xmlnode_get_data(groupname);
--
-- if (group_id == NULL) {
-- /* Group of ungroupped buddies */
-- g_free(group_name);
-- continue;
-- }
--
-- msn_group_new(session->userlist, group_id, group_name);
--
-- purple_debug_info("msn", "AB group_id: %s, name: %s\n", group_id, group_name ? group_name : "(null)");
-- if ((purple_find_group(group_name)) == NULL) {
-- PurpleGroup *g = purple_group_new(group_name);
-- purple_blist_add_group(g, NULL);
-- }
-- g_free(group_id);
-- g_free(group_name);
-- }
--}
--
--static gboolean
--msn_parse_addressbook_mobile(xmlnode *contactInfo, char **inout_mobile_number)
--{
-- xmlnode *phones;
-- char *mobile_number = NULL;
-- gboolean mobile = FALSE;
--
-- *inout_mobile_number = NULL;
--
-- if ((phones = xmlnode_get_child(contactInfo, "phones"))) {
-- xmlnode *contact_phone;
-- char *phone_type = NULL;
--
-- for (contact_phone = xmlnode_get_child(phones, "ContactPhone");
-- contact_phone;
-- contact_phone = xmlnode_get_next_twin(contact_phone)) {
-- xmlnode *contact_phone_type;
--
-- if (!(contact_phone_type =
-- xmlnode_get_child(contact_phone, "contactPhoneType")))
-- continue;
--
-- phone_type = xmlnode_get_data(contact_phone_type);
--
-- if (phone_type && !strcmp(phone_type, "ContactPhoneMobile")) {
-- xmlnode *number;
--
-- if ((number = xmlnode_get_child(contact_phone, "number"))) {
-- xmlnode *messenger_enabled;
-- char *is_messenger_enabled = NULL;
--
-- g_free(mobile_number);
-- mobile_number = xmlnode_get_data(number);
--
-- if (mobile_number &&
-- (messenger_enabled = xmlnode_get_child(contact_phone, "isMessengerEnabled"))
-- && (is_messenger_enabled = xmlnode_get_data(messenger_enabled))
-- && !strcmp(is_messenger_enabled, "true"))
-- mobile = TRUE;
--
-- g_free(is_messenger_enabled);
-- }
-- }
--
-- g_free(phone_type);
-- }
-- }
--
-- *inout_mobile_number = mobile_number;
-- return mobile;
--}
--
--static void
--msn_parse_addressbook_contacts(MsnSession *session, xmlnode *node)
--{
-- xmlnode *contactNode;
-- char *passport = NULL, *Name = NULL, *uid = NULL, *type = NULL, *mobile_number = NULL, *alias = NULL;
-- gboolean mobile = FALSE;
-- PurpleConnection *pc = purple_account_get_connection(session->account);
--
-- for(contactNode = xmlnode_get_child(node, "Contact"); contactNode;
-- contactNode = xmlnode_get_next_twin(contactNode)) {
-- xmlnode *contactId, *contactInfo, *contactType, *passportName, *displayName, *guid, *groupIds;
-- xmlnode *annotation;
-- MsnUser *user;
--
-- g_free(passport);
-- g_free(Name);
-- g_free(uid);
-- g_free(type);
-- g_free(mobile_number);
-- g_free(alias);
-- passport = Name = uid = type = mobile_number = alias = NULL;
-- mobile = FALSE;
--
-- if (!(contactId = xmlnode_get_child(contactNode,"contactId"))
-- || !(contactInfo = xmlnode_get_child(contactNode, "contactInfo"))
-- || !(contactType = xmlnode_get_child(contactInfo, "contactType")))
-- continue;
--
-- uid = xmlnode_get_data(contactId);
-- type = xmlnode_get_data(contactType);
--
-- /* Find out our settings */
-- if (type && !strcmp(type, "Me")) {
-- /* setup the Display Name */
-- if (purple_connection_get_display_name(pc) == NULL) {
-- char *friendly = NULL;
-- if ((displayName = xmlnode_get_child(contactInfo, "displayName")))
-- friendly = xmlnode_get_data(displayName);
-- purple_connection_set_display_name(pc,
-- friendly ? purple_url_decode(friendly) : NULL);
-- g_free(friendly);
-- }
--
-- for (annotation = xmlnode_get_child(contactInfo, "annotations/Annotation");
-- annotation;
-- annotation = xmlnode_get_next_twin(annotation)) {
-- char *name, *value;
-- name = xmlnode_get_data(xmlnode_get_child(annotation, "Name"));
-- value = xmlnode_get_data(xmlnode_get_child(annotation, "Value"));
-- if (name && g_str_equal(name, "MSN.IM.MPOP")) {
-- if (!value || atoi(value) != 0)
-- session->enable_mpop = TRUE;
-- else
-- session->enable_mpop = FALSE;
-- }
-- g_free(name);
-- g_free(value);
-- }
--
-- continue; /* Not adding own account as buddy to buddylist */
-- }
--
-- passportName = xmlnode_get_child(contactInfo, "passportName");
-- if (passportName == NULL) {
-- xmlnode *emailsNode, *contactEmailNode, *emailNode;
-- xmlnode *messengerEnabledNode;
-- char *msnEnabled;
--
-- /*TODO: add it to the non-instant Messenger group and recognize as email Membership*/
-- /* Yahoo/Federated User? */
-- emailsNode = xmlnode_get_child(contactInfo, "emails");
-- if (emailsNode == NULL) {
-- /*TODO: need to support the Mobile type*/
-- continue;
-- }
-- for (contactEmailNode = xmlnode_get_child(emailsNode, "ContactEmail");
-- contactEmailNode;
-- contactEmailNode = xmlnode_get_next_twin(contactEmailNode)) {
-- if ((messengerEnabledNode = xmlnode_get_child(contactEmailNode, "isMessengerEnabled"))) {
--
-- msnEnabled = xmlnode_get_data(messengerEnabledNode);
--
-- if (msnEnabled && !strcmp(msnEnabled, "true")) {
-- if ((emailNode = xmlnode_get_child(contactEmailNode, "email")))
-- passport = xmlnode_get_data(emailNode);
--
-- /* Messenger enabled, Get the Passport*/
-- purple_debug_info("msn", "AB Yahoo/Federated User %s\n", passport ? passport : "(null)");
-- g_free(msnEnabled);
-- break;
-- }
--
-- g_free(msnEnabled);
-- }
-- }
-- } else {
-- xmlnode *messenger_user;
-- /* ignore non-messenger contacts */
-- if ((messenger_user = xmlnode_get_child(contactInfo, "isMessengerUser"))) {
-- char *is_messenger_user = xmlnode_get_data(messenger_user);
--
-- if (is_messenger_user && !strcmp(is_messenger_user, "false")) {
-- g_free(is_messenger_user);
-- continue;
-- }
--
-- g_free(is_messenger_user);
-- }
--
-- passport = xmlnode_get_data(passportName);
-- }
--
-- /* Couldn't find anything */
-- if (passport == NULL)
-- continue;
--
-- if (!msn_email_is_valid(passport))
-- continue;
--
-- if ((displayName = xmlnode_get_child(contactInfo, "displayName")))
-- Name = xmlnode_get_data(displayName);
-- else
-- Name = g_strdup(passport);
--
-- for (annotation = xmlnode_get_child(contactInfo, "annotations/Annotation");
-- annotation;
-- annotation = xmlnode_get_next_twin(annotation)) {
-- char *name;
-- name = xmlnode_get_data(xmlnode_get_child(annotation, "Name"));
-- if (!name)
-- continue;
-- if (!strcmp(name, "AB.NickName"))
-- alias = xmlnode_get_data(xmlnode_get_child(annotation, "Value"));
-- else if (!strcmp(name, "MSN.IM.HasSharedFolder"))
-- ; /* Do nothing yet... */
-- else if (!strcmp(name, "AB.Spouse"))
-- ; /* Do nothing yet... */
-- else if (!strcmp(name, "MSN.Mobile.ContactId"))
-- ; /* Do nothing yet... */
-- else
-- purple_debug_info("msn",
-- "Unknown AB contact annotation: %s\n", name);
-- g_free(name);
-- }
--
-- mobile = msn_parse_addressbook_mobile(contactInfo, &mobile_number);
--
-- purple_debug_misc("msn", "AB passport:{%s} uid:{%s} display:{%s} alias: {%s} mobile:{%s} mobile number:{%s}\n",
-- passport, uid ? uid : "(null)", Name ? Name : "(null)", alias ? alias : "(null)",
-- mobile ? "true" : "false", mobile_number ? mobile_number : "(null)");
--
-- user = msn_userlist_find_add_user(session->userlist, passport, Name);
-- msn_user_set_uid(user, uid);
-- msn_user_set_mobile_phone(user, mobile_number);
--
-- groupIds = xmlnode_get_child(contactInfo, "groupIds");
-- if (groupIds) {
-- for (guid = xmlnode_get_child(groupIds, "guid"); guid;
-- guid = xmlnode_get_next_twin(guid)) {
-- char *group_id = xmlnode_get_data(guid);
-- msn_user_add_group_id(user, group_id);
-- purple_debug_misc("msn", "AB guid:%s\n", group_id ? group_id : "(null)");
-- g_free(group_id);
-- }
-- } else {
-- purple_debug_info("msn", "User not in any groups, adding to default group.\n");
-- /*not in any group,Then set default group*/
-- msn_user_add_group_id(user, MSN_INDIVIDUALS_GROUP_ID);
-- }
--
-- msn_got_lst_user(session, user, MSN_LIST_FL_OP, NULL);
--
-- if (mobile && user)
-- {
-- user->mobile = TRUE;
-- purple_prpl_got_user_status(session->account, user->passport, "mobile", NULL);
-- purple_prpl_got_user_status(session->account, user->passport, "available", NULL);
-- }
-- if (alias)
-- purple_serv_got_private_alias(pc, passport, alias);
-- }
--
-- g_free(passport);
-- g_free(Name);
-- g_free(uid);
-- g_free(type);
-- g_free(mobile_number);
-- g_free(alias);
--}
--
--static void
--msn_parse_addressbook_circles(MsnSession *session, xmlnode *node)
--{
-- xmlnode *ticket;
--
-- /* TODO: Parse groups */
--
-- ticket = xmlnode_get_child(node, "CircleTicket");
-- if (ticket) {
-- char *data = xmlnode_get_data(ticket);
-- msn_notification_send_circle_auth(session, data);
-- g_free(data);
-- }
--}
--
--static gboolean
--msn_parse_addressbook(MsnSession *session, xmlnode *node)
--{
-- xmlnode *result;
-- xmlnode *groups;
-- xmlnode *contacts;
-- xmlnode *abNode;
-- xmlnode *circleNode;
-- xmlnode *fault;
--
-- if ((fault = xmlnode_get_child(node, "Body/Fault"))) {
-- xmlnode *faultnode;
--
-- if ((faultnode = xmlnode_get_child(fault, "faultstring"))) {
-- gchar *faultstring = xmlnode_get_data(faultnode);
-- purple_debug_info("msn", "AB Faultstring: %s\n", faultstring);
-- g_free(faultstring);
-- }
--
-- if ((faultnode = xmlnode_get_child(fault, "detail/errorcode"))) {
-- gchar *errorcode = xmlnode_get_data(faultnode);
--
-- purple_debug_info("msn", "AB Error Code: %s\n", errorcode);
--
-- if (g_str_equal(errorcode, "ABDoesNotExist")) {
-- g_free(errorcode);
-- return TRUE;
-- }
-- g_free(errorcode);
-- }
--
-- return FALSE;
-- }
--
-- result = xmlnode_get_child(node, "Body/ABFindContactsPagedResponse/ABFindContactsPagedResult");
-- if (result == NULL) {
-- purple_debug_misc("msn", "Received no address book update\n");
-- return TRUE;
-- }
--
-- /* I don't see this "groups" tag documented on msnpiki, need to find out
-- if they are really there, and update msnpiki */
-- /*Process Group List*/
-- groups = xmlnode_get_child(result, "Groups");
-- if (groups != NULL) {
-- msn_parse_addressbook_groups(session, groups);
-- }
--
-- /* Add an "Other Contacts" group for buddies who aren't in a group */
-- msn_group_new(session->userlist, MSN_INDIVIDUALS_GROUP_ID,
-- MSN_INDIVIDUALS_GROUP_NAME);
-- purple_debug_misc("msn", "AB group_id:%s name:%s\n",
-- MSN_INDIVIDUALS_GROUP_ID, MSN_INDIVIDUALS_GROUP_NAME);
-- if ((purple_find_group(MSN_INDIVIDUALS_GROUP_NAME)) == NULL){
-- PurpleGroup *g = purple_group_new(MSN_INDIVIDUALS_GROUP_NAME);
-- purple_blist_add_group(g, NULL);
-- }
--
-- /* Add a "Non-IM Contacts" group */
-- msn_group_new(session->userlist, MSN_NON_IM_GROUP_ID, MSN_NON_IM_GROUP_NAME);
-- purple_debug_misc("msn", "AB group_id:%s name:%s\n", MSN_NON_IM_GROUP_ID, MSN_NON_IM_GROUP_NAME);
-- if ((purple_find_group(MSN_NON_IM_GROUP_NAME)) == NULL) {
-- PurpleGroup *g = purple_group_new(MSN_NON_IM_GROUP_NAME);
-- purple_blist_add_group(g, NULL);
-- }
--
-- /*Process contact List*/
-- purple_debug_info("msn", "Process contact list...\n");
-- contacts = xmlnode_get_child(result, "Contacts");
-- if (contacts != NULL) {
-- msn_parse_addressbook_contacts(session, contacts);
-- }
--
-- abNode = xmlnode_get_child(result, "Ab");
-- if (abNode != NULL) {
-- xmlnode *node2;
-- char *tmp = NULL;
--
-- if ((node2 = xmlnode_get_child(abNode, "lastChange")))
-- tmp = xmlnode_get_data(node2);
-- purple_debug_info("msn", "AB lastchanged Time:{%s}\n", tmp ? tmp : "(null)");
-- purple_account_set_string(session->account, "ablastChange", tmp);
--
-- g_free(tmp); tmp = NULL;
-- if ((node2 = xmlnode_get_child(abNode, "DynamicItemLastChanged")))
-- tmp = xmlnode_get_data(node2);
-- purple_debug_info("msn", "AB DynamicItemLastChanged :{%s}\n", tmp ? tmp : "(null)");
-- purple_account_set_string(session->account, "DynamicItemLastChanged", tmp);
-- g_free(tmp);
-- }
--
-- circleNode = xmlnode_get_child(result, "CircleResult");
-- if (circleNode != NULL) {
-- msn_parse_addressbook_circles(session, circleNode);
-- }
--
-- return TRUE;
--}
--
--static void
--msn_get_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
--{
-- MsnCallbackState *state = data;
-- MsnSession *session = state->session;
--
-- g_return_if_fail(session != NULL);
--
-- purple_debug_misc("msn", "Got the Address Book!\n");
--
-- if (msn_parse_addressbook(session, resp->xml)) {
-- msn_send_privacy(session->account->gc);
-- msn_notification_dump_contact(session);
-- } else {
-- /* This is making us loop infinitely when we fail to parse the
-- address book, disable for now (we should re-enable when we
-- send timestamps)
-- */
-- /*
-- msn_get_address_book(session, NULL, NULL);
-- */
-- msn_session_set_error(session, MSN_ERROR_BAD_BLIST, NULL);
-- }
--}
--
--/*get the address book*/
--void
--msn_get_address_book(MsnSession *session,
-- MsnSoapPartnerScenario partner_scenario, const char *LastChanged,
-- const char *dynamicItemLastChange)
--{
-- char *body, *update_str = NULL;
-- MsnCallbackState *state;
--
-- purple_debug_misc("msn", "Getting Address Book\n");
--
-- /*build SOAP and POST it*/
-- if (dynamicItemLastChange != NULL)
-- update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML, dynamicItemLastChange);
-- else if (LastChanged != NULL)
-- update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML, LastChanged);
--
-- body = g_strdup_printf(MSN_GET_ADDRESS_TEMPLATE,
-- MsnSoapPartnerScenarioText[partner_scenario],
-- update_str ? update_str : "");
--
-- state = msn_callback_state_new(session);
-- state->body = xmlnode_from_str(body, -1);
-- state->post_action = MSN_GET_ADDRESS_SOAP_ACTION;
-- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-- state->cb = msn_get_address_cb;
-- msn_contact_request(state);
--
-- g_free(update_str);
-- g_free(body);
--}
--
--/***************************************************************
-- * Contact Operations
-- ***************************************************************/
--
--static void
--msn_add_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-- gpointer data)
--{
-- MsnCallbackState *state = data;
-- MsnSession *session = state->session;
--
-- MsnUserList *userlist;
-- MsnUser *user;
-- xmlnode *guid;
--
-- xmlnode *fault;
--
-- g_return_if_fail(session != NULL);
-- userlist = session->userlist;
--
-- fault = xmlnode_get_child(resp->xml, "Body/Fault");
-- if (fault != NULL) {
-- char *errorcode = xmlnode_get_data(xmlnode_get_child(fault, "detail/errorcode"));
-- if (errorcode && !strcmp(errorcode, "EmailDomainIsFederated")) {
-- /* Do something special! */
-- purple_debug_error("msn", "Contact is from a federated domain, but don't know what to do yet!\n");
--
-- } else if (errorcode && !strcmp(errorcode, "InvalidPassportUser")) {
-- PurpleBuddy *buddy = purple_find_buddy(session->account, state->who);
-- char *str = g_strdup_printf(_("Unable to add \"%s\"."), state->who);
-- purple_notify_error(state->session, _("Buddy Add error"), str,
-- _("The username specified does not exist."));
-- g_free(str);
-- msn_userlist_rem_buddy(userlist, state->who);
-- if (buddy != NULL)
-- purple_blist_remove_buddy(buddy);
--
-- } else {
-- /* We don't know how to respond to this faultcode, so log it */
-- char *fault_str = xmlnode_to_str(fault, NULL);
-- if (fault_str != NULL) {
-- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-- msn_contact_operation_str(state->action), fault_str);
-- g_free(fault_str);
-- }
-- }
-- return;
-- }
--
-- purple_debug_info("msn", "Contact added successfully\n");
--
-- msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_AL);
-- msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_FL);
--
-- user = msn_userlist_find_add_user(userlist, state->who, state->who);
-- msn_user_add_group_id(user, state->guid);
--
-- guid = xmlnode_get_child(resp->xml,
-- "Body/ABContactAddResponse/ABContactAddResult/guid");
-- if (guid != NULL) {
-- char *uid = xmlnode_get_data(guid);
-- msn_user_set_uid(user, uid);
-- purple_debug_info("msn", "Set %s guid to %s.\n", state->who, uid);
-- g_free(uid);
-- }
--}
--
--/* add a Contact in MSN_INDIVIDUALS_GROUP */
--void
--msn_add_contact(MsnSession *session, MsnCallbackState *state, const char *passport)
--{
-- MsnUser *user;
-- gchar *body = NULL;
-- gchar *contact_xml = NULL;
--
-- purple_debug_info("msn", "Adding contact %s to contact list\n", passport);
--
-- user = msn_userlist_find_user(session->userlist, passport);
-- if (user == NULL) {
-- purple_debug_warning("msn", "Unable to retrieve user %s from the userlist!\n", passport);
-- return; /* guess this never happened! */
-- }
--
-- if (user->networkid != MSN_NETWORK_PASSPORT) {
-- contact_xml = g_strdup_printf(MSN_CONTACT_EMAIL_XML,
-- user->networkid == MSN_NETWORK_YAHOO ?
-- "Messenger2" :
-- "Messenger3",
-- passport, 0);
-- } else {
-- contact_xml = g_strdup_printf(MSN_CONTACT_XML, passport);
-- }
-- body = g_strdup_printf(MSN_ADD_CONTACT_TEMPLATE, contact_xml);
--
-- state->body = xmlnode_from_str(body, -1);
-- state->post_action = MSN_CONTACT_ADD_SOAP_ACTION;
-- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-- state->cb = msn_add_contact_read_cb;
-- msn_contact_request(state);
--
-- g_free(contact_xml);
-- g_free(body);
--}
--
--static void
--msn_add_contact_to_group_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-- gpointer data)
--{
-- MsnCallbackState *state = data;
-- MsnSession *session = state->session;
-- MsnUserList *userlist;
-- xmlnode *fault;
--
-- g_return_if_fail(session != NULL);
-- userlist = session->userlist;
--
-- fault = xmlnode_get_child(resp->xml, "Body/Fault");
-- if (fault != NULL) {
-- char *errorcode = xmlnode_get_data(xmlnode_get_child(fault, "detail/errorcode"));
-- if (errorcode && !strcmp(errorcode, "EmailDomainIsFederated")) {
-- /* Do something special! */
-- purple_debug_error("msn", "Contact is from a federated domain, but don't know what to do yet!\n");
--
-- } else if (errorcode && !strcmp(errorcode, "InvalidPassportUser")) {
-- PurpleBuddy *buddy = purple_find_buddy(session->account, state->who);
-- char *str = g_strdup_printf(_("Unable to add \"%s\"."), state->who);
-- purple_notify_error(session, _("Buddy Add error"), str,
-- _("The username specified does not exist."));
-- g_free(str);
-- msn_userlist_rem_buddy(userlist, state->who);
-- if (buddy != NULL)
-- purple_blist_remove_buddy(buddy);
--
-- } else {
-- /* We don't know how to respond to this faultcode, so log it */
-- char *fault_str = xmlnode_to_str(fault, NULL);
-- if (fault_str != NULL) {
-- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-- msn_contact_operation_str(state->action), fault_str);
-- g_free(fault_str);
-- }
-- }
-- return;
-- }
--
-- if (msn_userlist_add_buddy_to_group(userlist, state->who,
-- state->new_group_name)) {
-- purple_debug_info("msn", "Contact %s added to group %s successfully!\n", state->who, state->new_group_name);
-- } else {
-- purple_debug_info("msn", "Contact %s added to group %s successfully on server, but failed in the local list\n", state->who, state->new_group_name);
-- }
--
-- if (state->action & MSN_ADD_BUDDY) {
-- MsnUser *user = msn_userlist_find_user(userlist, state->who);
-- xmlnode *guid = xmlnode_get_child(resp->xml,
-- "Body/ABGroupContactAddResponse/ABGroupContactAddResult/guid");
--
-- if (guid != NULL) {
-- char *uid = xmlnode_get_data(guid);
-- msn_user_set_uid(user, uid);
-- purple_debug_info("msn", "Set %s guid to %s.\n", state->who, uid);
-- g_free(uid);
-- }
--
-- msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_AL);
-- msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_FL);
--
-- if (msn_user_is_in_list(user, MSN_LIST_PL)) {
-- msn_del_contact_from_list(state->session, NULL, state->who, MSN_LIST_PL);
-- return;
-- }
-- }
--
-- if (state->action & MSN_MOVE_BUDDY) {
-- msn_del_contact_from_group(state->session, state->who, state->old_group_name);
-- }
--}
--
--void
--msn_add_contact_to_group(MsnSession *session, MsnCallbackState *state,
-- const char *passport, const char *groupId)
--{
-- MsnUserList *userlist;
-- MsnUser *user;
-- gchar *body = NULL, *contact_xml, *invite;
--
-- g_return_if_fail(passport != NULL);
-- g_return_if_fail(groupId != NULL);
--
-- g_return_if_fail(session != NULL);
--
-- userlist = session->userlist;
--
-- if (!strcmp(groupId, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(groupId, MSN_NON_IM_GROUP_ID)) {
--
-- user = msn_userlist_find_add_user(userlist, passport, passport);
--
-- if (state->action & MSN_ADD_BUDDY) {
-- msn_add_contact(session, state, passport);
-- return;
-- }
--
-- if (state->action & MSN_MOVE_BUDDY) {
-- msn_user_add_group_id(user, groupId);
-- msn_del_contact_from_group(session, passport, state->old_group_name);
-- }
--
-- return;
-- }
--
-- purple_debug_info("msn", "Adding user %s to group %s\n", passport,
-- msn_userlist_find_group_name(userlist, groupId));
--
-- user = msn_userlist_find_user(userlist, passport);
-- if (user == NULL) {
-- purple_debug_warning("msn", "Unable to retrieve user %s from the userlist!\n", passport);
-- msn_callback_state_free(state);
-- return; /* guess this never happened! */
-- }
--
-- if (user->uid != NULL) {
-- contact_xml = g_strdup_printf(MSN_CONTACT_ID_XML, user->uid);
-- } else if (user->networkid != MSN_NETWORK_PASSPORT) {
-- contact_xml = g_strdup_printf(MSN_CONTACT_EMAIL_XML,
-- user->networkid == MSN_NETWORK_YAHOO ?
-- "Messenger2" :
-- "Messenger3",
-- passport, 0);
-- } else {
-- contact_xml = g_strdup_printf(MSN_CONTACT_XML, passport);
-- }
--
-- if (user->invite_message) {
-- char *tmp;
-- body = g_markup_escape_text(user->invite_message, -1);
--
-- /* Ignore the cast, we treat it as const anyway. */
-- tmp = (char *)purple_connection_get_display_name(session->account->gc);
-- tmp = tmp ? g_markup_escape_text(tmp, -1) : g_strdup("");
--
-- invite = g_strdup_printf(MSN_CONTACT_INVITE_MESSAGE_XML, body, tmp);
--
-- g_free(body);
-- g_free(tmp);
--
-- /* We can free this now */
-- g_free(user->invite_message);
-- user->invite_message = NULL;
--
-- } else {
-- invite = g_strdup("");
-- }
--
-- body = g_strdup_printf(MSN_ADD_CONTACT_GROUP_TEMPLATE, groupId, contact_xml, invite);
--
-- state->body = xmlnode_from_str(body, -1);
-- state->post_action = MSN_ADD_CONTACT_GROUP_SOAP_ACTION;
-- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-- state->cb = msn_add_contact_to_group_read_cb;
-- msn_contact_request(state);
--
-- g_free(invite);
-- g_free(contact_xml);
-- g_free(body);
--}
--
--static void
--msn_delete_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-- gpointer data)
--{
-- MsnCallbackState *state = data;
-- MsnUserList *userlist = state->session->userlist;
-- MsnUser *user = msn_userlist_find_user_with_id(userlist, state->uid);
-- xmlnode *fault;
--
-- /* We don't know how to respond to this faultcode, so log it */
-- fault = xmlnode_get_child(resp->xml, "Body/Fault");
-- if (fault != NULL) {
-- char *fault_str = xmlnode_to_str(fault, NULL);
-- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-- msn_contact_operation_str(state->action), fault_str);
-- g_free(fault_str);
-- return;
-- }
--
-- purple_debug_info("msn", "Delete contact successful\n");
--
-- if (user != NULL) {
-- msn_userlist_remove_user(userlist, user);
-- }
--}
--
--/*delete a Contact*/
--void
--msn_delete_contact(MsnSession *session, MsnUser *user)
--{
-- gchar *body = NULL;
-- gchar *contact_id_xml = NULL ;
-- MsnCallbackState *state;
--
-- if (user->uid != NULL) {
-- contact_id_xml = g_strdup_printf(MSN_CONTACT_ID_XML, user->uid);
-- purple_debug_info("msn", "Deleting contact with contactId: %s\n", user->uid);
-- } else {
-- purple_debug_info("msn", "Unable to delete contact %s without a ContactId\n", user->passport);
-- return;
-- }
--
-- state = msn_callback_state_new(session);
-- msn_callback_state_set_uid(state, user->uid);
--
-- /* build SOAP request */
-- body = g_strdup_printf(MSN_DEL_CONTACT_TEMPLATE, contact_id_xml);
--
-- state->body = xmlnode_from_str(body, -1);
-- state->post_action = MSN_CONTACT_DEL_SOAP_ACTION;
-- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-- state->cb = msn_delete_contact_read_cb;
-- msn_contact_request(state);
--
-- g_free(contact_id_xml);
-- g_free(body);
--}
--
--static void
--msn_del_contact_from_group_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-- gpointer data)
--{
-- MsnCallbackState *state = data;
-- xmlnode *fault;
--
-- /* We don't know how to respond to this faultcode, so log it */
-- fault = xmlnode_get_child(resp->xml, "Body/Fault");
-- if (fault != NULL) {
-- char *fault_str = xmlnode_to_str(fault, NULL);
-- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-- msn_contact_operation_str(state->action), fault_str);
-- g_free(fault_str);
-- return;
-- }
--
-- if (msn_userlist_rem_buddy_from_group(state->session->userlist,
-- state->who, state->old_group_name)) {
-- purple_debug_info("msn", "Contact %s deleted successfully from group %s\n", state->who, state->old_group_name);
-- } else {
-- purple_debug_info("msn", "Contact %s deleted successfully from group %s in the server, but failed in the local list\n", state->who, state->old_group_name);
-- }
--}
--
--void
--msn_del_contact_from_group(MsnSession *session, const char *passport, const char *group_name)
--{
-- MsnUserList * userlist;
-- MsnUser *user;
-- MsnCallbackState *state;
-- gchar *body, *contact_id_xml;
-- const gchar *groupId;
--
-- g_return_if_fail(passport != NULL);
-- g_return_if_fail(group_name != NULL);
-- g_return_if_fail(session != NULL);
--
-- userlist = session->userlist;
--
-- groupId = msn_userlist_find_group_id(userlist, group_name);
-- if (groupId != NULL) {
-- purple_debug_info("msn", "Deleting user %s from group %s\n", passport, group_name);
-- } else {
-- purple_debug_warning("msn", "Unable to retrieve group id from group %s !\n", group_name);
-- return;
-- }
--
-- user = msn_userlist_find_user(userlist, passport);
--
-- if (user == NULL) {
-- purple_debug_warning("msn", "Unable to retrieve user from passport %s!\n", passport);
-- return;
-- }
--
-- if ( !strcmp(groupId, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(groupId, MSN_NON_IM_GROUP_ID)) {
-- msn_user_remove_group_id(user, groupId);
-- return;
-- }
--
-- state = msn_callback_state_new(session);
-- msn_callback_state_set_who(state, passport);
-- msn_callback_state_set_guid(state, groupId);
-- msn_callback_state_set_old_group_name(state, group_name);
--
-- if (user->uid != NULL)
-- contact_id_xml = g_strdup_printf(MSN_CONTACT_ID_XML, user->uid);
-- else
-- contact_id_xml = g_strdup_printf(MSN_CONTACT_XML, passport);
-- body = g_strdup_printf(MSN_CONTACT_DEL_GROUP_TEMPLATE, contact_id_xml, groupId);
--
-- state->body = xmlnode_from_str(body, -1);
-- state->post_action = MSN_CONTACT_DEL_GROUP_SOAP_ACTION;
-- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-- state->cb = msn_del_contact_from_group_read_cb;
-- msn_contact_request(state);
--
-- g_free(contact_id_xml);
-- g_free(body);
--}
--
--
--static void
--msn_update_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-- gpointer data)
--{
-- MsnCallbackState *state = (MsnCallbackState *)data;
-- xmlnode *fault;
--
-- /* We don't know how to respond to this faultcode, so log it */
-- fault = xmlnode_get_child(resp->xml, "Body/Fault");
-- if (fault != NULL) {
-- char *fault_str = xmlnode_to_str(fault, NULL);
-- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-- msn_contact_operation_str(state->action), fault_str);
-- g_free(fault_str);
-- return;
-- }
--
-- purple_debug_info("msn", "Contact updated successfully\n");
--}
--
--/* Update a contact's info */
--void
--msn_update_contact(MsnSession *session, const char *passport, MsnContactUpdateType type, const char* value)
--{
-- MsnCallbackState *state;
-- xmlnode *contact;
-- xmlnode *contact_info;
-- xmlnode *changes;
-- MsnUser *user = NULL;
--
-- purple_debug_info("msn", "Update contact information for %s with new %s: %s\n",
-- passport ? passport : "(null)",
-- type == MSN_UPDATE_DISPLAY ? "display name" : "alias",
-- value ? value : "(null)");
-- g_return_if_fail(passport != NULL);
--
-- if (strcmp(passport, "Me") != 0) {
-- user = msn_userlist_find_user(session->userlist, passport);
-- if (!user)
-- return;
-- }
--
-- contact_info = xmlnode_new("contactInfo");
-- changes = xmlnode_new("propertiesChanged");
--
-- switch (type) {
-- xmlnode *annotations;
-- xmlnode *display;
-- xmlnode *a, *n, *v;
-- case MSN_UPDATE_DISPLAY:
-- display = xmlnode_new_child(contact_info, "displayName");
-- xmlnode_insert_data(display, value, -1);
-- xmlnode_insert_data(changes, "DisplayName", -1);
-- break;
--
-- case MSN_UPDATE_ALIAS:
-- annotations = xmlnode_new_child(contact_info, "annotations");
-- xmlnode_insert_data(changes, "Annotation ", -1);
--
-- a = xmlnode_new_child(annotations, "Annotation");
-- n = xmlnode_new_child(a, "Name");
-- xmlnode_insert_data(n, "AB.NickName", -1);
-- v = xmlnode_new_child(a, "Value");
-- xmlnode_insert_data(v, value, -1);
-- break;
--
-- default:
-- g_return_if_reached();
-- }
--
-- state = msn_callback_state_new(session);
--
-- state->body = xmlnode_from_str(MSN_CONTACT_UPDATE_TEMPLATE, -1);
-- state->action = MSN_UPDATE_INFO;
-- state->post_action = MSN_CONTACT_UPDATE_SOAP_ACTION;
-- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-- state->cb = msn_update_contact_read_cb;
--
-- contact = xmlnode_get_child(state->body, "Body/ABContactUpdate/contacts/Contact");
-- xmlnode_insert_child(contact, contact_info);
-- xmlnode_insert_child(contact, changes);
--
-- xmlnode_insert_data(xmlnode_get_child(state->body,
-- "Header/ABApplicationHeader/PartnerScenario"),
-- MsnSoapPartnerScenarioText[MSN_PS_SAVE_CONTACT], -1);
--
-- if (user) {
-- xmlnode *contactId = xmlnode_new_child(contact, "contactId");
-- msn_callback_state_set_uid(state, user->uid);
-- xmlnode_insert_data(contactId, state->uid, -1);
-- } else {
-- xmlnode *contactType = xmlnode_new_child(contact_info, "contactType");
-- xmlnode_insert_data(contactType, "Me", -1);
-- }
--
-- msn_contact_request(state);
--}
--
--static void
--msn_annotate_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-- gpointer data)
--{
-- MsnCallbackState *state = (MsnCallbackState *)data;
-- xmlnode *fault;
--
-- /* We don't know how to respond to this faultcode, so log it */
-- fault = xmlnode_get_child(resp->xml, "Body/Fault");
-- if (fault != NULL) {
-- char *fault_str = xmlnode_to_str(fault, NULL);
-- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-- msn_contact_operation_str(state->action), fault_str);
-- g_free(fault_str);
-- return;
-- }
--
-- purple_debug_info("msn", "Contact annotated successfully\n");
--}
--
--/* Update a contact's annotations */
--void
--msn_annotate_contact(MsnSession *session, const char *passport, ...)
--{
-- va_list params;
-- MsnCallbackState *state;
-- xmlnode *contact;
-- xmlnode *contact_info;
-- xmlnode *annotations;
-- MsnUser *user = NULL;
--
-- g_return_if_fail(passport != NULL);
--
-- if (strcmp(passport, "Me") != 0) {
-- user = msn_userlist_find_user(session->userlist, passport);
-- if (!user)
-- return;
-- }
--
-- contact_info = xmlnode_new("contactInfo");
-- annotations = xmlnode_new_child(contact_info, "annotations");
--
-- va_start(params, passport);
-- while (TRUE) {
-- const char *name;
-- const char *value;
-- xmlnode *a, *n, *v;
--
-- name = va_arg(params, const char *);
-- if (!name)
-- break;
--
-- value = va_arg(params, const char *);
-- if (!value)
-- break;
--
-- a = xmlnode_new_child(annotations, "Annotation");
-- n = xmlnode_new_child(a, "Name");
-- xmlnode_insert_data(n, name, -1);
-- v = xmlnode_new_child(a, "Value");
-- xmlnode_insert_data(v, value, -1);
-- }
-- va_end(params);
--
-- state = msn_callback_state_new(session);
--
-- state->body = xmlnode_from_str(MSN_CONTACT_ANNOTATE_TEMPLATE, -1);
-- state->action = MSN_ANNOTATE_USER;
-- state->post_action = MSN_CONTACT_ANNOTATE_SOAP_ACTION;
-- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-- state->cb = msn_annotate_contact_read_cb;
--
-- xmlnode_insert_data(xmlnode_get_child(state->body,
-- "Header/ABApplicationHeader/PartnerScenario"),
-- MsnSoapPartnerScenarioText[MSN_PS_SAVE_CONTACT], -1);
--
-- contact = xmlnode_get_child(state->body, "Body/ABContactUpdate/contacts/Contact");
-- xmlnode_insert_child(contact, contact_info);
--
-- if (user) {
-- xmlnode *contactId = xmlnode_new_child(contact, "contactId");
-- msn_callback_state_set_uid(state, user->uid);
-- xmlnode_insert_data(contactId, state->uid, -1);
-- } else {
-- xmlnode *contactType = xmlnode_new_child(contact_info, "contactType");
-- xmlnode_insert_data(contactType, "Me", -1);
-- }
--
-- msn_contact_request(state);
--}
--
--static void
--msn_del_contact_from_list_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-- gpointer data)
--{
-- MsnCallbackState *state = data;
-- MsnSession *session = state->session;
-- xmlnode *fault;
--
-- /* We don't know how to respond to this faultcode, so log it */
-- fault = xmlnode_get_child(resp->xml, "Body/Fault");
-- if (fault != NULL) {
-- char *fault_str = xmlnode_to_str(fault, NULL);
-- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-- msn_contact_operation_str(state->action), fault_str);
-- g_free(fault_str);
-- return;
-- }
--
-- purple_debug_info("msn", "Contact %s deleted successfully from %s list on server!\n", state->who, MsnMemberRole[state->list_id]);
--
-- if (state->list_id == MSN_LIST_PL) {
-- MsnUser *user = msn_userlist_find_user(session->userlist, state->who);
-- MsnCallbackState *new_state = msn_callback_state_dup(state);
--
-- if (user != NULL)
-- msn_user_unset_op(user, MSN_LIST_PL_OP);
--
-- msn_add_contact_to_list(session, new_state, state->who, MSN_LIST_RL);
-- return;
-- } else if (state->list_id == MSN_LIST_AL) {
-- purple_privacy_permit_remove(session->account, state->who, TRUE);
-- msn_add_contact_to_list(session, NULL, state->who, MSN_LIST_BL);
-- } else if (state->list_id == MSN_LIST_BL) {
-- purple_privacy_deny_remove(session->account, state->who, TRUE);
-- msn_add_contact_to_list(session, NULL, state->who, MSN_LIST_AL);
-- }
--
--}
--
--void
--msn_del_contact_from_list(MsnSession *session, MsnCallbackState *state,
-- const gchar *passport, const MsnListId list)
--{
-- gchar *body = NULL, *member = NULL;
-- MsnSoapPartnerScenario partner_scenario;
-- MsnUser *user;
--
-- g_return_if_fail(session != NULL);
-- g_return_if_fail(session->userlist != NULL);
-- g_return_if_fail(passport != NULL);
-- g_return_if_fail(list < 5);
--
-- purple_debug_info("msn", "Deleting contact %s from %s list\n", passport, MsnMemberRole[list]);
--
-- if (state == NULL) {
-- state = msn_callback_state_new(session);
-- }
-- msn_callback_state_set_list_id(state, list);
-- msn_callback_state_set_who(state, passport);
--
-- user = msn_userlist_find_user(session->userlist, passport);
--
-- if (list == MSN_LIST_PL) {
-- partner_scenario = MSN_PS_CONTACT_API;
-- if (user->networkid != MSN_NETWORK_PASSPORT)
-- member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML,
-- "EmailMember", "Email",
-- user->member_id_on_pending_list);
-- else
-- member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML,
-- "PassportMember", "Passport",
-- user->member_id_on_pending_list);
-- } else {
-- /* list == MSN_LIST_AL || list == MSN_LIST_BL */
-- partner_scenario = MSN_PS_BLOCK_UNBLOCK;
-- if (user && user->networkid != MSN_NETWORK_PASSPORT)
-- member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
-- "EmailMember", "Email",
-- "Email", passport, "Email");
-- else
-- member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
-- "PassportMember", "Passport",
-- "PassportName", passport, "PassportName");
-- }
--
-- body = g_strdup_printf(MSN_CONTACT_DELETE_FROM_LIST_TEMPLATE,
-- MsnSoapPartnerScenarioText[partner_scenario],
-- MsnMemberRole[list], member);
--
-- state->body = xmlnode_from_str(body, -1);
-- state->post_action = MSN_DELETE_MEMBER_FROM_LIST_SOAP_ACTION;
-- state->post_url = MSN_SHARE_POST_URL;
-- state->cb = msn_del_contact_from_list_read_cb;
-- msn_contact_request(state);
--
-- g_free(member);
-- g_free(body);
--}
--
--static void
--msn_add_contact_to_list_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
-- gpointer data)
--{
-- MsnCallbackState *state = data;
-- xmlnode *fault;
--
-- /* We don't know how to respond to this faultcode, so log it */
-- fault = xmlnode_get_child(resp->xml, "Body/Fault");
-- if (fault != NULL) {
-- char *fault_str = xmlnode_to_str(fault, NULL);
-- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-- msn_contact_operation_str(state->action), fault_str);
-- g_free(fault_str);
-- return;
-- }
--
-- g_return_if_fail(state->session != NULL);
--
-- purple_debug_info("msn", "Contact %s added successfully to %s list on server!\n", state->who, MsnMemberRole[state->list_id]);
--
-- if (state->list_id == MSN_LIST_RL) {
-- MsnUser *user = msn_userlist_find_user(state->session->userlist, state->who);
--
-- if (user != NULL) {
-- msn_user_set_op(user, MSN_LIST_RL_OP);
-- }
--
-- if (state->action & MSN_DENIED_BUDDY) {
-- msn_add_contact_to_list(state->session, NULL, state->who, MSN_LIST_BL);
-- } else if (state->list_id == MSN_LIST_AL) {
-- purple_privacy_permit_add(state->session->account, state->who, TRUE);
-- } else if (state->list_id == MSN_LIST_BL) {
-- purple_privacy_deny_add(state->session->account, state->who, TRUE);
-- }
-- }
--}
--
--void
--msn_add_contact_to_list(MsnSession *session, MsnCallbackState *state,
-- const gchar *passport, const MsnListId list)
--{
-- gchar *body = NULL, *member = NULL;
-- MsnSoapPartnerScenario partner_scenario;
-- MsnUser *user;
--
-- g_return_if_fail(session != NULL);
-- g_return_if_fail(passport != NULL);
-- g_return_if_fail(list < 5);
--
-- purple_debug_info("msn", "Adding contact %s to %s list\n", passport, MsnMemberRole[list]);
--
-- if (state == NULL) {
-- state = msn_callback_state_new(session);
-- }
-- msn_callback_state_set_list_id(state, list);
-- msn_callback_state_set_who(state, passport);
--
-- user = msn_userlist_find_user(session->userlist, passport);
--
-- partner_scenario = (list == MSN_LIST_RL) ? MSN_PS_CONTACT_API : MSN_PS_BLOCK_UNBLOCK;
-- if (user && user->networkid != MSN_NETWORK_PASSPORT)
-- member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
-- "EmailMember", "Email",
-- "Email", state->who, "Email");
-- else
-- member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
-- "PassportMember", "Passport",
-- "PassportName", state->who, "PassportName");
--
-- body = g_strdup_printf(MSN_CONTACT_ADD_TO_LIST_TEMPLATE,
-- MsnSoapPartnerScenarioText[partner_scenario],
-- MsnMemberRole[list], member);
--
-- state->body = xmlnode_from_str(body, -1);
-- state->post_action = MSN_ADD_MEMBER_TO_LIST_SOAP_ACTION;
-- state->post_url = MSN_SHARE_POST_URL;
-- state->cb = msn_add_contact_to_list_read_cb;
-- msn_contact_request(state);
--
-- g_free(member);
-- g_free(body);
--}
--
--#if 0
--static void
--msn_gleams_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
--{
-- purple_debug_info("msn", "Gleams read done\n");
--}
--
--/*get the gleams info*/
--void
--msn_get_gleams(MsnSession *session)
--{
-- MsnSoapReq *soap_request;
--
-- purple_debug_info("msn", "msn get gleams info...\n");
--
-- state = msn_callback_state_new(session);
-- state->body = xmlnode_from_str(MSN_GLEAMS_TEMPLATE, -1);
-- state->post_action = MSN_GET_GLEAMS_SOAP_ACTION;
-- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-- state->cb = msn_gleams_read_cb;
-- msn_contact_request(state);
--}
--#endif
--
--
--/***************************************************************
-- * Group Operations
-- ***************************************************************/
--
--static void
--msn_group_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
--{
-- MsnCallbackState *state = data;
-- MsnSession *session;
-- MsnUserList *userlist;
-- xmlnode *fault;
--
-- /* We don't know how to respond to this faultcode, so log it */
-- fault = xmlnode_get_child(resp->xml, "Body/Fault");
-- if (fault != NULL) {
-- char *fault_str = xmlnode_to_str(fault, NULL);
-- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
-- msn_contact_operation_str(state->action), fault_str);
-- g_free(fault_str);
-- return;
-- }
--
-- purple_debug_info("msn", "Group request successful.\n");
--
-- g_return_if_fail(state->session != NULL);
-- g_return_if_fail(state->session->userlist != NULL);
--
-- session = state->session;
-- userlist = session->userlist;
--
-- if (state->action & MSN_RENAME_GROUP) {
-- msn_userlist_rename_group_id(session->userlist,
-- state->guid,
-- state->new_group_name);
-- }
--
-- if (state->action & MSN_ADD_GROUP) {
-- /* the response is taken from
-- http://telepathy.freedesktop.org/wiki/Pymsn/MSNP/ContactListActions
-- should copy it to msnpiki some day */
-- xmlnode *guid_node = xmlnode_get_child(resp->xml,
-- "Body/ABGroupAddResponse/ABGroupAddResult/guid");
--
-- if (guid_node) {
-- char *guid = xmlnode_get_data(guid_node);
--
-- /* create and add the new group to the userlist */
-- purple_debug_info("msn", "Adding group %s with guid = %s to the userlist\n", state->new_group_name, guid);
-- msn_group_new(session->userlist, guid, state->new_group_name);
--
-- if (state->action & MSN_ADD_BUDDY) {
-- msn_userlist_add_buddy(session->userlist,
-- state->who,
-- state->new_group_name);
-- } else if (state->action & MSN_MOVE_BUDDY) {
-- /* This will be freed when the add contact callback fires */
-- MsnCallbackState *new_state = msn_callback_state_dup(state);
-- msn_add_contact_to_group(session, new_state, state->who, guid);
-- g_free(guid);
-- return;
-- }
-- g_free(guid);
-- } else {
-- purple_debug_info("msn", "Adding group %s failed\n",
-- state->new_group_name);
-- }
-- }
--
-- if (state->action & MSN_DEL_GROUP) {
-- GList *l;
--
-- msn_userlist_remove_group_id(session->userlist, state->guid);
-- for (l = userlist->users; l != NULL; l = l->next) {
-- msn_user_remove_group_id( (MsnUser *)l->data, state->guid);
-- }
-- }
--}
--
--/* add group */
--void
--msn_add_group(MsnSession *session, MsnCallbackState *state, const char* group_name)
--{
-- char *body = NULL;
-- char *escaped_group_name = NULL;
--
-- g_return_if_fail(session != NULL);
-- g_return_if_fail(group_name != NULL);
--
-- purple_debug_info("msn", "Adding group %s to contact list.\n", group_name);
--
-- if (state == NULL) {
-- state = msn_callback_state_new(session);
-- }
--
-- msn_callback_state_set_action(state, MSN_ADD_GROUP);
-- msn_callback_state_set_new_group_name(state, group_name);
--
-- /* escape group name's html special chars so it can safely be sent
-- * in a XML SOAP request
-- */
-- escaped_group_name = g_markup_escape_text(group_name, -1);
-- body = g_strdup_printf(MSN_GROUP_ADD_TEMPLATE, escaped_group_name);
--
-- state->body = xmlnode_from_str(body, -1);
-- state->post_action = MSN_GROUP_ADD_SOAP_ACTION;
-- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-- state->cb = msn_group_read_cb;
-- msn_contact_request(state);
--
-- g_free(escaped_group_name);
-- g_free(body);
--}
--
--/* delete group */
--void
--msn_del_group(MsnSession *session, const gchar *group_name)
--{
-- MsnCallbackState *state;
-- char *body = NULL;
-- const gchar *guid;
--
-- g_return_if_fail(session != NULL);
--
-- g_return_if_fail(group_name != NULL);
-- purple_debug_info("msn", "Deleting group %s from contact list\n", group_name);
--
-- guid = msn_userlist_find_group_id(session->userlist, group_name);
--
-- /* if group uid we need to del is NULL,
-- * we need to delete nothing
-- */
-- if (guid == NULL) {
-- purple_debug_info("msn", "Group %s guid not found, returning.\n", group_name);
-- return;
-- }
--
-- if ( !strcmp(guid, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(guid, MSN_NON_IM_GROUP_ID) ) {
-- /* XXX add back PurpleGroup since it isn't really removed in the server? */
-- return;
-- }
--
-- state = msn_callback_state_new(session);
-- msn_callback_state_set_action(state, MSN_DEL_GROUP);
-- msn_callback_state_set_guid(state, guid);
--
-- body = g_strdup_printf(MSN_GROUP_DEL_TEMPLATE, guid);
--
-- state->body = xmlnode_from_str(body, -1);
-- state->post_action = MSN_GROUP_DEL_SOAP_ACTION;
-- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-- state->cb = msn_group_read_cb;
-- msn_contact_request(state);
--
-- g_free(body);
--}
--
--/* rename group */
--void
--msn_contact_rename_group(MsnSession *session, const char *old_group_name, const char *new_group_name)
--{
-- gchar *body = NULL;
-- const gchar * guid;
-- MsnCallbackState *state;
-- char *escaped_group_name;
--
-- g_return_if_fail(session != NULL);
-- g_return_if_fail(session->userlist != NULL);
-- g_return_if_fail(old_group_name != NULL);
-- g_return_if_fail(new_group_name != NULL);
--
-- purple_debug_info("msn", "Renaming group %s to %s.\n", old_group_name, new_group_name);
--
-- guid = msn_userlist_find_group_id(session->userlist, old_group_name);
-- if (guid == NULL)
-- return;
--
-- state = msn_callback_state_new(session);
-- msn_callback_state_set_guid(state, guid);
-- msn_callback_state_set_new_group_name(state, new_group_name);
--
-- if ( !strcmp(guid, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(guid, MSN_NON_IM_GROUP_ID) ) {
-- MsnCallbackState *new_state = msn_callback_state_dup(state);
-- msn_add_group(session, new_state, new_group_name);
-- /* XXX move every buddy there (we probably need to fix concurrent SOAP reqs first) */
-- }
--
-- msn_callback_state_set_action(state, MSN_RENAME_GROUP);
--
-- escaped_group_name = g_markup_escape_text(new_group_name, -1);
-- body = g_strdup_printf(MSN_GROUP_RENAME_TEMPLATE, guid, escaped_group_name);
--
-- state->body = xmlnode_from_str(body, -1);
-- state->post_action = MSN_GROUP_RENAME_SOAP_ACTION;
-- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
-- state->cb = msn_group_read_cb;
-- msn_contact_request(state);
--
-- g_free(escaped_group_name);
-- g_free(body);
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/contact.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/contact.h
---- pidgin-2.10.7/libpurple/protocols/msn/contact.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/contact.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,746 +0,0 @@
--/**
-- * @file contact.h Header file for contact.c
-- * Author
-- * MaYuan<mayuan2006@gmail.com>
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-- */
--#ifndef MSN_CONTACT_H
--#define MSN_CONTACT_H
--
--typedef struct _MsnCallbackState MsnCallbackState;
--
--typedef enum
--{
-- MSN_ADD_BUDDY = 0x01,
-- MSN_MOVE_BUDDY = 0x02,
-- MSN_ACCEPTED_BUDDY = 0x04,
-- MSN_DENIED_BUDDY = 0x08,
-- MSN_ADD_GROUP = 0x10,
-- MSN_DEL_GROUP = 0x20,
-- MSN_RENAME_GROUP = 0x40,
-- MSN_UPDATE_INFO = 0x80,
-- MSN_ANNOTATE_USER = 0x100
--} MsnCallbackAction;
--
--typedef enum
--{
-- MSN_UPDATE_DISPLAY, /* Real display name */
-- MSN_UPDATE_ALIAS, /* Aliased display name */
-- MSN_UPDATE_COMMENT
--} MsnContactUpdateType;
--
--typedef enum
--{
-- MSN_PS_INITIAL,
-- MSN_PS_SAVE_CONTACT,
-- MSN_PS_PENDING_LIST,
-- MSN_PS_CONTACT_API,
-- MSN_PS_BLOCK_UNBLOCK,
-- MSN_PS_TIMER
--} MsnSoapPartnerScenario;
--
--#include "session.h"
--#include "soap.h"
--
--#define MSN_APPLICATION_ID "CFE80F9D-180F-4399-82AB-413F33A1FA11"
--
--#define MSN_CONTACT_SERVER "local-bay.contacts.msn.com"
--
--/* Get Contact List */
--
--#define MSN_GET_CONTACT_POST_URL "/abservice/SharingService.asmx"
--#define MSN_GET_CONTACT_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/FindMembership"
--
--#define MSN_GET_CONTACT_UPDATE_XML \
-- "<View>Full</View>"\
-- "<deltasOnly>true</deltasOnly>"\
-- "<lastChange>%s</lastChange>"
--
--#define MSN_GET_CONTACT_TEMPLATE "<?xml version='1.0' encoding='utf-8'?>"\
--"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
-- "<soap:Header xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
-- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ApplicationId xmlns=\"http://www.msn.com/webservices/AddressBook\">" MSN_APPLICATION_ID "</ApplicationId>"\
-- "<IsMigration xmlns=\"http://www.msn.com/webservices/AddressBook\">false</IsMigration>"\
-- "<PartnerScenario xmlns=\"http://www.msn.com/webservices/AddressBook\">%s</PartnerScenario>"\
-- "</ABApplicationHeader>"\
-- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ManagedGroupRequest xmlns=\"http://www.msn.com/webservices/AddressBook\">false</ManagedGroupRequest>"\
-- "<TicketToken>EMPTY</TicketToken>"\
-- "</ABAuthHeader>"\
-- "</soap:Header>"\
-- "<soap:Body xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
-- "<FindMembership xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<serviceFilter xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<Types xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Messenger</ServiceType>"\
-- "<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Invitation</ServiceType>"\
-- "<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">SocialNetwork</ServiceType>"\
-- "<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Space</ServiceType>"\
-- "<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Profile</ServiceType>"\
-- "</Types>"\
-- "</serviceFilter>"\
-- "%s"\
-- "</FindMembership>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--/************************************************
-- * Address Book SOAP
-- * *********************************************/
--
--#define MSN_ADDRESS_BOOK_POST_URL "/abservice/abservice.asmx"
--
--/* Create AddressBook template */
--#define MSN_ADD_ADDRESSBOOK_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABAdd"
--
--#define MSN_ADD_ADDRESSBOOK_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope"\
-- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-- "<soap:Header>"\
-- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-- "<IsMigration>false</IsMigration>"\
-- "<PartnerScenario>Initial</PartnerScenario>"\
-- "</ABApplicationHeader>"\
-- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
-- "<TicketToken>EMPTY</TicketToken>"\
-- "</ABAuthHeader>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<ABAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<abInfo>"\
-- "<name/>"\
-- "<ownerPuid>0</ownerPuid>"\
-- "<ownerEmail>%s</ownerEmail>"\
-- "<fDefault>true</fDefault>"\
-- "</abInfo>"\
-- "</ABAdd>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--/* Get AddressBook */
--#define MSN_GET_ADDRESS_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABFindContactsPaged"
--#define MSN_GET_ADDRESS_FULL_TIME "0001-01-01T00:00:00.0000000-08:00"
--#define MSN_GET_ADDRESS_UPDATE_XML \
-- "<filterOptions>"\
-- "<deltasOnly>true</deltasOnly>"\
-- "<lastChange>%s</lastChange>"\
-- "</filterOptions>"
--
--#define MSN_GET_GLEAM_UPDATE_XML \
-- "%s"\
-- "<dynamicItemView>Gleam</dynamicItemView>"\
-- "<dynamicItemLastChange>%s</dynamicItemLastChange>"
--
--#define MSN_GET_ADDRESS_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope"\
-- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-- "<soap:Header>"\
-- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-- "<IsMigration>false</IsMigration>"\
-- "<PartnerScenario>%s</PartnerScenario>"\
-- "</ABApplicationHeader>"\
-- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
-- "<TicketToken>EMPTY</TicketToken>"\
-- "</ABAuthHeader>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<ABFindContactsPaged xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<abView>Full</abView>"\
-- "<extendedContent>AB AllGroups CircleResult</extendedContent>"\
-- "%s"\
-- "</ABFindContactsPaged>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--
--/*Gleams SOAP request template*/
--#define MSN_GET_GLEAMS_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABFindAll"
--#define MSN_GLEAMS_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope"\
-- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-- "<soap:Header>"\
-- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-- "<IsMigration>false</IsMigration>"\
-- "<PartnerScenario>Initial</PartnerScenario>"\
-- "</ABApplicationHeader>"\
-- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
-- "<TicketToken>EMPTY</TicketToken>"\
-- "</ABAuthHeader>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<ABFindAll xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
-- "<abView>Full</abView>"\
-- "<dynamicItemView>Gleam</dynamicItemView>"\
-- "<dynamicItemLastChange>0001-01-01T00:00:00.0000000-08:00</dynamicItemLastChange>"\
-- "</ABFindAll>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--
--/*******************************************************
-- * Contact Management SOAP actions
-- *******************************************************/
--
--/* Add a new contact */
--#define MSN_CONTACT_ADD_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactAdd"
--#define MSN_CONTACT_LIVE_PENDING_XML \
-- "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<contactInfo>"\
-- "<contactType>LivePending</contactType>"\
-- "<passportName>%s</passportName>"\
-- "<isMessengerUser>true</isMessengerUser>"\
-- "</contactInfo>"\
-- "</Contact>"
--
--#define MSN_CONTACT_XML \
-- "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<contactInfo>"\
-- "<passportName>%s</passportName>"\
-- "<isSmtp>false</isSmtp>"\
-- "<isMessengerUser>true</isMessengerUser>"\
-- "</contactInfo>"\
-- "</Contact>"
--
--#define MSN_CONTACT_DISPLAYNAME_XML \
-- "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<contactInfo>"\
-- "<displayName>%s</displayName>"\
-- "<passportName>%s</passportName>"\
-- "<isMessengerUser>true</isMessengerUser>"\
-- "</contactInfo>"\
-- "</Contact>"
--
--#define MSN_CONTACT_ID_XML \
-- "<Contact>"\
-- "<contactId>%s</contactId>"\
-- "</Contact>"
--
--#define MSN_CONTACT_EMAIL_XML \
-- "<Contact>"\
-- "<contactInfo>"\
-- "<emails>"\
-- "<ContactEmail>"\
-- "<contactEmailType>%s</contactEmailType>"\
-- "<email>%s</email>"\
-- "<isMessengerEnabled>true</isMessengerEnabled>"\
-- "<Capability>%d</Capability>"\
-- "<MessengerEnabledExternally>false</MessengerEnabledExternally>"\
-- "<propertiesChanged/>"\
-- "</ContactEmail>"\
-- "</emails>"\
-- "</contactInfo>"\
-- "</Contact>"
--
--#define MSN_CONTACT_INVITE_MESSAGE_XML \
-- "<MessengerMemberInfo>"\
-- "<PendingAnnotations>"\
-- "<Annotation>"\
-- "<Name>MSN.IM.InviteMessage</Name>"\
-- "<Value>%s</Value>"\
-- "</Annotation>"\
-- "</PendingAnnotations>"\
-- "<DisplayName>%s</DisplayName>"\
-- "</MessengerMemberInfo>"
--
--#define MSN_ADD_CONTACT_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-- "<soap:Header>"\
-- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-- "<IsMigration>false</IsMigration>"\
-- "<PartnerScenario>ContactSave</PartnerScenario>"\
-- "</ABApplicationHeader>"\
-- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
-- "<TicketToken>EMPTY</TicketToken>"\
-- "</ABAuthHeader>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<ABContactAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
-- "<contacts>%s</contacts>"\
-- "<options>"\
-- "<EnableAllowListManagement>true</EnableAllowListManagement>"\
-- "</options>"\
-- "</ABContactAdd>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--/* Add a contact to a group */
--#define MSN_ADD_CONTACT_GROUP_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupContactAdd"
--#define MSN_ADD_CONTACT_GROUP_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-- "<soap:Header>"\
-- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-- "<IsMigration>false</IsMigration>"\
-- "<PartnerScenario>ContactSave</PartnerScenario>"\
-- "</ABApplicationHeader>"\
-- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
-- "<TicketToken>EMPTY</TicketToken>"\
-- "</ABAuthHeader>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<ABGroupContactAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
-- "<groupFilter>"\
-- "<groupIds>"\
-- "<guid>%s</guid>"\
-- "</groupIds>"\
-- "</groupFilter>"\
-- "<contacts>%s</contacts>"\
-- "<groupContactAddOptions>"\
-- "<fGenerateMissingQuickName>true</fGenerateMissingQuickName>"\
-- "<EnableAllowListManagement>true</EnableAllowListManagement>"\
-- "</groupContactAddOptions>"\
-- "%s"\
-- "</ABGroupContactAdd>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--/* Delete a contact from the Contact List */
--#define MSN_CONTACT_DEL_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactDelete"
--#define MSN_DEL_CONTACT_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope"\
-- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-- "<soap:Header>"\
-- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-- "<IsMigration>false</IsMigration>"\
-- "<PartnerScenario>Timer</PartnerScenario>"\
-- "</ABApplicationHeader>"\
-- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
-- "<TicketToken>EMPTY</TicketToken>"\
-- "</ABAuthHeader>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<ABContactDelete xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
-- "<contacts>%s</contacts>"\
-- "</ABContactDelete>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--/* Remove a contact from a group */
--#define MSN_CONTACT_DEL_GROUP_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupContactDelete"
--#define MSN_CONTACT_DEL_GROUP_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope"\
-- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-- "<soap:Header>"\
-- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-- "<IsMigration>false</IsMigration>"\
-- "<PartnerScenario>Timer</PartnerScenario>"\
-- "</ABApplicationHeader>"\
-- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
-- "<TicketToken>EMPTY</TicketToken>"\
-- "</ABAuthHeader>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<ABGroupContactDelete xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
-- "<contacts>%s</contacts>"\
-- "<groupFilter>"\
-- "<groupIds>"\
-- "<guid>%s</guid>"\
-- "</groupIds>"\
-- "</groupFilter>"\
-- "</ABGroupContactDelete>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--
--/* Update Contact Information */
--#define MSN_CONTACT_UPDATE_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactUpdate"
--#define MSN_CONTACT_UPDATE_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope"\
-- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-- "<soap:Header>"\
-- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-- "<IsMigration>false</IsMigration>"\
-- "<PartnerScenario></PartnerScenario>"\
-- "</ABApplicationHeader>"\
-- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
-- "<TicketToken>EMPTY</TicketToken>"\
-- "</ABAuthHeader>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<ABContactUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
-- "<contacts>"\
-- "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- ""\
-- "</Contact>"\
-- "</contacts>"\
-- "</ABContactUpdate>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--/* Update Contact Annotations */
--#define MSN_CONTACT_ANNOTATE_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactUpdate"
--#define MSN_CONTACT_ANNOTATE_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope"\
-- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-- "<soap:Header>"\
-- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-- "<IsMigration>false</IsMigration>"\
-- "<PartnerScenario></PartnerScenario>"\
-- "</ABApplicationHeader>"\
-- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
-- "<TicketToken>EMPTY</TicketToken>"\
-- "</ABAuthHeader>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<ABContactUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
-- "<contacts>"\
-- "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<propertiesChanged>Annotation</propertiesChanged>"\
-- "</Contact>"\
-- "</contacts>"\
-- "</ABContactUpdate>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--/*******************************************************
-- * Add/Delete contact from lists SOAP actions
-- *******************************************************/
--
--/* block means delete from allow list and add contact to block list */
--#define MSN_SHARE_POST_URL "/abservice/SharingService.asmx"
--
--#define MSN_ADD_MEMBER_TO_LIST_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/AddMember"
--#define MSN_DELETE_MEMBER_FROM_LIST_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/DeleteMember"
--
--#define MSN_MEMBER_PASSPORT_XML \
-- "<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"%s\">"\
-- "<Type>%s</Type>"\
-- "<State>Accepted</State>"\
-- "<%s>%s</%s>"\
-- "</Member>"
--
--#define MSN_MEMBER_MEMBERSHIPID_XML \
-- "<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"%s\">"\
-- "<Type>%s</Type>"\
-- "<MembershipId>%u</MembershipId>"\
-- "<State>Accepted</State>"\
-- "</Member>"
--
--/* first delete contact from allow list */
--
--#define MSN_CONTACT_DELETE_FROM_LIST_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope"\
-- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-- "<soap:Header>"\
-- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-- "<IsMigration>false</IsMigration>"\
-- "<PartnerScenario>%s</PartnerScenario>"\
-- "</ABApplicationHeader>"\
-- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
-- "<TicketToken>EMPTY</TicketToken>"\
-- "</ABAuthHeader>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<DeleteMember xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<serviceHandle>"\
-- "<Id>0</Id>"\
-- "<Type>Messenger</Type>"\
-- "<ForeignId></ForeignId>"\
-- "</serviceHandle>"\
-- "<memberships>"\
-- "<Membership>"\
-- "<MemberRole>%s</MemberRole>"\
-- "<Members>"\
-- "%s"\
-- "</Members>"\
-- "</Membership>"\
-- "</memberships>"\
-- "</DeleteMember>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--#define MSN_CONTACT_ADD_TO_LIST_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope"\
-- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-- "<soap:Header>"\
-- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-- "<IsMigration>false</IsMigration>"\
-- "<PartnerScenario>%s</PartnerScenario>"\
-- "</ABApplicationHeader>"\
-- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
-- "<TicketToken>EMPTY</TicketToken>"\
-- "</ABAuthHeader>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<AddMember xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<serviceHandle>"\
-- "<Id>0</Id>"\
-- "<Type>Messenger</Type>"\
-- "<ForeignId></ForeignId>"\
-- "</serviceHandle>"\
-- "<memberships>"\
-- "<Membership>"\
-- "<MemberRole>%s</MemberRole>"\
-- "<Members>"\
-- "%s"\
-- "</Members>"\
-- "</Membership>"\
-- "</memberships>"\
-- "</AddMember>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--
--
--/*******************************************************
-- * Group management SOAP actions
-- *******************************************************/
--
--/* add a group */
--#define MSN_GROUP_ADD_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupAdd"
--#define MSN_GROUP_ADD_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope"\
-- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-- "<soap:Header>"\
-- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-- "<IsMigration>false</IsMigration>"\
-- "<PartnerScenario>GroupSave</PartnerScenario>"\
-- "</ABApplicationHeader>"\
-- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
-- "<TicketToken>EMPTY</TicketToken>"\
-- "</ABAuthHeader>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<ABGroupAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
-- "<groupAddOptions>"\
-- "<fRenameOnMsgrConflict>false</fRenameOnMsgrConflict>"\
-- "</groupAddOptions>"\
-- "<groupInfo>"\
-- "<GroupInfo>"\
-- "<name>%s</name>"\
-- "<groupType>C8529CE2-6EAD-434d-881F-341E17DB3FF8</groupType>"\
-- "<fMessenger>false</fMessenger>"\
-- "<annotations>"\
-- "<Annotation>"\
-- "<Name>MSN.IM.Display</Name>"\
-- "<Value>1</Value>"\
-- "</Annotation>"\
-- "</annotations>"\
-- "</GroupInfo>"\
-- "</groupInfo>"\
-- "</ABGroupAdd>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--/* delete a group */
--#define MSN_GROUP_DEL_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupDelete"
--#define MSN_GROUP_DEL_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope"\
-- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-- "<soap:Header>"\
-- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-- "<IsMigration>false</IsMigration>"\
-- "<PartnerScenario>Timer</PartnerScenario>"\
-- "</ABApplicationHeader>"\
-- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
-- "<TicketToken>EMPTY</TicketToken>"\
-- "</ABAuthHeader>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<ABGroupDelete xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
-- "<groupFilter>"\
-- "<groupIds>"\
-- "<guid>%s</guid>"\
-- "</groupIds>"\
-- "</groupFilter>"\
-- "</ABGroupDelete>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--/* change a group's name */
--#define MSN_GROUP_RENAME_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupUpdate"
--#define MSN_GROUP_RENAME_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope"\
-- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
-- "<soap:Header>"\
-- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
-- "<IsMigration>false</IsMigration>"\
-- "<PartnerScenario>Timer</PartnerScenario>"\
-- "</ABApplicationHeader>"\
-- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
-- "<TicketToken>EMPTY</TicketToken>"\
-- "</ABAuthHeader>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<ABGroupUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
-- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
-- "<groups>"\
-- "<Group>"\
-- "<groupId>%s</groupId>"\
-- "<groupInfo>"\
-- "<name>%s</name>"\
-- "</groupInfo>"\
-- "<propertiesChanged>GroupName </propertiesChanged>"\
-- "</Group>"\
-- "</groups>"\
-- "</ABGroupUpdate>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--struct _MsnCallbackState
--{
-- gchar * who;
-- gchar * uid;
-- gchar * old_group_name;
-- gchar * new_group_name;
-- gchar * guid;
-- MsnListId list_id;
-- MsnCallbackAction action;
-- MsnSession *session;
-- xmlnode *body;
-- xmlnode *token;
-- const gchar *post_action;
-- const gchar *post_url;
-- MsnSoapCallback cb;
-- /* For msn_get_contact_list only */
-- MsnSoapPartnerScenario partner_scenario;
--};
--
--/************************************************
-- * function prototype
-- ************************************************/
--MsnCallbackState * msn_callback_state_new(MsnSession *session);
--MsnCallbackState * msn_callback_state_dup(MsnCallbackState *state);
--void msn_callback_state_free(MsnCallbackState *state);
--void msn_callback_state_set_who(MsnCallbackState *state, const gchar *who);
--void msn_callback_state_set_uid(MsnCallbackState *state, const gchar *uid);
--void msn_callback_state_set_old_group_name(MsnCallbackState *state,
-- const gchar *old_group_name);
--void msn_callback_state_set_new_group_name(MsnCallbackState *state,
-- const gchar *new_group_name);
--void msn_callback_state_set_guid(MsnCallbackState *state, const gchar *guid);
--void msn_callback_state_set_list_id(MsnCallbackState *state, MsnListId list_id);
--void msn_callback_state_set_action(MsnCallbackState *state,
-- MsnCallbackAction action);
--
--void msn_get_contact_list(MsnSession *session,
-- const MsnSoapPartnerScenario partner_scenario,
-- const char *update);
--void msn_get_address_book(MsnSession *session,
-- const MsnSoapPartnerScenario partner_scenario,
-- const char * update, const char * gupdate);
--
--/* contact SOAP operations */
--void msn_update_contact(MsnSession *session, const char *passport, MsnContactUpdateType type, const char* value);
--
--void msn_annotate_contact(MsnSession *session, const char *passport, ...) G_GNUC_NULL_TERMINATED;
--
--void msn_add_contact(MsnSession *session, MsnCallbackState *state,
-- const char *passport);
--void msn_delete_contact(MsnSession *session, MsnUser *user);
--
--void msn_add_contact_to_group(MsnSession *session, MsnCallbackState *state,
-- const char *passport, const char *groupId);
--void msn_del_contact_from_group(MsnSession *session, const char *passport,
-- const char *group_name);
--/* group operations */
--void msn_add_group(MsnSession *session, MsnCallbackState *state,
-- const char* group_name);
--void msn_del_group(MsnSession *session, const gchar *group_name);
--void msn_contact_rename_group(MsnSession *session, const char *old_group_name,
-- const char *new_group_name);
--
--/* lists operations */
--void msn_add_contact_to_list(MsnSession *session, MsnCallbackState *state,
-- const gchar *passport, const MsnListId list);
--void msn_del_contact_from_list(MsnSession *session, MsnCallbackState *state,
-- const gchar *passport, const MsnListId list);
--
--#endif /* MSN_CONTACT_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/directconn.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/directconn.c
---- pidgin-2.10.7/libpurple/protocols/msn/directconn.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/directconn.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,958 +0,0 @@
--/**
-- * @file directconn.c MSN direct connection functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "cipher.h"
--#include "debug.h"
--
--#include "msn.h"
--#include "msnutils.h"
--#include "directconn.h"
--
--#include "slp.h"
--#include "slpmsg.h"
--#include "p2p.h"
--
--#define DC_MAX_BODY_SIZE 8*1024
--#define DC_MAX_PACKET_SIZE (P2P_PACKET_HEADER_SIZE + DC_MAX_BODY_SIZE)
--
--static void
--msn_dc_calculate_nonce_hash(MsnDirectConnNonceType type,
-- const guchar nonce[16], gchar nonce_hash[37])
--{
-- guchar digest[20];
--
-- if (type == DC_NONCE_SHA1) {
-- PurpleCipher *cipher = purple_ciphers_find_cipher("sha1");
-- PurpleCipherContext *context = purple_cipher_context_new(cipher, NULL);
-- purple_cipher_context_append(context, nonce, sizeof(nonce));
-- purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
-- purple_cipher_context_destroy(context);
-- } else if (type == DC_NONCE_PLAIN) {
-- memcpy(digest, nonce, 16);
-- } else {
-- nonce_hash[0] = '\0';
-- g_return_if_reached();
-- }
--
-- g_sprintf(nonce_hash,
-- "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
--
-- digest[3],
-- digest[2],
-- digest[1],
-- digest[0],
--
-- digest[5],
-- digest[4],
--
-- digest[7],
-- digest[6],
--
-- digest[8],
-- digest[9],
--
-- digest[10],
-- digest[11],
-- digest[12],
-- digest[13],
-- digest[14],
-- digest[15]
-- );
--}
--
--static void
--msn_dc_generate_nonce(MsnDirectConn *dc)
--{
-- guint32 *nonce;
-- int i;
--
-- nonce = (guint32 *)&dc->nonce;
-- for (i = 0; i < 4; i++)
-- nonce[i] = rand();
--
-- msn_dc_calculate_nonce_hash(dc->nonce_type, dc->nonce, dc->nonce_hash);
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "DC %p generated nonce %s\n", dc, dc->nonce_hash);
--}
--
--static MsnDirectConnPacket *
--msn_dc_new_packet(guint32 length)
--{
-- MsnDirectConnPacket *p;
--
-- p = g_new0(MsnDirectConnPacket, 1);
-- p->length = length;
-- p->data = g_malloc(length);
--
-- return p;
--}
--
--static void
--msn_dc_destroy_packet(MsnDirectConnPacket *p)
--{
-- g_free(p->data);
--
-- if (p->part)
-- msn_slpmsgpart_unref(p->part);
--
-- g_free(p);
--}
--
--MsnDirectConn *
--msn_dc_new(MsnSlpCall *slpcall)
--{
-- MsnDirectConn *dc;
--
-- g_return_val_if_fail(slpcall != NULL, NULL);
--
-- dc = g_new0(MsnDirectConn, 1);
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "msn_dc_new %p\n", dc);
--
-- dc->slplink = slpcall->slplink;
-- dc->slpcall = slpcall;
--
-- if (dc->slplink->dc != NULL)
-- purple_debug_warning("msn", "msn_dc_new: slplink already has an allocated DC!\n");
--
-- dc->slplink->dc = dc;
--
-- dc->msg_body = NULL;
-- dc->prev_ack = NULL;
-- dc->listen_data = NULL;
-- dc->connect_data = NULL;
-- dc->listenfd = -1;
-- dc->listenfd_handle = 0;
-- dc->connect_timeout_handle = 0;
-- dc->fd = -1;
-- dc->recv_handle = 0;
-- dc->send_handle = 0;
-- dc->state = DC_STATE_CLOSED;
-- dc->in_buffer = NULL;
-- dc->out_queue = g_queue_new();
-- dc->msg_pos = -1;
-- dc->send_connection_info_msg_cb = NULL;
-- dc->ext_ip = NULL;
-- dc->timeout_handle = 0;
-- dc->progress = FALSE;
-- /*dc->num_calls = 1;*/
--
-- /* TODO: Probably should set this based on buddy caps */
-- dc->nonce_type = DC_NONCE_PLAIN;
-- msn_dc_generate_nonce(dc);
--
-- return dc;
--}
--
--void
--msn_dc_destroy(MsnDirectConn *dc)
--{
-- MsnSlpLink *slplink;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "msn_dc_destroy %p\n", dc);
--
-- g_return_if_fail(dc != NULL);
--
-- if (dc->slpcall != NULL)
-- dc->slpcall->wait_for_socket = FALSE;
--
-- slplink = dc->slplink;
-- if (slplink) {
-- slplink->dc = NULL;
-- if (slplink->swboard == NULL)
-- msn_slplink_unref(slplink);
-- }
--
-- g_free(dc->msg_body);
--
-- if (dc->prev_ack) {
-- msn_slpmsg_destroy(dc->prev_ack);
-- }
--
-- if (dc->listen_data != NULL) {
-- purple_network_listen_cancel(dc->listen_data);
-- }
--
-- if (dc->connect_data != NULL) {
-- purple_proxy_connect_cancel(dc->connect_data);
-- }
--
-- if (dc->listenfd != -1) {
-- purple_network_remove_port_mapping(dc->listenfd);
-- close(dc->listenfd);
-- }
--
-- if (dc->listenfd_handle != 0) {
-- purple_input_remove(dc->listenfd_handle);
-- }
--
-- if (dc->connect_timeout_handle != 0) {
-- purple_timeout_remove(dc->connect_timeout_handle);
-- }
--
-- if (dc->fd != -1) {
-- close(dc->fd);
-- }
--
-- if (dc->send_handle != 0) {
-- purple_input_remove(dc->send_handle);
-- }
--
-- if (dc->recv_handle != 0) {
-- purple_input_remove(dc->recv_handle);
-- }
--
-- g_free(dc->in_buffer);
--
-- if (dc->out_queue != NULL) {
-- while (!g_queue_is_empty(dc->out_queue))
-- msn_dc_destroy_packet( g_queue_pop_head(dc->out_queue) );
--
-- g_queue_free(dc->out_queue);
-- }
--
-- g_free(dc->ext_ip);
--
-- if (dc->timeout_handle != 0) {
-- purple_timeout_remove(dc->timeout_handle);
-- }
--
-- g_free(dc);
--}
--
--/*
--void
--msn_dc_ref(MsnDirectConn *dc)
--{
-- g_return_if_fail(dc != NULL);
--
-- dc->num_calls++;
--}
--
--void
--msn_dc_unref(MsnDirectConn *dc)
--{
-- g_return_if_fail(dc != NULL);
--
--
-- if (dc->num_calls > 0) {
-- dc->num_calls--;
-- }
--}
--*/
--
--void
--msn_dc_send_invite(MsnDirectConn *dc)
--{
-- MsnSlpCall *slpcall;
-- MsnSlpMessage *msg;
-- gchar *header;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "msn_dc_send_invite %p\n", dc);
--
-- g_return_if_fail(dc != NULL);
--
-- slpcall = dc->slpcall;
-- g_return_if_fail(slpcall != NULL);
--
-- header = g_strdup_printf(
-- "INVITE MSNMSGR:%s MSNSLP/1.0",
-- slpcall->slplink->remote_user
-- );
--
-- msg = msn_slpmsg_sip_new(
-- slpcall,
-- 0,
-- header,
-- slpcall->branch,
-- "application/x-msnmsgr-transrespbody",
-- dc->msg_body
-- );
-- msg->info = "DC INVITE";
-- msg->text_body = TRUE;
-- g_free(header);
-- g_free(dc->msg_body);
-- dc->msg_body = NULL;
--
-- msn_slplink_queue_slpmsg(slpcall->slplink, msg);
--}
--
--void
--msn_dc_send_ok(MsnDirectConn *dc)
--{
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "msn_dc_send_ok %p\n", dc);
--
-- g_return_if_fail(dc != NULL);
--
-- msn_slp_send_ok(dc->slpcall, dc->slpcall->branch,
-- "application/x-msnmsgr-transrespbody", dc->msg_body);
-- g_free(dc->msg_body);
-- dc->msg_body = NULL;
--
-- msn_slplink_send_slpmsg(dc->slpcall->slplink, dc->prev_ack);
-- msn_slpmsg_destroy(dc->prev_ack);
-- dc->prev_ack = NULL;
-- msn_slplink_send_queued_slpmsgs(dc->slpcall->slplink);
--}
--
--void
--msn_dc_fallback_to_sb(MsnDirectConn *dc)
--{
-- MsnSlpLink *slplink;
-- MsnSlpCall *slpcall;
-- GQueue *queue = NULL;
--
-- purple_debug_info("msn", "msn_dc_fallback_to_sb %p\n", dc);
--
-- g_return_if_fail(dc != NULL);
--
-- slpcall = dc->slpcall;
-- slplink = msn_slplink_ref(dc->slplink);
-- if (slpcall && !g_queue_is_empty(dc->out_queue)) {
-- queue = dc->out_queue;
-- dc->out_queue = NULL;
-- }
--
-- msn_dc_destroy(dc);
--
-- if (slpcall) {
-- msn_slpcall_session_init(slpcall);
-- if (queue) {
-- while (!g_queue_is_empty(queue)) {
-- MsnDirectConnPacket *p = g_queue_pop_head(queue);
-- msn_slplink_send_msgpart(slplink, (MsnSlpMessage*)p->part->ack_data);
-- msn_dc_destroy_packet(p);
-- }
-- g_queue_free(queue);
-- }
-- }
-- msn_slplink_unref(slplink);
--}
--
--static void
--msn_dc_send_cb(gpointer data, gint fd, PurpleInputCondition cond)
--{
-- MsnDirectConn *dc = data;
-- MsnDirectConnPacket *p;
-- int bytes_to_send;
-- int bytes_sent;
--
-- g_return_if_fail(dc != NULL);
-- g_return_if_fail(fd != -1);
--
-- if (g_queue_is_empty(dc->out_queue)) {
-- if (dc->send_handle != 0) {
-- purple_input_remove(dc->send_handle);
-- dc->send_handle = 0;
-- }
-- return;
-- }
--
-- p = g_queue_peek_head(dc->out_queue);
--
-- if (dc->msg_pos < 0) {
-- /* First we send the length of the packet */
-- guint32 len = GUINT32_TO_LE(p->length);
-- bytes_sent = send(fd, &len, 4, 0);
-- if (bytes_sent < 0) {
-- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-- return;
--
-- purple_debug_warning("msn", "msn_dc_send_cb: send error\n");
-- msn_dc_destroy(dc);
-- return;
-- }
-- dc->msg_pos = 0;
-- }
--
-- bytes_to_send = p->length - dc->msg_pos;
-- bytes_sent = send(fd, p->data + dc->msg_pos, bytes_to_send, 0);
-- if (bytes_sent < 0) {
-- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-- return;
--
-- purple_debug_warning("msn", "msn_dc_send_cb: send error\n");
-- msn_dc_destroy(dc);
-- return;
-- }
--
-- dc->progress = TRUE;
--
-- dc->msg_pos += bytes_sent;
-- if (dc->msg_pos == p->length) {
-- if (p->sent_cb != NULL)
-- p->sent_cb(p);
--
-- g_queue_pop_head(dc->out_queue);
-- msn_dc_destroy_packet(p);
--
-- dc->msg_pos = -1;
-- }
--}
--
--static void
--msn_dc_enqueue_packet(MsnDirectConn *dc, MsnDirectConnPacket *p)
--{
-- gboolean was_empty;
--
-- was_empty = g_queue_is_empty(dc->out_queue);
-- g_queue_push_tail(dc->out_queue, p);
--
-- if (was_empty && dc->send_handle == 0) {
-- dc->send_handle = purple_input_add(dc->fd, PURPLE_INPUT_WRITE, msn_dc_send_cb, dc);
-- msn_dc_send_cb(dc, dc->fd, PURPLE_INPUT_WRITE);
-- }
--}
--
--static void
--msn_dc_send_foo(MsnDirectConn *dc)
--{
-- MsnDirectConnPacket *p;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "msn_dc_send_foo %p\n", dc);
--
-- p = msn_dc_new_packet(4);
--
-- memcpy(p->data, "foo\0", 4);
--
-- msn_dc_enqueue_packet(dc, p);
--}
--
--#if 0 /* We don't actually need this */
--typedef struct {
-- guint32 null;
-- guint32 id;
-- guint32 null[5];
-- guint32 flags;
-- guint8 nonce[16];
--} MsnDirectConnNoncePacket;
--#endif
--#define DC_NONCE_PACKET_SIZE (8 * 4 + 16)
--#define DC_NONCE_PACKET_NONCE (8 * 4)
--
--static void
--msn_dc_send_handshake(MsnDirectConn *dc)
--{
-- MsnDirectConnPacket *p;
-- gchar *h;
--
-- p = msn_dc_new_packet(DC_NONCE_PACKET_SIZE);
-- h = (gchar *)p->data;
--
-- msn_push32le(h, 0); /* NUL */
--
-- msn_push32le(h, dc->slpcall->slplink->slp_seq_id++);
--
-- /* More NUL stuff */
-- msn_push64le(h, 0);
-- msn_push64le(h, 0);
-- msn_push32le(h, 0);
--
-- /* Flags */
-- msn_push32le(h, P2P_DC_HANDSHAKE);
--
-- /* The real Nonce, yay! */
-- memcpy(h, dc->nonce, 16);
--
-- msn_dc_enqueue_packet(dc, p);
--}
--
--static gboolean
--msn_dc_verify_handshake(MsnDirectConn *dc, guint32 packet_length)
--{
-- guchar nonce[16];
-- gchar nonce_hash[37];
--
-- if (packet_length != DC_NONCE_PACKET_SIZE)
-- return FALSE;
--
-- memcpy(nonce, dc->in_buffer + 4 + DC_NONCE_PACKET_NONCE, 16);
--
-- if (dc->nonce_type == DC_NONCE_PLAIN) {
-- if (memcmp(dc->nonce, nonce, 16) == 0) {
-- purple_debug_info("msn",
-- "Nonce from buddy request and nonce from DC attempt match, "
-- "allowing direct connection\n");
-- return TRUE;
-- } else {
-- purple_debug_warning("msn",
-- "Nonce from buddy request and nonce from DC attempt "
-- "don't match, ignoring direct connection\n");
-- return FALSE;
-- }
--
-- } else if (dc->nonce_type == DC_NONCE_SHA1) {
-- msn_dc_calculate_nonce_hash(dc->nonce_type, nonce, nonce_hash);
--
-- if (g_str_equal(dc->remote_nonce, nonce_hash)) {
-- purple_debug_info("msn",
-- "Received nonce %s from buddy request "
-- "and calculated nonce %s from DC attempt. "
-- "Nonces match, allowing direct connection\n",
-- dc->remote_nonce, nonce_hash);
-- return TRUE;
-- } else {
-- purple_debug_warning("msn",
-- "Received nonce %s from buddy request "
-- "and calculated nonce %s from DC attempt. "
-- "Nonces don't match, ignoring direct connection\n",
-- dc->remote_nonce, nonce_hash);
-- return FALSE;
-- }
-- } else
-- return FALSE;
--}
--
--static void
--msn_dc_send_packet_cb(MsnDirectConnPacket *p)
--{
-- if (p->part != NULL && p->part->ack_cb != NULL)
-- p->part->ack_cb(p->part, p->part->ack_data);
--}
--
--void
--msn_dc_enqueue_part(MsnDirectConn *dc, MsnSlpMessagePart *part)
--{
-- MsnDirectConnPacket *p;
-- size_t length;
--
-- p = msn_dc_new_packet(0);
-- p->data = (guchar *)msn_slpmsgpart_serialize(part, &length);
-- p->length = length - P2P_PACKET_FOOTER_SIZE; /* DC doesn't need footer? */
--
-- p->sent_cb = msn_dc_send_packet_cb;
-- p->part = msn_slpmsgpart_ref(part);
--
-- msn_dc_enqueue_packet(dc, p);
--}
--
--static int
--msn_dc_process_packet(MsnDirectConn *dc, guint32 packet_length)
--{
-- MsnSlpMessagePart *part;
--
-- g_return_val_if_fail(dc != NULL, DC_PROCESS_ERROR);
--
-- switch (dc->state) {
-- case DC_STATE_CLOSED:
-- break;
--
-- case DC_STATE_FOO:
-- /* FOO message is always 4 bytes long */
-- if (packet_length != 4 || memcmp(dc->in_buffer, "\4\0\0\0foo", 8) != 0)
-- return DC_PROCESS_FALLBACK;
--
-- dc->state = DC_STATE_HANDSHAKE;
-- break;
--
-- case DC_STATE_HANDSHAKE:
-- if (!msn_dc_verify_handshake(dc, packet_length))
-- return DC_PROCESS_FALLBACK;
--
-- msn_dc_send_handshake(dc);
-- dc->state = DC_STATE_ESTABLISHED;
--
-- msn_slpcall_session_init(dc->slpcall);
-- dc->slpcall = NULL;
-- break;
--
-- case DC_STATE_HANDSHAKE_REPLY:
-- if (!msn_dc_verify_handshake(dc, packet_length))
-- return DC_PROCESS_FALLBACK;
--
-- dc->state = DC_STATE_ESTABLISHED;
--
-- msn_slpcall_session_init(dc->slpcall);
-- dc->slpcall = NULL;
-- break;
--
-- case DC_STATE_ESTABLISHED:
-- if (packet_length) {
-- MsnP2PVersion p2p;
-- p2p = msn_slplink_get_p2p_version(dc->slplink);
-- part = msn_slpmsgpart_new_from_data(p2p, dc->in_buffer + 4, packet_length);
-- if (part) {
-- msn_slplink_process_msg(dc->slplink, part);
-- msn_slpmsgpart_unref(part);
-- }
-- }
--
-- /*
-- if (dc->num_calls == 0) {
-- msn_dc_destroy(dc);
--
-- return DC_PROCESS_CLOSE;
-- }
-- */
-- break;
-- }
--
-- return DC_PROCESS_OK;
--}
--
--static void
--msn_dc_recv_cb(gpointer data, gint fd, PurpleInputCondition cond)
--{
-- MsnDirectConn *dc;
-- int free_buf_space;
-- int bytes_received;
-- guint32 packet_length;
--
-- g_return_if_fail(data != NULL);
-- g_return_if_fail(fd != -1);
--
-- dc = data;
-- free_buf_space = dc->in_size - dc->in_pos;
--
-- bytes_received = recv(fd, dc->in_buffer + dc->in_pos, free_buf_space, 0);
-- if (bytes_received < 0) {
-- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-- return;
--
-- purple_debug_warning("msn", "msn_dc_recv_cb: recv error\n");
--
-- if(dc->state != DC_STATE_ESTABLISHED)
-- msn_dc_fallback_to_sb(dc);
-- else
-- msn_dc_destroy(dc);
-- return;
--
-- } else if (bytes_received == 0) {
-- /* EOF. Remote side closed connection. */
-- purple_debug_info("msn", "msn_dc_recv_cb: recv EOF\n");
--
-- if(dc->state != DC_STATE_ESTABLISHED)
-- msn_dc_fallback_to_sb(dc);
-- else
-- msn_dc_destroy(dc);
-- return;
-- }
--
-- dc->progress = TRUE;
--
-- dc->in_pos += bytes_received;
--
-- /* Wait for packet length */
-- while (dc->in_pos >= 4) {
-- packet_length = GUINT32_FROM_LE(*((guint32*)dc->in_buffer));
--
-- if (packet_length > DC_MAX_PACKET_SIZE) {
-- /* Oversized packet */
-- purple_debug_warning("msn", "msn_dc_recv_cb: oversized packet received\n");
-- return;
-- }
--
-- /* Wait for the whole packet to arrive */
-- if (dc->in_pos < 4 + packet_length)
-- return;
--
-- switch (msn_dc_process_packet(dc, packet_length)) {
-- case DC_PROCESS_CLOSE:
-- return;
--
-- case DC_PROCESS_FALLBACK:
-- purple_debug_warning("msn", "msn_dc_recv_cb: packet processing error, fall back to SB\n");
-- msn_dc_fallback_to_sb(dc);
-- return;
--
-- }
--
-- if (dc->in_pos > packet_length + 4) {
-- g_memmove(dc->in_buffer, dc->in_buffer + 4 + packet_length, dc->in_pos - packet_length - 4);
-- }
--
-- dc->in_pos -= packet_length + 4;
-- }
--}
--
--static gboolean
--msn_dc_timeout(gpointer data)
--{
-- MsnDirectConn *dc = data;
--
-- g_return_val_if_fail(dc != NULL, FALSE);
--
-- if (dc->progress) {
-- dc->progress = FALSE;
-- return TRUE;
-- } else {
-- dc->timeout_handle = 0;
-- msn_dc_destroy(dc);
-- return FALSE;
-- }
--}
--
--static void
--msn_dc_init(MsnDirectConn *dc)
--{
-- g_return_if_fail(dc != NULL);
--
-- dc->in_size = DC_MAX_PACKET_SIZE + 4;
-- dc->in_pos = 0;
-- dc->in_buffer = g_malloc(dc->in_size);
--
-- dc->recv_handle = purple_input_add(dc->fd, PURPLE_INPUT_READ, msn_dc_recv_cb, dc);
-- dc->send_handle = purple_input_add(dc->fd, PURPLE_INPUT_WRITE, msn_dc_send_cb, dc);
--
-- dc->timeout_handle = purple_timeout_add_seconds(DC_TIMEOUT, msn_dc_timeout, dc);
--}
--
--void
--msn_dc_connected_to_peer_cb(gpointer data, gint fd, const gchar *error_msg)
--{
-- MsnDirectConn *dc = data;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "msn_dc_connected_to_peer_cb %p\n", dc);
--
-- g_return_if_fail(dc != NULL);
--
-- dc->connect_data = NULL;
-- purple_timeout_remove(dc->connect_timeout_handle);
-- dc->connect_timeout_handle = 0;
--
-- dc->fd = fd;
-- if (dc->fd != -1) {
-- msn_dc_init(dc);
-- msn_dc_send_foo(dc);
-- msn_dc_send_handshake(dc);
-- dc->state = DC_STATE_HANDSHAKE_REPLY;
-- }
--}
--
--/*
-- * This callback will be called when we're the server
-- * and nobody has connected us in DC_INCOMING_TIMEOUT seconds
-- */
--static gboolean
--msn_dc_incoming_connection_timeout_cb(gpointer data) {
-- MsnDirectConn *dc = data;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "msn_dc_incoming_connection_timeout_cb %p\n", dc);
--
-- g_return_val_if_fail(dc != NULL, FALSE);
--
-- if (dc->listen_data != NULL) {
-- purple_network_listen_cancel(dc->listen_data);
-- dc->listen_data = NULL;
-- }
--
-- if (dc->listenfd_handle != 0) {
-- purple_input_remove(dc->listenfd_handle);
-- dc->listenfd_handle = 0;
-- }
--
-- if (dc->listenfd != -1) {
-- purple_network_remove_port_mapping(dc->listenfd);
-- close(dc->listenfd);
-- dc->listenfd = -1;
-- }
--
-- dc->connect_timeout_handle = 0;
-- msn_dc_fallback_to_sb(dc);
--
-- return FALSE;
--}
--
--/*
-- * This callback will be called when we're unable to connect to
-- * the remote host in DC_OUTGOING_TIMEOUT seconds.
-- */
--gboolean
--msn_dc_outgoing_connection_timeout_cb(gpointer data)
--{
-- MsnDirectConn *dc = data;
--
-- purple_debug_info("msn", "msn_dc_outgoing_connection_timeout_cb %p\n", dc);
--
-- g_return_val_if_fail(dc != NULL, FALSE);
--
-- dc->connect_timeout_handle = 0;
--
-- if (dc->connect_data != NULL) {
-- purple_proxy_connect_cancel(dc->connect_data);
-- dc->connect_data = NULL;
-- }
--
-- if (dc->ext_ip && dc->ext_port) {
-- /* Try external IP/port if available. */
-- dc->connect_data = purple_proxy_connect(
-- NULL,
-- dc->slpcall->slplink->session->account,
-- dc->ext_ip,
-- dc->ext_port,
-- msn_dc_connected_to_peer_cb,
-- dc
-- );
--
-- g_free(dc->ext_ip);
-- dc->ext_ip = NULL;
--
-- if (dc->connect_data) {
-- dc->connect_timeout_handle = purple_timeout_add_seconds(
-- DC_OUTGOING_TIMEOUT,
-- msn_dc_outgoing_connection_timeout_cb,
-- dc
-- );
-- } else {
-- /*
-- * Connection failed
-- * Fall back to SB transfer
-- */
-- msn_dc_outgoing_connection_timeout_cb(dc);
-- }
--
-- } else {
-- /*
-- * Both internal and external connection attempts failed.
-- * Fall back to SB transfer.
-- */
-- msn_dc_fallback_to_sb(dc);
-- }
--
-- return FALSE;
--}
--
--/*
-- * This callback will be called when we're the server
-- * and somebody has connected to us in DC_INCOMING_TIMEOUT seconds.
-- */
--static void
--msn_dc_incoming_connection_cb(gpointer data, gint listenfd, PurpleInputCondition cond)
--{
-- MsnDirectConn *dc = data;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "msn_dc_incoming_connection_cb %p\n", dc);
--
-- g_return_if_fail(dc != NULL);
--
-- if (dc->connect_timeout_handle != 0) {
-- purple_timeout_remove(dc->connect_timeout_handle);
-- dc->connect_timeout_handle = 0;
-- }
--
-- if (dc->listenfd_handle != 0) {
-- purple_input_remove(dc->listenfd_handle);
-- dc->listenfd_handle = 0;
-- }
--
-- dc->fd = accept(listenfd, NULL, 0);
--
-- purple_network_remove_port_mapping(dc->listenfd);
-- close(dc->listenfd);
-- dc->listenfd = -1;
--
-- if (dc->fd != -1) {
-- msn_dc_init(dc);
-- dc->state = DC_STATE_FOO;
-- }
--}
--
--void
--msn_dc_listen_socket_created_cb(int listenfd, gpointer data)
--{
-- MsnDirectConn *dc = data;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "msn_dc_listen_socket_created_cb %p\n", dc);
--
-- g_return_if_fail(dc != NULL);
--
-- dc->listen_data = NULL;
--
-- if (listenfd != -1) {
-- const char *ext_ip;
-- const char *int_ip;
-- int port;
--
-- ext_ip = purple_network_get_my_ip(listenfd);
-- int_ip = purple_network_get_local_system_ip(listenfd);
-- port = purple_network_get_port_from_fd(listenfd);
--
-- dc->listenfd = listenfd;
-- dc->listenfd_handle = purple_input_add(
-- listenfd,
-- PURPLE_INPUT_READ,
-- msn_dc_incoming_connection_cb,
-- dc
-- );
-- dc->connect_timeout_handle = purple_timeout_add_seconds(
-- DC_INCOMING_TIMEOUT,
-- msn_dc_incoming_connection_timeout_cb,
-- dc
-- );
--
-- if (strcmp(int_ip, ext_ip) != 0) {
-- dc->msg_body = g_strdup_printf(
-- "Bridge: TCPv1\r\n"
-- "Listening: true\r\n"
-- "%sNonce: {%s}\r\n"
-- "IPv4External-Addrs: %s\r\n"
-- "IPv4External-Port: %d\r\n"
-- "IPv4Internal-Addrs: %s\r\n"
-- "IPv4Internal-Port: %d\r\n"
-- "\r\n",
--
-- dc->nonce_type != DC_NONCE_PLAIN ? "Hashed-" : "",
-- dc->nonce_hash,
-- ext_ip,
-- port,
-- int_ip,
-- port
-- );
--
-- } else {
-- dc->msg_body = g_strdup_printf(
-- "Bridge: TCPv1\r\n"
-- "Listening: true\r\n"
-- "%sNonce: {%s}\r\n"
-- "IPv4External-Addrs: %s\r\n"
-- "IPv4External-Port: %d\r\n"
-- "\r\n",
--
-- dc->nonce_type != DC_NONCE_PLAIN ? "Hashed-" : "",
-- dc->nonce_hash,
-- ext_ip,
-- port
-- );
-- }
--
-- if (dc->slpcall->wait_for_socket) {
-- if (dc->send_connection_info_msg_cb != NULL)
-- dc->send_connection_info_msg_cb(dc);
--
-- dc->slpcall->wait_for_socket = FALSE;
-- }
-- }
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/directconn.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/directconn.h
---- pidgin-2.10.7/libpurple/protocols/msn/directconn.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/directconn.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,200 +0,0 @@
--/**
-- * @file directconn.h MSN direct connection functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_DIRECTCONN_H
--#define MSN_DIRECTCONN_H
--
--typedef struct _MsnDirectConn MsnDirectConn;
--
--#include "network.h"
--#include "proxy.h"
--#include "circbuffer.h"
--
--#include "slp.h"
--#include "slplink.h"
--#include "slpmsg.h"
--#include "slpmsg_part.h"
--#include "p2p.h"
--
--#define MSN_DCCONN_MAX_SIZE 1352
--
--typedef enum
--{
-- DC_STATE_CLOSED, /*< No socket opened yet */
-- DC_STATE_FOO, /*< Waiting for FOO message */
-- DC_STATE_HANDSHAKE, /*< Waiting for handshake message */
-- DC_STATE_HANDSHAKE_REPLY, /*< Waiting for handshake reply message */
-- DC_STATE_ESTABLISHED /*< Handshake complete */
--} MsnDirectConnState;
--
--typedef enum
--{
-- DC_PROCESS_OK = 0,
-- DC_PROCESS_ERROR,
-- DC_PROCESS_FALLBACK,
-- DC_PROCESS_CLOSE
--
--} MsnDirectConnProcessResult;
--
--typedef enum
--{
-- DC_NONCE_UNKNOWN, /**< Invalid scheme */
-- DC_NONCE_PLAIN, /**< No hashing */
-- DC_NONCE_SHA1 /**< First 16 bytes of SHA1 of nonce */
--
--} MsnDirectConnNonceType;
--
--typedef struct _MsnDirectConnPacket MsnDirectConnPacket;
--
--struct _MsnDirectConnPacket {
-- guint32 length;
-- guchar *data;
--
-- void (*sent_cb)(struct _MsnDirectConnPacket*);
-- MsnSlpMessagePart *part;
--};
--
--struct _MsnDirectConn
--{
-- MsnDirectConnState state; /**< Direct connection status */
-- MsnSlpLink *slplink; /**< The slplink using this direct connection */
-- MsnSlpCall *slpcall; /**< The slpcall which initiated the direct connection */
-- char *msg_body; /**< The body of message sent by send_connection_info_msg_cb */
-- MsnSlpMessage *prev_ack; /**< The saved SLP ACK message */
--
-- MsnDirectConnNonceType nonce_type; /**< The type of nonce hashing */
-- guchar nonce[16]; /**< The nonce used for handshake */
-- gchar nonce_hash[37]; /**< The hash of nonce */
-- gchar remote_nonce[37]; /**< The remote side's nonce */
--
-- PurpleNetworkListenData *listen_data; /**< The pending socket creation request */
-- PurpleProxyConnectData *connect_data; /**< The pending connection attempt */
-- int listenfd; /**< The socket we're listening for incoming connections */
-- guint listenfd_handle; /**< The timeout handle for incoming connection */
-- guint connect_timeout_handle; /**< The timeout handle for outgoing connection */
--
-- int fd; /**< The direct connection socket */
-- guint recv_handle; /**< The incoming data callback handle */
-- guint send_handle; /**< The outgoing data callback handle */
--
-- gchar *in_buffer; /**< The receive buffer */
-- int in_size; /**< The receive buffer size */
-- int in_pos; /**< The first free position in receive buffer */
-- GQueue *out_queue; /**< The outgoing packet queue */
-- int msg_pos; /**< The position of next byte to be sent in the actual packet */
--
-- /** The callback used for sending information to the peer about the opened socket */
-- void (*send_connection_info_msg_cb)(MsnDirectConn *);
--
-- gchar *ext_ip; /**< Our external IP address */
-- int ext_port; /**< Our external port */
--
-- guint timeout_handle;
-- gboolean progress;
--
-- /*int num_calls;*/ /**< The number of slpcalls using this direct connection */
--};
--
--/* Outgoing attempt */
--#define DC_OUTGOING_TIMEOUT (5)
--/* Time for internal + external connection attempts */
--#define DC_INCOMING_TIMEOUT (DC_OUTGOING_TIMEOUT * 3)
--/* Timeout for lack of activity */
--#define DC_TIMEOUT (60)
--
--/*
-- * Queues an MSN message to be sent via direct connection.
-- */
--void
--msn_dc_enqueue_part(MsnDirectConn *dc, MsnSlpMessagePart *part);
--
--/*
-- * Creates, initializes, and returns a new MsnDirectConn structure.
-- */
--MsnDirectConn *
--msn_dc_new(MsnSlpCall *slpcall);
--
--/*
-- * Destroys an MsnDirectConn structure. Frees every buffer allocated earlier
-- * restores saved callbacks, etc.
-- */
--void
--msn_dc_destroy(MsnDirectConn *dc);
--
--/*
-- * Fallback to switchboard connection. Used when neither side is able to
-- * create a listening socket.
-- */
--void
--msn_dc_fallback_to_sb(MsnDirectConn *dc);
--
--/*
-- * Increases the slpcall counter in DC. The direct connection remains open
-- * until all slpcalls using it are destroyed.
-- */
--void
--msn_dc_ref(MsnDirectConn *dc);
--
--/*
-- * Decrease the slpcall counter in DC. The direct connection remains open
-- * until all slpcalls using it are destroyed.
-- */
--void
--msn_dc_unref(MsnDirectConn *dc);
--
--/*
-- * Sends a direct connect INVITE message on the associated slplink
-- * with the corresponding connection type and information.
-- */
--void
--msn_dc_send_invite(MsnDirectConn *dc);
--
--/*
-- * Sends a direct connect OK message as a response to an INVITE received earliaer
-- * on the corresponding slplink.
-- */
--void
--msn_dc_send_ok(MsnDirectConn *dc);
--
--/*
-- * This callback will be called when we're successfully connected to
-- * the remote host.
-- */
--void
--msn_dc_connected_to_peer_cb(gpointer data, gint fd, const gchar *error_msg);
--
--/*
-- * This callback will be called when we're unable to connect to
-- * the remote host in DC_CONNECT_TIMEOUT seconds.
-- */
--gboolean
--msn_dc_outgoing_connection_timeout_cb(gpointer data);
--
--/*
-- * This callback will be called when the listening socket is successfully
-- * created and its parameters (IP/port) are available.
-- */
--void
--msn_dc_listen_socket_created_cb(int listenfd, gpointer data);
--
--#endif /* MSN_DIRECTCONN_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/error.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/error.c
---- pidgin-2.10.7/libpurple/protocols/msn/error.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/error.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,384 +0,0 @@
--/**
-- * @file error.c Error functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--/* Masca: can we get rid of the sync issue dialog? */
--#include "request.h"
--
--#include "error.h"
--
--typedef struct
--{
-- MsnSession *session;
-- char *who;
-- char *group;
-- gboolean add;
--
--} MsnAddRemData;
--
--const char *
--msn_error_get_text(unsigned int type, gboolean *debug)
--{
-- static char msg[256];
-- const char *result;
-- *debug = FALSE;
--
-- switch (type) {
-- case 0:
-- result = _("Unable to parse message");
-- *debug = TRUE;
-- break;
-- case 200:
-- result = _("Syntax Error (probably a client bug)");
-- *debug = TRUE;
-- break;
-- case 201:
-- result = _("Invalid email address");
-- break;
-- case 205:
-- result = _("User does not exist");
-- break;
-- case 206:
-- result = _("Fully qualified domain name missing");
-- break;
-- case 207:
-- result = _("Already logged in");
-- break;
-- case 208:
-- result = _("Invalid username");
-- break;
-- case 209:
-- result = _("Invalid friendly name");
-- break;
-- case 210:
-- result = _("List full");
-- break;
-- case 215:
-- result = _("Already there");
-- *debug = TRUE;
-- break;
-- case 216:
-- result = _("Not on list");
-- break;
-- case 217:
-- result = _("User is offline");
-- break;
-- case 218:
-- result = _("Already in the mode");
-- *debug = TRUE;
-- break;
-- case 219:
-- result = _("Already in opposite list");
-- *debug = TRUE;
-- break;
-- case 223:
-- result = _("Too many groups");
-- break;
-- case 224:
-- result = _("Invalid group");
-- break;
-- case 225:
-- result = _("User not in group");
-- break;
-- case 229:
-- result = _("Group name too long");
-- break;
-- case 230:
-- result = _("Cannot remove group zero");
-- *debug = TRUE;
-- break;
-- case 231:
-- result = _("Tried to add a user to a group that doesn't exist");
-- break;
-- case 280:
-- result = _("Switchboard failed");
-- *debug = TRUE;
-- break;
-- case 281:
-- result = _("Notify transfer failed");
-- *debug = TRUE;
-- break;
--
-- case 300:
-- result = _("Required fields missing");
-- *debug = TRUE;
-- break;
-- case 301:
-- result = _("Too many hits to a FND");
-- *debug = TRUE;
-- break;
-- case 302:
-- result = _("Not logged in");
-- break;
--
-- case 500:
-- result = _("Service temporarily unavailable");
-- break;
-- case 501:
-- result = _("Database server error");
-- *debug = TRUE;
-- break;
-- case 502:
-- result = _("Command disabled");
-- *debug = TRUE;
-- break;
-- case 510:
-- result = _("File operation error");
-- *debug = TRUE;
-- break;
-- case 520:
-- result = _("Memory allocation error");
-- *debug = TRUE;
-- break;
-- case 540:
-- result = _("Wrong CHL value sent to server");
-- *debug = TRUE;
-- break;
--
-- case 600:
-- result = _("Server busy");
-- break;
-- case 601:
-- result = _("Server unavailable");
-- break;
-- case 602:
-- result = _("Peer notification server down");
-- *debug = TRUE;
-- break;
-- case 603:
-- result = _("Database connect error");
-- *debug = TRUE;
-- break;
-- case 604:
-- result = _("Server is going down (abandon ship)");
-- break;
-- case 605:
-- result = _("Server unavailable");
-- break;
--
-- case 707:
-- result = _("Error creating connection");
-- *debug = TRUE;
-- break;
-- case 710:
-- result = _("CVR parameters are either unknown or not allowed");
-- *debug = TRUE;
-- break;
-- case 711:
-- result = _("Unable to write");
-- break;
-- case 712:
-- result = _("Session overload");
-- *debug = TRUE;
-- break;
-- case 713:
-- result = _("User is too active");
-- break;
-- case 714:
-- result = _("Too many sessions");
-- break;
-- case 715:
-- result = _("Passport not verified");
-- break;
-- case 717:
-- result = _("Bad friend file");
-- *debug = TRUE;
-- break;
-- case 731:
-- result = _("Not expected");
-- *debug = TRUE;
-- break;
--
-- case 800:
-- result = _("Friendly name is changing too rapidly");
-- break;
--
-- case 910:
-- case 912:
-- case 918:
-- case 919:
-- case 921:
-- case 922:
-- result = _("Server too busy");
-- break;
-- case 911:
-- case 917:
-- result = _("Authentication failed");
-- break;
-- case 913:
-- result = _("Not allowed when offline");
-- break;
-- case 914:
-- case 915:
-- case 916:
-- result = _("Server unavailable");
-- break;
-- case 920:
-- result = _("Not accepting new users");
-- break;
-- case 923:
-- result = _("Kids Passport without parental consent");
-- break;
-- case 924:
-- result = _("Passport account not yet verified");
-- break;
-- case 927:
-- result = _("Passport account suspended");
-- break;
-- case 928:
-- result = _("Bad ticket");
-- *debug = TRUE;
-- break;
--
-- default:
-- g_snprintf(msg, sizeof(msg),
-- _("Unknown Error Code %d"), type);
-- *debug = TRUE;
-- result = msg;
-- break;
-- }
--
-- return result;
--}
--
--void
--msn_error_handle(MsnSession *session, unsigned int type)
--{
-- char *buf;
-- gboolean debug;
--
-- buf = g_strdup_printf(_("MSN Error: %s\n"),
-- msn_error_get_text(type, &debug));
-- if (debug)
-- purple_debug_warning("msn", "error %d: %s\n", type, buf);
-- else
-- purple_notify_error(session->account->gc, NULL, buf, NULL);
-- g_free(buf);
--}
--
--/* Remove the buddy referenced by the MsnAddRemData before the serverside list
-- * is changed. If the buddy will be added, he'll be added back; if he will be
-- * removed, he won't be. */
--/* Actually with our MSNP14 code that isn't true yet, he won't be added back :(
-- * */
--static void
--msn_complete_sync_issue(MsnAddRemData *data)
--{
-- PurpleBuddy *buddy;
-- PurpleGroup *group = NULL;
--
-- if (data->group != NULL)
-- group = purple_find_group(data->group);
--
-- if (group != NULL)
-- buddy = purple_find_buddy_in_group(data->session->account, data->who, group);
-- else
-- buddy = purple_find_buddy(data->session->account, data->who);
--
-- if (buddy != NULL)
-- purple_blist_remove_buddy(buddy);
--}
--
--
--static void
--msn_add_cb(MsnAddRemData *data)
--{
--#if 0
-- /* this *should* be necessary !! */
-- msn_complete_sync_issue(data);
--#endif
-- MsnUserList *userlist = data->session->userlist;
--
-- msn_userlist_add_buddy(userlist, data->who, data->group);
--
-- g_free(data->group);
-- g_free(data->who);
-- g_free(data);
--}
--
--static void
--msn_rem_cb(MsnAddRemData *data)
--{
-- MsnUserList *userlist = data->session->userlist;
-- msn_complete_sync_issue(data);
--
--
-- if (data->group == NULL) {
-- msn_userlist_rem_buddy_from_list(userlist, data->who, MSN_LIST_FL);
-- } else {
-- g_free(data->group);
-- }
--
-- g_free(data->who);
-- g_free(data);
--}
--
--void
--msn_error_sync_issue(MsnSession *session, const char *passport,
-- const char *group_name)
--{
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- MsnAddRemData *data;
-- char *msg, *reason;
--
-- account = session->account;
-- gc = purple_account_get_connection(account);
--
-- data = g_new0(MsnAddRemData, 1);
-- data->who = g_strdup(passport);
-- data->group = g_strdup(group_name);
-- data->session = session;
--
-- msg = g_strdup_printf(_("Buddy list synchronization issue in %s (%s)"),
-- purple_account_get_username(account),
-- purple_account_get_protocol_name(account));
--
-- if (group_name != NULL)
-- {
-- reason = g_strdup_printf(_("%s on the local list is "
-- "inside the group \"%s\" but not on "
-- "the server list. "
-- "Do you want this buddy to be added?"),
-- passport, group_name);
-- }
-- else
-- {
-- reason = g_strdup_printf(_("%s is on the local list but "
-- "not on the server list. "
-- "Do you want this buddy to be added?"),
-- passport);
-- }
--
-- purple_request_action(gc, NULL, msg, reason, PURPLE_DEFAULT_ACTION_NONE,
-- account, data->who, NULL,
-- data, 2,
-- _("Yes"), G_CALLBACK(msn_add_cb),
-- _("No"), G_CALLBACK(msn_rem_cb));
--
-- g_free(reason);
-- g_free(msg);
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/error.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/error.h
---- pidgin-2.10.7/libpurple/protocols/msn/error.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/error.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,57 +0,0 @@
--/**
-- * @file error.h Error functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_ERROR_H
--#define MSN_ERROR_H
--
--#include "session.h"
--
--/**
-- * Returns the string representation of an error type.
-- *
-- * @param type The error type.
-- * @param debug Whether this should be treated as a debug log message or a user-visible error
-- *
-- * @return The string representation of the error type.
-- */
--const char *msn_error_get_text(unsigned int type, gboolean *debug);
--
--/**
-- * Handles an error.
-- *
-- * @param session The current session.
-- * @param type The error type.
-- */
--void msn_error_handle(MsnSession *session, unsigned int type);
--
--/**
-- * Show the sync issue in a dialog using request api
-- *
-- * @param sesion MsnSession associated to this error.
-- * @param passport The passport associated with the error.
-- * @param group_name The group in the buddy is suppoused to be
-- */
--void msn_error_sync_issue(MsnSession *session, const char *passport,
-- const char *group_name);
--
--#endif /* MSN_ERROR_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/group.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/group.c
---- pidgin-2.10.7/libpurple/protocols/msn/group.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/group.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,89 +0,0 @@
--/**
-- * @file group.c Group functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#include "msn.h"
--#include "group.h"
--
--MsnGroup *
--msn_group_new(MsnUserList *userlist, const char *id, const char *name)
--{
-- MsnGroup *group;
--
-- g_return_val_if_fail(id != NULL, NULL);
-- g_return_val_if_fail(name != NULL, NULL);
--
-- group = g_new0(MsnGroup, 1);
--
-- msn_userlist_add_group(userlist, group);
--
-- group->id = g_strdup(id);
-- group->name = g_strdup(name);
--
-- return group;
--}
--
--void
--msn_group_destroy(MsnGroup *group)
--{
-- g_return_if_fail(group != NULL);
--
-- g_free(group->id);
-- g_free(group->name);
-- g_free(group);
--}
--
--void
--msn_group_set_id(MsnGroup *group, const char *id)
--{
-- g_return_if_fail(group != NULL);
-- g_return_if_fail(id != NULL);
--
-- g_free(group->id);
-- group->id = g_strdup(id);
--}
--
--void
--msn_group_set_name(MsnGroup *group, const char *name)
--{
-- g_return_if_fail(group != NULL);
-- g_return_if_fail(name != NULL);
--
-- g_free(group->name);
-- group->name = g_strdup(name);
--}
--
--char*
--msn_group_get_id(const MsnGroup *group)
--{
-- g_return_val_if_fail(group != NULL, NULL);
--
-- return group->id;
--}
--
--const char *
--msn_group_get_name(const MsnGroup *group)
--{
-- g_return_val_if_fail(group != NULL, NULL);
--
-- return group->name;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/group.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/group.h
---- pidgin-2.10.7/libpurple/protocols/msn/group.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/group.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,109 +0,0 @@
--/**
-- * @file group.h Group functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_GROUP_H
--#define MSN_GROUP_H
--
--typedef struct _MsnGroup MsnGroup;
--
--#include "internal.h"
--
--#include "session.h"
--#include "user.h"
--#include "userlist.h"
--
--#define MSN_INDIVIDUALS_GROUP_ID "1983"
--#define MSN_INDIVIDUALS_GROUP_NAME _("Other Contacts")
--
--#define MSN_NON_IM_GROUP_ID "email"
--#define MSN_NON_IM_GROUP_NAME _("Non-IM Contacts")
--
--/**
-- * A group.
-- */
--struct _MsnGroup
--{
-- MsnSession *session; /**< The MSN session. */
--
-- char *id; /**< The group ID. */
-- char *name; /**< The name of the group. */
--};
--
--/**************************************************************************
-- ** @name Group API *
-- **************************************************************************/
--/*@{*/
--
--/**
-- * Creates a new group structure.
-- *
-- * @param session The MSN session.
-- * @param id The group ID.
-- * @param name The name of the group.
-- *
-- * @return A new group structure.
-- */
--MsnGroup *msn_group_new(MsnUserList *userlist, const char *id, const char *name);
--
--/**
-- * Destroys a group structure.
-- *
-- * @param group The group to destroy.
-- */
--void msn_group_destroy(MsnGroup *group);
--
--/**
-- * Sets the ID for a group.
-- *
-- * @param group The group.
-- * @param id The ID.
-- */
--void msn_group_set_id(MsnGroup *group, const char *id);
--
--/**
-- * Sets the name for a group.
-- *
-- * @param group The group.
-- * @param name The name.
-- */
--void msn_group_set_name(MsnGroup *group, const char *name);
--
--/**
-- * Returns the ID for a group.
-- *
-- * @param group The group.
-- *
-- * @return The ID.
-- */
--char* msn_group_get_id(const MsnGroup *group);
--
--/**
-- * Returns the name for a group.
-- *
-- * @param group The group.
-- *
-- * @return The name.
-- */
--const char *msn_group_get_name(const MsnGroup *group);
--
--#endif /* MSN_GROUP_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/history.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/history.c
---- pidgin-2.10.7/libpurple/protocols/msn/history.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/history.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,93 +0,0 @@
--/**
-- * @file history.c MSN history functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#include "msn.h"
--#include "history.h"
--
--MsnHistory *
--msn_history_new(void)
--{
-- MsnHistory *history = g_new0(MsnHistory, 1);
--
-- history->trId = 1;
--
-- history->queue = g_queue_new();
--
-- return history;
--}
--
--void
--msn_history_destroy(MsnHistory *history)
--{
-- MsnTransaction *trans;
--
-- while ((trans = g_queue_pop_head(history->queue)) != NULL)
-- msn_transaction_destroy(trans);
--
-- g_queue_free(history->queue);
-- g_free(history);
--}
--
--MsnTransaction *
--msn_history_find(MsnHistory *history, unsigned int trId)
--{
-- MsnTransaction *trans;
-- GList *list;
--
-- for (list = history->queue->head; list != NULL; list = list->next)
-- {
-- trans = list->data;
-- if (trans->trId == trId)
-- return trans;
-- }
--
-- return NULL;
--}
--
--void
--msn_history_add(MsnHistory *history, MsnTransaction *trans)
--{
-- GQueue *queue;
-- int max_elems;
--
-- g_return_if_fail(history != NULL);
-- g_return_if_fail(trans != NULL);
--
-- queue = history->queue;
--
-- trans->trId = history->trId++;
--
-- g_queue_push_tail(queue, trans);
--
-- if (trans->cmdproc->servconn->type == MSN_SERVCONN_NS)
-- max_elems = MSN_NS_HIST_ELEMS;
-- else
-- max_elems = MSN_SB_HIST_ELEMS;
--
-- if (queue->length > max_elems)
-- {
-- trans = g_queue_pop_head(queue);
-- msn_transaction_destroy(trans);
-- }
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/history.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/history.h
---- pidgin-2.10.7/libpurple/protocols/msn/history.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/history.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,50 +0,0 @@
--/**
-- * @file history.h MSN history functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_HISTORY_H
--#define MSN_HISTORY_H
--
--#include "internal.h"
--
--typedef struct _MsnHistory MsnHistory;
--
--#include "transaction.h"
--
--#define MSN_NS_HIST_ELEMS 0x300
--#define MSN_SB_HIST_ELEMS 0x30
--
--/**
-- * The history.
-- */
--struct _MsnHistory
--{
-- GQueue *queue;
-- unsigned int trId;
--};
--
--MsnHistory *msn_history_new(void);
--void msn_history_destroy(MsnHistory *history);
--MsnTransaction *msn_history_find(MsnHistory *history, unsigned int triId);
--void msn_history_add(MsnHistory *history, MsnTransaction *trans);
--
--#endif /* MSN_HISTORY_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/httpconn.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/httpconn.c
---- pidgin-2.10.7/libpurple/protocols/msn/httpconn.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/httpconn.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,739 +0,0 @@
--/**
-- * @file httpconn.c HTTP connection method
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#include "msn.h"
--#include "debug.h"
--#include "httpconn.h"
--
--typedef struct
--{
-- MsnHttpConn *httpconn;
-- char *body;
-- size_t body_len;
--} MsnHttpQueueData;
--
--static void
--msn_httpconn_process_queue(MsnHttpConn *httpconn)
--{
-- httpconn->waiting_response = FALSE;
--
-- if (httpconn->queue != NULL)
-- {
-- MsnHttpQueueData *queue_data;
--
-- queue_data = (MsnHttpQueueData *)httpconn->queue->data;
--
-- httpconn->queue = g_list_remove(httpconn->queue, queue_data);
--
-- msn_httpconn_write(queue_data->httpconn,
-- queue_data->body,
-- queue_data->body_len);
--
-- g_free(queue_data->body);
-- g_free(queue_data);
-- }
--}
--
--static gboolean
--msn_httpconn_parse_data(MsnHttpConn *httpconn, const char *buf,
-- size_t size, char **ret_buf, size_t *ret_size,
-- gboolean *error)
--{
-- const char *s, *c;
-- char *header, *body;
-- const char *body_start;
-- char *tmp;
-- size_t body_len = 0;
--
-- g_return_val_if_fail(httpconn != NULL, FALSE);
-- g_return_val_if_fail(buf != NULL, FALSE);
-- g_return_val_if_fail(size > 0, FALSE);
-- g_return_val_if_fail(ret_buf != NULL, FALSE);
-- g_return_val_if_fail(ret_size != NULL, FALSE);
-- g_return_val_if_fail(error != NULL, FALSE);
--
--#if 0
-- purple_debug_info("msn", "HTTP: parsing data {%s}\n", buf);
--#endif
--
-- /* Healthy defaults. */
-- body = NULL;
--
-- *ret_buf = NULL;
-- *ret_size = 0;
-- *error = FALSE;
--
-- /* First, some tests to see if we have a full block of stuff. */
-- if (((strncmp(buf, "HTTP/1.1 200 OK\r\n", 17) != 0) &&
-- (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) != 0)) &&
-- ((strncmp(buf, "HTTP/1.0 200 OK\r\n", 17) != 0) &&
-- (strncmp(buf, "HTTP/1.0 100 Continue\r\n", 23) != 0)))
-- {
-- *error = TRUE;
--
-- return FALSE;
-- }
--
-- if (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) == 0)
-- {
-- if ((s = strstr(buf, "\r\n\r\n")) == NULL)
-- return FALSE;
--
-- s += 4;
--
-- if (*s == '\0')
-- {
-- *ret_buf = g_strdup("");
-- *ret_size = 0;
--
-- msn_httpconn_process_queue(httpconn);
--
-- return TRUE;
-- }
--
-- size -= (s - buf);
-- buf = s;
-- }
--
-- if ((s = strstr(buf, "\r\n\r\n")) == NULL)
-- /* Need to wait for the full HTTP header to arrive */
-- return FALSE;
--
-- s += 4; /* Skip \r\n\r\n */
-- header = g_strndup(buf, s - buf);
-- body_start = s;
-- body_len = size - (body_start - buf);
--
-- if ((s = purple_strcasestr(header, "Content-Length: ")) != NULL)
-- {
-- int tmp_len;
--
-- s += strlen("Content-Length: ");
--
-- if ((c = strchr(s, '\r')) == NULL)
-- {
-- g_free(header);
--
-- return FALSE;
-- }
--
-- tmp = g_strndup(s, c - s);
-- tmp_len = atoi(tmp);
-- g_free(tmp);
--
-- if (body_len != tmp_len)
-- {
-- /* Need to wait for the full packet to arrive */
--
-- g_free(header);
--
--#if 0
-- purple_debug_warning("msn",
-- "body length (%d) != content length (%d)\n",
-- body_len, tmp_len);
--#endif
--
-- return FALSE;
-- }
-- }
--
-- body = g_malloc(body_len + 1);
-- memcpy(body, body_start, body_len);
-- body[body_len] = '\0';
--
-- if (purple_debug_is_verbose())
-- purple_debug_misc("msn", "Incoming HTTP buffer (header): {%s}\n",
-- header);
--
-- /* Now we should be able to process the data. */
-- if ((s = purple_strcasestr(header, "X-MSN-Messenger: ")) != NULL)
-- {
-- gchar *full_session_id = NULL, *gw_ip = NULL, *session_action = NULL;
-- char *t, *session_id;
-- char **elems, **cur, **tokens;
--
-- full_session_id = gw_ip = session_action = NULL;
--
-- s += strlen("X-MSN-Messenger: ");
--
-- if ((c = strchr(s, '\r')) == NULL)
-- {
-- msn_session_set_error(httpconn->session,
-- MSN_ERROR_HTTP_MALFORMED, NULL);
-- purple_debug_error("msn", "Malformed X-MSN-Messenger field.\n{%s}\n",
-- buf);
--
-- g_free(header);
-- g_free(body);
-- return FALSE;
-- }
--
-- tmp = g_strndup(s, c - s);
--
-- elems = g_strsplit(tmp, "; ", 0);
--
-- for (cur = elems; *cur != NULL; cur++)
-- {
-- tokens = g_strsplit(*cur, "=", 2);
--
-- if (strcmp(tokens[0], "SessionID") == 0) {
-- g_free(full_session_id);
-- full_session_id = tokens[1];
-- } else if (strcmp(tokens[0], "GW-IP") == 0) {
-- g_free(gw_ip);
-- gw_ip = tokens[1];
-- } else if (strcmp(tokens[0], "Session") == 0) {
-- g_free(session_action);
-- session_action = tokens[1];
-- } else
-- g_free(tokens[1]);
--
-- g_free(tokens[0]);
-- /* Don't free each of the tokens, only the array. */
-- g_free(tokens);
-- }
--
-- g_strfreev(elems);
--
-- g_free(tmp);
--
-- t = full_session_id ? strchr(full_session_id, '.') : NULL;
-- if (t != NULL)
-- session_id = g_strndup(full_session_id, t - full_session_id);
-- else {
-- purple_debug_error("msn", "Malformed full_session_id[%s]\n",
-- full_session_id ? full_session_id : NULL);
-- session_id = g_strdup(full_session_id);
-- }
--
-- if (session_action == NULL || strcmp(session_action, "close") != 0)
-- {
-- g_free(httpconn->full_session_id);
-- httpconn->full_session_id = full_session_id;
--
-- g_free(httpconn->session_id);
-- httpconn->session_id = session_id;
--
-- g_free(httpconn->host);
-- httpconn->host = gw_ip;
-- }
-- else
-- {
-- /* I'll be honest, I don't fully understand all this, but this
-- * causes crashes, Stu. */
--#if 0
-- MsnServConn *servconn;
--
-- /* It's going to die. */
-- /* poor thing */
--
-- servconn = httpconn->servconn;
--
-- if (servconn != NULL)
-- servconn->wasted = TRUE;
--#endif
--
-- g_free(full_session_id);
-- g_free(session_id);
-- g_free(gw_ip);
-- }
--
-- g_free(session_action);
-- }
--
-- g_free(header);
--
-- *ret_buf = body;
-- *ret_size = body_len;
--
-- msn_httpconn_process_queue(httpconn);
--
-- return TRUE;
--}
--
--static void
--read_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- MsnHttpConn *httpconn;
-- MsnServConn *servconn;
-- char buf[MSN_BUF_LEN];
-- gssize len;
-- char *result_msg = NULL;
-- size_t result_len = 0;
-- gboolean error = FALSE;
--
-- httpconn = data;
-- servconn = httpconn->servconn;
--
-- if (servconn->type == MSN_SERVCONN_NS)
-- servconn->session->account->gc->last_received = time(NULL);
--
-- len = read(httpconn->fd, buf, sizeof(buf) - 1);
-- if (len < 0 && errno == EAGAIN)
-- return;
-- if (len <= 0) {
-- purple_debug_error("msn", "HTTP: servconn %03d read error, "
-- "len: %" G_GSSIZE_FORMAT ", errno: %d, error: %s\n",
-- servconn->num, len, error, g_strerror(errno));
-- msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ, NULL);
--
-- return;
-- }
--
-- buf[len] = '\0';
--
-- httpconn->rx_buf = g_realloc(httpconn->rx_buf, len + httpconn->rx_len + 1);
-- memcpy(httpconn->rx_buf + httpconn->rx_len, buf, len + 1);
-- httpconn->rx_len += len;
--
-- if (!msn_httpconn_parse_data(httpconn, httpconn->rx_buf, httpconn->rx_len,
-- &result_msg, &result_len, &error))
-- {
-- /* Either we must wait for more input, or something went wrong */
-- if (error)
-- msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ, NULL);
--
-- return;
-- }
--
-- if (error)
-- {
-- purple_debug_error("msn", "HTTP: Special error\n");
-- msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ, NULL);
--
-- return;
-- }
--
-- g_free(httpconn->rx_buf);
-- httpconn->rx_buf = NULL;
-- httpconn->rx_len = 0;
--
-- if (result_len == 0)
-- {
-- /* Nothing to do here */
--#if 0
-- purple_debug_info("msn", "HTTP: nothing to do here\n");
--#endif
-- g_free(result_msg);
-- return;
-- }
--
-- g_free(servconn->rx_buf);
-- servconn->rx_buf = result_msg;
-- servconn->rx_len = result_len;
--
-- msn_servconn_process_data(servconn);
--}
--
--static void
--httpconn_write_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- MsnHttpConn *httpconn;
-- gssize ret;
-- int writelen;
--
-- httpconn = data;
-- writelen = purple_circ_buffer_get_max_read(httpconn->tx_buf);
--
-- if (writelen == 0)
-- {
-- purple_input_remove(httpconn->tx_handler);
-- httpconn->tx_handler = 0;
-- return;
-- }
--
-- ret = write(httpconn->fd, httpconn->tx_buf->outptr, writelen);
-- if (ret <= 0)
-- {
-- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-- /* No worries */
-- return;
--
-- /* Error! */
-- msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_WRITE, NULL);
-- return;
-- }
--
-- purple_circ_buffer_mark_read(httpconn->tx_buf, ret);
--
-- /* TODO: I don't think these 2 lines are needed. Remove them? */
-- if (ret == writelen)
-- httpconn_write_cb(data, source, cond);
--}
--
--static gboolean
--write_raw(MsnHttpConn *httpconn, const char *data, size_t data_len)
--{
-- gssize res; /* result of the write operation */
--
-- if (httpconn->tx_handler == 0)
-- res = write(httpconn->fd, data, data_len);
-- else
-- {
-- res = -1;
-- errno = EAGAIN;
-- }
--
-- if ((res <= 0) && ((errno != EAGAIN) && (errno != EWOULDBLOCK)))
-- {
-- msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_WRITE, NULL);
-- return FALSE;
-- }
--
-- if (res < 0 || res < data_len)
-- {
-- if (res < 0)
-- res = 0;
-- if (httpconn->tx_handler == 0 && httpconn->fd)
-- httpconn->tx_handler = purple_input_add(httpconn->fd,
-- PURPLE_INPUT_WRITE, httpconn_write_cb, httpconn);
-- purple_circ_buffer_append(httpconn->tx_buf, data + res,
-- data_len - res);
-- }
--
-- return TRUE;
--}
--
--static char *
--msn_httpconn_proxy_auth(MsnHttpConn *httpconn)
--{
-- PurpleAccount *account;
-- PurpleProxyInfo *gpi;
-- const char *username, *password;
-- char *auth = NULL;
--
-- account = httpconn->session->account;
--
-- gpi = purple_proxy_get_setup(account);
--
-- if (gpi == NULL || !(purple_proxy_info_get_type(gpi) == PURPLE_PROXY_HTTP ||
-- purple_proxy_info_get_type(gpi) == PURPLE_PROXY_USE_ENVVAR))
-- return NULL;
--
-- username = purple_proxy_info_get_username(gpi);
-- password = purple_proxy_info_get_password(gpi);
--
-- if (username != NULL) {
-- char *tmp;
-- auth = g_strdup_printf("%s:%s", username, password ? password : "");
-- tmp = purple_base64_encode((const guchar *)auth, strlen(auth));
-- g_free(auth);
-- auth = g_strdup_printf("Proxy-Authorization: Basic %s\r\n", tmp);
-- g_free(tmp);
-- }
--
-- return auth;
--}
--
--static gboolean
--msn_httpconn_poll(gpointer data)
--{
-- MsnHttpConn *httpconn;
-- char *header;
-- char *auth;
--
-- httpconn = data;
--
-- g_return_val_if_fail(httpconn != NULL, FALSE);
--
-- if ((httpconn->host == NULL) || (httpconn->full_session_id == NULL))
-- {
-- /* There's no need to poll if the session is not fully established */
-- return TRUE;
-- }
--
-- if (httpconn->waiting_response)
-- {
-- /* There's no need to poll if we're already waiting for a response */
-- return TRUE;
-- }
--
-- auth = msn_httpconn_proxy_auth(httpconn);
--
-- header = g_strdup_printf(
-- "POST http://%s/gateway/gateway.dll?Action=poll&SessionID=%s HTTP/1.1\r\n"
-- "Accept: */*\r\n"
-- "Accept-Language: en-us\r\n"
-- "User-Agent: MSMSGS\r\n"
-- "Host: %s\r\n"
-- "Proxy-Connection: Keep-Alive\r\n"
-- "%s" /* Proxy auth */
-- "Connection: Keep-Alive\r\n"
-- "Pragma: no-cache\r\n"
-- "Content-Type: application/x-msn-messenger\r\n"
-- "Content-Length: 0\r\n\r\n",
-- httpconn->host,
-- httpconn->full_session_id,
-- httpconn->host,
-- auth ? auth : "");
--
-- g_free(auth);
--
-- if (write_raw(httpconn, header, strlen(header)))
-- httpconn->waiting_response = TRUE;
--
-- g_free(header);
--
-- return TRUE;
--}
--
--gssize
--msn_httpconn_write(MsnHttpConn *httpconn, const char *body, size_t body_len)
--{
-- char *params;
-- char *data;
-- int header_len;
-- char *auth;
-- const char *server_types[] = { "NS", "SB" };
-- const char *server_type;
-- char *host;
-- MsnServConn *servconn;
--
-- /* TODO: remove http data from servconn */
--
-- g_return_val_if_fail(httpconn != NULL, 0);
-- g_return_val_if_fail(body != NULL, 0);
-- g_return_val_if_fail(body_len > 0, 0);
--
-- servconn = httpconn->servconn;
--
-- if (httpconn->waiting_response)
-- {
-- MsnHttpQueueData *queue_data = g_new0(MsnHttpQueueData, 1);
--
-- queue_data->httpconn = httpconn;
-- queue_data->body = g_memdup(body, body_len);
-- queue_data->body_len = body_len;
--
-- httpconn->queue = g_list_append(httpconn->queue, queue_data);
--
-- return body_len;
-- }
--
-- server_type = server_types[servconn->type];
--
-- if (httpconn->virgin)
-- {
-- /* QuLogic: This doesn't look right to me, but it still seems to work */
-- host = MSN_HTTPCONN_SERVER;
--
-- /* The first time servconn->host is the host we should connect to. */
-- params = g_strdup_printf("Action=open&Server=%s&IP=%s",
-- server_type,
-- servconn->host);
-- httpconn->virgin = FALSE;
-- }
-- else
-- {
-- /* The rest of the times servconn->host is the gateway host. */
-- host = httpconn->host;
--
-- if (host == NULL || httpconn->full_session_id == NULL)
-- {
-- purple_debug_warning("msn", "Attempted HTTP write before session is established\n");
-- return -1;
-- }
--
-- params = g_strdup_printf("SessionID=%s",
-- httpconn->full_session_id);
-- }
--
-- auth = msn_httpconn_proxy_auth(httpconn);
--
-- data = g_strdup_printf(
-- "POST http://%s/gateway/gateway.dll?%s HTTP/1.1\r\n"
-- "Accept: */*\r\n"
-- "Accept-Language: en-us\r\n"
-- "User-Agent: MSMSGS\r\n"
-- "Host: %s\r\n"
-- "Proxy-Connection: Keep-Alive\r\n"
-- "%s" /* Proxy auth */
-- "Connection: Keep-Alive\r\n"
-- "Pragma: no-cache\r\n"
-- "Content-Type: application/x-msn-messenger\r\n"
-- "Content-Length: %d\r\n\r\n",
-- host,
-- params,
-- host,
-- auth ? auth : "",
-- (int) body_len);
--
-- g_free(params);
--
-- g_free(auth);
--
-- header_len = strlen(data);
-- data = g_realloc(data, header_len + body_len);
-- memcpy(data + header_len, body, body_len);
--
-- if (write_raw(httpconn, data, header_len + body_len))
-- httpconn->waiting_response = TRUE;
--
-- g_free(data);
--
-- return body_len;
--}
--
--MsnHttpConn *
--msn_httpconn_new(MsnServConn *servconn)
--{
-- MsnHttpConn *httpconn;
--
-- g_return_val_if_fail(servconn != NULL, NULL);
--
-- httpconn = g_new0(MsnHttpConn, 1);
--
-- purple_debug_info("msn", "new httpconn (%p)\n", httpconn);
--
-- /* TODO: Remove this */
-- httpconn->session = servconn->session;
--
-- httpconn->servconn = servconn;
--
-- httpconn->tx_buf = purple_circ_buffer_new(MSN_BUF_LEN);
-- httpconn->tx_handler = 0;
--
-- httpconn->fd = -1;
--
-- return httpconn;
--}
--
--void
--msn_httpconn_destroy(MsnHttpConn *httpconn)
--{
-- g_return_if_fail(httpconn != NULL);
--
-- purple_debug_info("msn", "destroy httpconn (%p)\n", httpconn);
--
-- if (httpconn->connected)
-- msn_httpconn_disconnect(httpconn);
--
-- g_free(httpconn->full_session_id);
--
-- g_free(httpconn->session_id);
--
-- g_free(httpconn->host);
--
-- while (httpconn->queue != NULL) {
-- MsnHttpQueueData *queue_data;
--
-- queue_data = (MsnHttpQueueData *) httpconn->queue->data;
--
-- httpconn->queue = g_list_delete_link(httpconn->queue, httpconn->queue);
--
-- g_free(queue_data->body);
-- g_free(queue_data);
-- }
--
-- purple_circ_buffer_destroy(httpconn->tx_buf);
-- if (httpconn->tx_handler > 0)
-- purple_input_remove(httpconn->tx_handler);
--
-- g_free(httpconn);
--}
--
--static void
--connect_cb(gpointer data, gint source, const gchar *error_message)
--{
-- MsnHttpConn *httpconn;
--
-- httpconn = data;
-- httpconn->connect_data = NULL;
-- httpconn->fd = source;
--
-- if (source >= 0)
-- {
-- httpconn->inpa = purple_input_add(httpconn->fd, PURPLE_INPUT_READ,
-- read_cb, data);
--
-- httpconn->timer = purple_timeout_add_seconds(2, msn_httpconn_poll, httpconn);
--
-- msn_httpconn_process_queue(httpconn);
-- }
-- else
-- {
-- purple_debug_error("msn", "HTTP: Connection error: %s\n",
-- error_message ? error_message : "(null)");
-- msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_CONNECT, error_message);
-- }
--}
--
--gboolean
--msn_httpconn_connect(MsnHttpConn *httpconn, const char *host, int port)
--{
-- g_return_val_if_fail(httpconn != NULL, FALSE);
-- g_return_val_if_fail(host != NULL, FALSE);
-- g_return_val_if_fail(port > 0, FALSE);
--
-- if (httpconn->connected)
-- msn_httpconn_disconnect(httpconn);
--
-- httpconn->connect_data = purple_proxy_connect(NULL, httpconn->session->account,
-- host, 80, connect_cb, httpconn);
--
-- if (httpconn->connect_data != NULL)
-- {
-- httpconn->waiting_response = TRUE;
-- httpconn->connected = TRUE;
-- }
--
-- return httpconn->connected;
--}
--
--void
--msn_httpconn_disconnect(MsnHttpConn *httpconn)
--{
-- g_return_if_fail(httpconn != NULL);
--
-- if (!httpconn->connected)
-- return;
--
-- if (httpconn->connect_data != NULL)
-- {
-- purple_proxy_connect_cancel(httpconn->connect_data);
-- httpconn->connect_data = NULL;
-- }
--
-- if (httpconn->timer)
-- {
-- purple_timeout_remove(httpconn->timer);
-- httpconn->timer = 0;
-- }
--
-- if (httpconn->inpa > 0)
-- {
-- purple_input_remove(httpconn->inpa);
-- httpconn->inpa = 0;
-- }
--
-- close(httpconn->fd);
-- httpconn->fd = -1;
--
-- g_free(httpconn->rx_buf);
-- httpconn->rx_buf = NULL;
-- httpconn->rx_len = 0;
--
-- httpconn->connected = FALSE;
--
-- /* msn_servconn_disconnect(httpconn->servconn); */
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/httpconn.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/httpconn.h
---- pidgin-2.10.7/libpurple/protocols/msn/httpconn.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/httpconn.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,112 +0,0 @@
--/**
-- * @file httpconn.h HTTP connection
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_HTTPCONN_H
--#define MSN_HTTPCONN_H
--
--typedef struct _MsnHttpConn MsnHttpConn;
--
--#include "circbuffer.h"
--#include "servconn.h"
--#include "session.h"
--
--/**
-- * An HTTP Connection.
-- */
--struct _MsnHttpConn
--{
-- MsnSession *session; /**< The MSN Session. */
-- MsnServConn *servconn; /**< The connection object. */
--
-- PurpleProxyConnectData *connect_data;
--
-- char *full_session_id; /**< The full session id. */
-- char *session_id; /**< The trimmed session id. */
--
-- int timer; /**< The timer for polling. */
--
-- gboolean waiting_response; /**< The flag that states if we are waiting
-- a response from the server. */
-- gboolean connected; /**< The flag that states if the connection is on. */
-- gboolean virgin; /**< The flag that states if this connection
-- should specify the host (not gateway) to
-- connect to. */
--
-- char *host; /**< The HTTP gateway host. */
-- GList *queue; /**< The queue of data chunks to write. */
--
-- int fd; /**< The connection's file descriptor. */
-- guint inpa; /**< The connection's input handler. */
--
-- char *rx_buf; /**< The receive buffer. */
-- int rx_len; /**< The receive buffer length. */
--
-- PurpleCircBuffer *tx_buf;
-- guint tx_handler;
--};
--
--/**
-- * Creates a new HTTP connection object.
-- *
-- * @param servconn The connection object.
-- *
-- * @return The new object.
-- */
--MsnHttpConn *msn_httpconn_new(MsnServConn *servconn);
--
--/**
-- * Destroys an HTTP connection object.
-- *
-- * @param httpconn The HTTP connection object.
-- */
--void msn_httpconn_destroy(MsnHttpConn *httpconn);
--
--/**
-- * Writes a chunk of data to the HTTP connection.
-- *
-- * @param servconn The server connection.
-- * @param data The data to write.
-- * @param data_len The size of the data to write.
-- *
-- * @return The number of bytes written.
-- */
--gssize msn_httpconn_write(MsnHttpConn *httpconn, const char *data, size_t data_len);
--
--/**
-- * Connects the HTTP connection object to a host.
-- *
-- * @param httpconn The HTTP connection object.
-- * @param host The host to connect to.
-- * @param port The port to connect to.
-- */
--gboolean msn_httpconn_connect(MsnHttpConn *httpconn,
-- const char *host, int port);
--
--/**
-- * Disconnects the HTTP connection object.
-- *
-- * @param httpconn The HTTP connection object.
-- */
--void msn_httpconn_disconnect(MsnHttpConn *httpconn);
--
--#endif /* MSN_HTTPCONN_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/msn/Makefile.am
---- pidgin-2.10.7/libpurple/protocols/msn/Makefile.am 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/Makefile.am 1969-12-31 21:00:00.000000000 -0300
-@@ -1,102 +0,0 @@
--EXTRA_DIST = \
-- directconn.c \
-- directconn.h \
-- Makefile.mingw
--
--pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
--
--MSNSOURCES = \
-- cmdproc.c \
-- cmdproc.h \
-- command.c \
-- command.h \
-- contact.c\
-- contact.h\
-- directconn.c \
-- directconn.h \
-- error.c \
-- error.h \
-- group.c \
-- group.h \
-- history.c \
-- history.h \
-- httpconn.c \
-- httpconn.h \
-- msg.c \
-- msg.h \
-- msn.c \
-- msn.h \
-- nexus.c \
-- nexus.h \
-- notification.c \
-- notification.h \
-- object.c \
-- object.h \
-- oim.c\
-- oim.h\
-- p2p.c \
-- p2p.h \
-- page.c \
-- page.h \
-- servconn.c \
-- servconn.h \
-- session.c \
-- session.h \
-- slp.c \
-- slp.h \
-- slpcall.c \
-- slpcall.h \
-- slplink.c \
-- slplink.h \
-- slpmsg.c \
-- slpmsg.h \
-- slpmsg_part.c \
-- slpmsg_part.h \
-- soap.c \
-- soap.h \
-- state.c \
-- state.h \
-- sbconn.c \
-- sbconn.h \
-- switchboard.c \
-- switchboard.h \
-- table.c \
-- table.h \
-- tlv.c \
-- tlv.h \
-- transaction.c \
-- transaction.h \
-- user.c \
-- user.h \
-- userlist.c \
-- userlist.h \
-- xfer.c \
-- xfer.h \
-- msnutils.c \
-- msnutils.h
--
--AM_CFLAGS = $(st)
--
--libmsn_la_LDFLAGS = -module -avoid-version
--
--if STATIC_MSN
--
--st = -DPURPLE_STATIC_PRPL
--noinst_LTLIBRARIES = libmsn.la
--libmsn_la_SOURCES = $(MSNSOURCES)
--libmsn_la_CFLAGS = $(AM_CFLAGS)
--
--else
--
--st =
--pkg_LTLIBRARIES = libmsn.la
--libmsn_la_SOURCES = $(MSNSOURCES)
--libmsn_la_LIBADD = $(GLIB_LIBS)
--
--endif
--
--AM_CPPFLAGS = \
-- -I$(top_srcdir)/libpurple \
-- -I$(top_builddir)/libpurple \
-- $(GLIB_CFLAGS) \
-- $(DEBUG_CFLAGS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/msn/Makefile.in
---- pidgin-2.10.7/libpurple/protocols/msn/Makefile.in 2013-02-11 07:17:20.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/Makefile.in 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1102 +0,0 @@
--# Makefile.in generated by automake 1.11.6 from Makefile.am.
--# @configure_input@
--
--# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
--# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
--# Foundation, Inc.
--# This Makefile.in is free software; the Free Software Foundation
--# gives unlimited permission to copy and/or distribute it,
--# with or without modifications, as long as this notice is preserved.
--
--# This program is distributed in the hope that it will be useful,
--# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
--# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
--# PARTICULAR PURPOSE.
--
--@SET_MAKE@
--
--VPATH = @srcdir@
--am__make_dryrun = \
-- { \
-- am__dry=no; \
-- case $$MAKEFLAGS in \
-- *\\[\ \ ]*) \
-- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
-- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
-- *) \
-- for am__flg in $$MAKEFLAGS; do \
-- case $$am__flg in \
-- *=*|--*) ;; \
-- *n*) am__dry=yes; break;; \
-- esac; \
-- done;; \
-- esac; \
-- test $$am__dry = yes; \
-- }
--pkgdatadir = $(datadir)/@PACKAGE@
--pkgincludedir = $(includedir)/@PACKAGE@
--pkglibdir = $(libdir)/@PACKAGE@
--pkglibexecdir = $(libexecdir)/@PACKAGE@
--am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
--install_sh_DATA = $(install_sh) -c -m 644
--install_sh_PROGRAM = $(install_sh) -c
--install_sh_SCRIPT = $(install_sh) -c
--INSTALL_HEADER = $(INSTALL_DATA)
--transform = $(program_transform_name)
--NORMAL_INSTALL = :
--PRE_INSTALL = :
--POST_INSTALL = :
--NORMAL_UNINSTALL = :
--PRE_UNINSTALL = :
--POST_UNINSTALL = :
--build_triplet = @build@
--host_triplet = @host@
--subdir = libpurple/protocols/msn
--DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
--ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
--am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
-- $(top_srcdir)/configure.ac
--am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-- $(ACLOCAL_M4)
--mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
--CONFIG_HEADER = $(top_builddir)/config.h
--CONFIG_CLEAN_FILES =
--CONFIG_CLEAN_VPATH_FILES =
--am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
--am__vpath_adj = case $$p in \
-- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
-- *) f=$$p;; \
-- esac;
--am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
--am__install_max = 40
--am__nobase_strip_setup = \
-- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
--am__nobase_strip = \
-- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
--am__nobase_list = $(am__nobase_strip_setup); \
-- for p in $$list; do echo "$$p $$p"; done | \
-- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
-- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
-- if (++n[$$2] == $(am__install_max)) \
-- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
-- END { for (dir in files) print dir, files[dir] }'
--am__base_list = \
-- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
-- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
--am__uninstall_files_from_dir = { \
-- test -z "$$files" \
-- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
-- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
-- $(am__cd) "$$dir" && rm -f $$files; }; \
-- }
--am__installdirs = "$(DESTDIR)$(pkgdir)"
--LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkg_LTLIBRARIES)
--am__DEPENDENCIES_1 =
--@STATIC_MSN_FALSE@libmsn_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
--am__libmsn_la_SOURCES_DIST = cmdproc.c cmdproc.h command.c command.h \
-- contact.c contact.h directconn.c directconn.h error.c error.h \
-- group.c group.h history.c history.h httpconn.c httpconn.h \
-- msg.c msg.h msn.c msn.h nexus.c nexus.h notification.c \
-- notification.h object.c object.h oim.c oim.h p2p.c p2p.h \
-- page.c page.h servconn.c servconn.h session.c session.h slp.c \
-- slp.h slpcall.c slpcall.h slplink.c slplink.h slpmsg.c \
-- slpmsg.h slpmsg_part.c slpmsg_part.h soap.c soap.h state.c \
-- state.h sbconn.c sbconn.h switchboard.c switchboard.h table.c \
-- table.h tlv.c tlv.h transaction.c transaction.h user.c user.h \
-- userlist.c userlist.h xfer.c xfer.h msnutils.c msnutils.h
--am__objects_1 = libmsn_la-cmdproc.lo libmsn_la-command.lo \
-- libmsn_la-contact.lo libmsn_la-directconn.lo \
-- libmsn_la-error.lo libmsn_la-group.lo libmsn_la-history.lo \
-- libmsn_la-httpconn.lo libmsn_la-msg.lo libmsn_la-msn.lo \
-- libmsn_la-nexus.lo libmsn_la-notification.lo \
-- libmsn_la-object.lo libmsn_la-oim.lo libmsn_la-p2p.lo \
-- libmsn_la-page.lo libmsn_la-servconn.lo libmsn_la-session.lo \
-- libmsn_la-slp.lo libmsn_la-slpcall.lo libmsn_la-slplink.lo \
-- libmsn_la-slpmsg.lo libmsn_la-slpmsg_part.lo libmsn_la-soap.lo \
-- libmsn_la-state.lo libmsn_la-sbconn.lo \
-- libmsn_la-switchboard.lo libmsn_la-table.lo libmsn_la-tlv.lo \
-- libmsn_la-transaction.lo libmsn_la-user.lo \
-- libmsn_la-userlist.lo libmsn_la-xfer.lo libmsn_la-msnutils.lo
--@STATIC_MSN_FALSE@am_libmsn_la_OBJECTS = $(am__objects_1)
--@STATIC_MSN_TRUE@am_libmsn_la_OBJECTS = $(am__objects_1)
--libmsn_la_OBJECTS = $(am_libmsn_la_OBJECTS)
--AM_V_lt = $(am__v_lt_@AM_V@)
--am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
--am__v_lt_0 = --silent
--libmsn_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libmsn_la_CFLAGS) \
-- $(CFLAGS) $(libmsn_la_LDFLAGS) $(LDFLAGS) -o $@
--@STATIC_MSN_FALSE@am_libmsn_la_rpath = -rpath $(pkgdir)
--@STATIC_MSN_TRUE@am_libmsn_la_rpath =
--DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
--depcomp = $(SHELL) $(top_srcdir)/depcomp
--am__depfiles_maybe = depfiles
--am__mv = mv -f
--COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
--LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-- $(AM_CFLAGS) $(CFLAGS)
--AM_V_CC = $(am__v_CC_@AM_V@)
--am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
--am__v_CC_0 = @echo " CC " $@;
--AM_V_at = $(am__v_at_@AM_V@)
--am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
--am__v_at_0 = @
--CCLD = $(CC)
--LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-- $(AM_LDFLAGS) $(LDFLAGS) -o $@
--AM_V_CCLD = $(am__v_CCLD_@AM_V@)
--am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
--am__v_CCLD_0 = @echo " CCLD " $@;
--AM_V_GEN = $(am__v_GEN_@AM_V@)
--am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
--am__v_GEN_0 = @echo " GEN " $@;
--SOURCES = $(libmsn_la_SOURCES)
--DIST_SOURCES = $(am__libmsn_la_SOURCES_DIST)
--am__can_run_installinfo = \
-- case $$AM_UPDATE_INFO_DIR in \
-- n|no|NO) false;; \
-- *) (install-info --version) >/dev/null 2>&1;; \
-- esac
--ETAGS = etags
--CTAGS = ctags
--DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
--ACLOCAL = @ACLOCAL@
--ALLOCA = @ALLOCA@
--ALL_LINGUAS = @ALL_LINGUAS@
--AMTAR = @AMTAR@
--AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
--AR = @AR@
--AUTOCONF = @AUTOCONF@
--AUTOHEADER = @AUTOHEADER@
--AUTOMAKE = @AUTOMAKE@
--AVAHI_CFLAGS = @AVAHI_CFLAGS@
--AVAHI_LIBS = @AVAHI_LIBS@
--AWK = @AWK@
--CATALOGS = @CATALOGS@
--CATOBJEXT = @CATOBJEXT@
--CC = @CC@
--CCDEPMODE = @CCDEPMODE@
--CFLAGS = @CFLAGS@
--CHECK_CFLAGS = @CHECK_CFLAGS@
--CHECK_LIBS = @CHECK_LIBS@
--CPP = @CPP@
--CPPFLAGS = @CPPFLAGS@
--CYGPATH_W = @CYGPATH_W@
--DATADIRNAME = @DATADIRNAME@
--DBUS_CFLAGS = @DBUS_CFLAGS@
--DBUS_LIBS = @DBUS_LIBS@
--DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
--DEBUG_CFLAGS = @DEBUG_CFLAGS@
--DEFS = @DEFS@
--DEPDIR = @DEPDIR@
--DLLTOOL = @DLLTOOL@
--DOT = @DOT@
--DOXYGEN = @DOXYGEN@
--DSYMUTIL = @DSYMUTIL@
--DUMPBIN = @DUMPBIN@
--DYNALOADER_A = @DYNALOADER_A@
--DYNAMIC_PRPLS = @DYNAMIC_PRPLS@
--ECHO_C = @ECHO_C@
--ECHO_N = @ECHO_N@
--ECHO_T = @ECHO_T@
--EGREP = @EGREP@
--EVOLUTION_ADDRESSBOOK_CFLAGS = @EVOLUTION_ADDRESSBOOK_CFLAGS@
--EVOLUTION_ADDRESSBOOK_LIBS = @EVOLUTION_ADDRESSBOOK_LIBS@
--EXEEXT = @EXEEXT@
--FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
--FARSTREAM_LIBS = @FARSTREAM_LIBS@
--FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
--GCONFTOOL = @GCONFTOOL@
--GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
--GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
--GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
--GLIB_CFLAGS = @GLIB_CFLAGS@
--GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
--GLIB_LIBS = @GLIB_LIBS@
--GMOFILES = @GMOFILES@
--GMSGFMT = @GMSGFMT@
--GNT_CFLAGS = @GNT_CFLAGS@
--GNT_LIBS = @GNT_LIBS@
--GNT_LT_VERSION_INFO = @GNT_LT_VERSION_INFO@
--GNT_MAJOR_VERSION = @GNT_MAJOR_VERSION@
--GNT_MICRO_VERSION = @GNT_MICRO_VERSION@
--GNT_MINOR_VERSION = @GNT_MINOR_VERSION@
--GNT_VERSION = @GNT_VERSION@
--GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
--GNUTLS_LIBS = @GNUTLS_LIBS@
--GREP = @GREP@
--GSTINTERFACES_CFLAGS = @GSTINTERFACES_CFLAGS@
--GSTINTERFACES_LIBS = @GSTINTERFACES_LIBS@
--GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
--GSTREAMER_LIBS = @GSTREAMER_LIBS@
--GTKSPELL_CFLAGS = @GTKSPELL_CFLAGS@
--GTKSPELL_LIBS = @GTKSPELL_LIBS@
--GTK_CFLAGS = @GTK_CFLAGS@
--GTK_LIBS = @GTK_LIBS@
--IDN_CFLAGS = @IDN_CFLAGS@
--IDN_LIBS = @IDN_LIBS@
--INSTALL = @INSTALL@
--INSTALL_DATA = @INSTALL_DATA@
--INSTALL_PROGRAM = @INSTALL_PROGRAM@
--INSTALL_SCRIPT = @INSTALL_SCRIPT@
--INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
--INSTOBJEXT = @INSTOBJEXT@
--INTLLIBS = @INTLLIBS@
--INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
--INTLTOOL_MERGE = @INTLTOOL_MERGE@
--INTLTOOL_PERL = @INTLTOOL_PERL@
--INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
--INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
--INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
--INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
--INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
--KRB4_CFLAGS = @KRB4_CFLAGS@
--KRB4_LDFLAGS = @KRB4_LDFLAGS@
--KRB4_LIBS = @KRB4_LIBS@
--LD = @LD@
--LDADD = @LDADD@
--LDFLAGS = @LDFLAGS@
--LIBOBJS = @LIBOBJS@
--LIBPERL_A = @LIBPERL_A@
--LIBS = @LIBS@
--LIBTOOL = @LIBTOOL@
--LIBXML_CFLAGS = @LIBXML_CFLAGS@
--LIBXML_LIBS = @LIBXML_LIBS@
--LIPO = @LIPO@
--LN_S = @LN_S@
--LTLIBOBJS = @LTLIBOBJS@
--MAKEINFO = @MAKEINFO@
--MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
--MKDIR_P = @MKDIR_P@
--MKINSTALLDIRS = @MKINSTALLDIRS@
--MONO_CFLAGS = @MONO_CFLAGS@
--MONO_LIBS = @MONO_LIBS@
--MSGFMT = @MSGFMT@
--MSGFMT_OPTS = @MSGFMT_OPTS@
--MSGMERGE = @MSGMERGE@
--NETWORKMANAGER_CFLAGS = @NETWORKMANAGER_CFLAGS@
--NETWORKMANAGER_LIBS = @NETWORKMANAGER_LIBS@
--NM = @NM@
--NMEDIT = @NMEDIT@
--NSS_CFLAGS = @NSS_CFLAGS@
--NSS_LIBS = @NSS_LIBS@
--OBJDUMP = @OBJDUMP@
--OBJEXT = @OBJEXT@
--OTOOL = @OTOOL@
--OTOOL64 = @OTOOL64@
--PACKAGE = @PACKAGE@
--PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
--PACKAGE_NAME = @PACKAGE_NAME@
--PACKAGE_STRING = @PACKAGE_STRING@
--PACKAGE_TARNAME = @PACKAGE_TARNAME@
--PACKAGE_URL = @PACKAGE_URL@
--PACKAGE_VERSION = @PACKAGE_VERSION@
--PANGO_CFLAGS = @PANGO_CFLAGS@
--PANGO_LIBS = @PANGO_LIBS@
--PATH_SEPARATOR = @PATH_SEPARATOR@
--PERL = @PERL@
--PERL_CFLAGS = @PERL_CFLAGS@
--PERL_LIBS = @PERL_LIBS@
--PKG_CONFIG = @PKG_CONFIG@
--PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
--PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
--PLUGINS_DEFINE = @PLUGINS_DEFINE@
--POFILES = @POFILES@
--POSUB = @POSUB@
--PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
--PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
--PURPLE_LT_VERSION_INFO = @PURPLE_LT_VERSION_INFO@
--PURPLE_MAJOR_VERSION = @PURPLE_MAJOR_VERSION@
--PURPLE_MICRO_VERSION = @PURPLE_MICRO_VERSION@
--PURPLE_MINOR_VERSION = @PURPLE_MINOR_VERSION@
--PURPLE_VERSION = @PURPLE_VERSION@
--PYTHON = @PYTHON@
--PY_CFLAGS = @PY_CFLAGS@
--PY_LIBS = @PY_LIBS@
--RANLIB = @RANLIB@
--SASL_LIBS = @SASL_LIBS@
--SED = @SED@
--SET_MAKE = @SET_MAKE@
--SHELL = @SHELL@
--SILC_CFLAGS = @SILC_CFLAGS@
--SILC_LIBS = @SILC_LIBS@
--SM_LIBS = @SM_LIBS@
--SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
--SQLITE3_LIBS = @SQLITE3_LIBS@
--SSL_CERTIFICATES_DIR = @SSL_CERTIFICATES_DIR@
--STATIC_LINK_LIBS = @STATIC_LINK_LIBS@
--STATIC_PRPLS = @STATIC_PRPLS@
--STRIP = @STRIP@
--TCL_CFLAGS = @TCL_CFLAGS@
--TCL_LIBS = @TCL_LIBS@
--TK_LIBS = @TK_LIBS@
--USE_NLS = @USE_NLS@
--VERSION = @VERSION@
--X11_CFLAGS = @X11_CFLAGS@
--X11_LIBS = @X11_LIBS@
--XGETTEXT = @XGETTEXT@
--XMKMF = @XMKMF@
--XSLTPROC = @XSLTPROC@
--XSS_LIBS = @XSS_LIBS@
--X_CFLAGS = @X_CFLAGS@
--X_EXTRA_LIBS = @X_EXTRA_LIBS@
--X_LIBS = @X_LIBS@
--X_PRE_LIBS = @X_PRE_LIBS@
--ZEPHYR_CFLAGS = @ZEPHYR_CFLAGS@
--ZEPHYR_LDFLAGS = @ZEPHYR_LDFLAGS@
--ZEPHYR_LIBS = @ZEPHYR_LIBS@
--abs_builddir = @abs_builddir@
--abs_srcdir = @abs_srcdir@
--abs_top_builddir = @abs_top_builddir@
--abs_top_srcdir = @abs_top_srcdir@
--ac_ct_AR = @ac_ct_AR@
--ac_ct_CC = @ac_ct_CC@
--ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
--am__include = @am__include@
--am__leading_dot = @am__leading_dot@
--am__quote = @am__quote@
--am__tar = @am__tar@
--am__untar = @am__untar@
--bindir = @bindir@
--build = @build@
--build_alias = @build_alias@
--build_cpu = @build_cpu@
--build_os = @build_os@
--build_vendor = @build_vendor@
--builddir = @builddir@
--datadir = @datadir@
--datarootdir = @datarootdir@
--docdir = @docdir@
--dvidir = @dvidir@
--enable_dbus = @enable_dbus@
--enable_devhelp = @enable_devhelp@
--enable_dot = @enable_dot@
--enable_doxygen = @enable_doxygen@
--exec_prefix = @exec_prefix@
--host = @host@
--host_alias = @host_alias@
--host_cpu = @host_cpu@
--host_os = @host_os@
--host_vendor = @host_vendor@
--htmldir = @htmldir@
--includedir = @includedir@
--infodir = @infodir@
--install_sh = @install_sh@
--intltool__v_merge_options_ = @intltool__v_merge_options_@
--intltool__v_merge_options_0 = @intltool__v_merge_options_0@
--libdir = @libdir@
--libexecdir = @libexecdir@
--localedir = @localedir@
--localstatedir = @localstatedir@
--mandir = @mandir@
--mkdir_p = @mkdir_p@
--oldincludedir = @oldincludedir@
--pdfdir = @pdfdir@
--perlpath = @perlpath@
--pidginpath = @pidginpath@
--prefix = @prefix@
--program_transform_name = @program_transform_name@
--psdir = @psdir@
--sbindir = @sbindir@
--sedpath = @sedpath@
--sharedstatedir = @sharedstatedir@
--srcdir = @srcdir@
--sysconfdir = @sysconfdir@
--target_alias = @target_alias@
--top_build_prefix = @top_build_prefix@
--top_builddir = @top_builddir@
--top_srcdir = @top_srcdir@
--EXTRA_DIST = \
-- directconn.c \
-- directconn.h \
-- Makefile.mingw
--
--pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
--MSNSOURCES = \
-- cmdproc.c \
-- cmdproc.h \
-- command.c \
-- command.h \
-- contact.c\
-- contact.h\
-- directconn.c \
-- directconn.h \
-- error.c \
-- error.h \
-- group.c \
-- group.h \
-- history.c \
-- history.h \
-- httpconn.c \
-- httpconn.h \
-- msg.c \
-- msg.h \
-- msn.c \
-- msn.h \
-- nexus.c \
-- nexus.h \
-- notification.c \
-- notification.h \
-- object.c \
-- object.h \
-- oim.c\
-- oim.h\
-- p2p.c \
-- p2p.h \
-- page.c \
-- page.h \
-- servconn.c \
-- servconn.h \
-- session.c \
-- session.h \
-- slp.c \
-- slp.h \
-- slpcall.c \
-- slpcall.h \
-- slplink.c \
-- slplink.h \
-- slpmsg.c \
-- slpmsg.h \
-- slpmsg_part.c \
-- slpmsg_part.h \
-- soap.c \
-- soap.h \
-- state.c \
-- state.h \
-- sbconn.c \
-- sbconn.h \
-- switchboard.c \
-- switchboard.h \
-- table.c \
-- table.h \
-- tlv.c \
-- tlv.h \
-- transaction.c \
-- transaction.h \
-- user.c \
-- user.h \
-- userlist.c \
-- userlist.h \
-- xfer.c \
-- xfer.h \
-- msnutils.c \
-- msnutils.h
--
--AM_CFLAGS = $(st)
--libmsn_la_LDFLAGS = -module -avoid-version
--@STATIC_MSN_FALSE@st =
--@STATIC_MSN_TRUE@st = -DPURPLE_STATIC_PRPL
--@STATIC_MSN_TRUE@noinst_LTLIBRARIES = libmsn.la
--@STATIC_MSN_FALSE@libmsn_la_SOURCES = $(MSNSOURCES)
--@STATIC_MSN_TRUE@libmsn_la_SOURCES = $(MSNSOURCES)
--@STATIC_MSN_TRUE@libmsn_la_CFLAGS = $(AM_CFLAGS)
--@STATIC_MSN_FALSE@pkg_LTLIBRARIES = libmsn.la
--@STATIC_MSN_FALSE@libmsn_la_LIBADD = $(GLIB_LIBS)
--AM_CPPFLAGS = \
-- -I$(top_srcdir)/libpurple \
-- -I$(top_builddir)/libpurple \
-- $(GLIB_CFLAGS) \
-- $(DEBUG_CFLAGS)
--
--all: all-am
--
--.SUFFIXES:
--.SUFFIXES: .c .lo .o .obj
--$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
-- @for dep in $?; do \
-- case '$(am__configure_deps)' in \
-- *$$dep*) \
-- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
-- && { if test -f $@; then exit 0; else break; fi; }; \
-- exit 1;; \
-- esac; \
-- done; \
-- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpurple/protocols/msn/Makefile'; \
-- $(am__cd) $(top_srcdir) && \
-- $(AUTOMAKE) --gnu libpurple/protocols/msn/Makefile
--.PRECIOUS: Makefile
--Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-- @case '$?' in \
-- *config.status*) \
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-- *) \
-- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-- esac;
--
--$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--
--$(top_srcdir)/configure: $(am__configure_deps)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--$(ACLOCAL_M4): $(am__aclocal_m4_deps)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--$(am__aclocal_m4_deps):
--
--clean-noinstLTLIBRARIES:
-- -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-- @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
-- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-- test "$$dir" != "$$p" || dir=.; \
-- echo "rm -f \"$${dir}/so_locations\""; \
-- rm -f "$${dir}/so_locations"; \
-- done
--install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES)
-- @$(NORMAL_INSTALL)
-- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
-- list2=; for p in $$list; do \
-- if test -f $$p; then \
-- list2="$$list2 $$p"; \
-- else :; fi; \
-- done; \
-- test -z "$$list2" || { \
-- echo " $(MKDIR_P) '$(DESTDIR)$(pkgdir)'"; \
-- $(MKDIR_P) "$(DESTDIR)$(pkgdir)" || exit 1; \
-- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgdir)'"; \
-- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgdir)"; \
-- }
--
--uninstall-pkgLTLIBRARIES:
-- @$(NORMAL_UNINSTALL)
-- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
-- for p in $$list; do \
-- $(am__strip_dir) \
-- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgdir)/$$f'"; \
-- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgdir)/$$f"; \
-- done
--
--clean-pkgLTLIBRARIES:
-- -test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES)
-- @list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
-- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-- test "$$dir" != "$$p" || dir=.; \
-- echo "rm -f \"$${dir}/so_locations\""; \
-- rm -f "$${dir}/so_locations"; \
-- done
--libmsn.la: $(libmsn_la_OBJECTS) $(libmsn_la_DEPENDENCIES) $(EXTRA_libmsn_la_DEPENDENCIES)
-- $(AM_V_CCLD)$(libmsn_la_LINK) $(am_libmsn_la_rpath) $(libmsn_la_OBJECTS) $(libmsn_la_LIBADD) $(LIBS)
--
--mostlyclean-compile:
-- -rm -f *.$(OBJEXT)
--
--distclean-compile:
-- -rm -f *.tab.c
--
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-cmdproc.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-command.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-contact.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-directconn.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-error.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-group.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-history.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-httpconn.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-msg.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-msn.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-msnutils.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-nexus.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-notification.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-object.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-oim.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-p2p.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-page.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-sbconn.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-servconn.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-session.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-slp.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-slpcall.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-slplink.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-slpmsg.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-slpmsg_part.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-soap.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-state.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-switchboard.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-table.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-tlv.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-transaction.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-user.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-userlist.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-xfer.Plo@am__quote@
--
--.c.o:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
--
--.c.obj:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
--
--.c.lo:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
--
--libmsn_la-cmdproc.lo: cmdproc.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-cmdproc.lo -MD -MP -MF $(DEPDIR)/libmsn_la-cmdproc.Tpo -c -o libmsn_la-cmdproc.lo `test -f 'cmdproc.c' || echo '$(srcdir)/'`cmdproc.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-cmdproc.Tpo $(DEPDIR)/libmsn_la-cmdproc.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmdproc.c' object='libmsn_la-cmdproc.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-cmdproc.lo `test -f 'cmdproc.c' || echo '$(srcdir)/'`cmdproc.c
--
--libmsn_la-command.lo: command.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-command.lo -MD -MP -MF $(DEPDIR)/libmsn_la-command.Tpo -c -o libmsn_la-command.lo `test -f 'command.c' || echo '$(srcdir)/'`command.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-command.Tpo $(DEPDIR)/libmsn_la-command.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='command.c' object='libmsn_la-command.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-command.lo `test -f 'command.c' || echo '$(srcdir)/'`command.c
--
--libmsn_la-contact.lo: contact.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-contact.lo -MD -MP -MF $(DEPDIR)/libmsn_la-contact.Tpo -c -o libmsn_la-contact.lo `test -f 'contact.c' || echo '$(srcdir)/'`contact.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-contact.Tpo $(DEPDIR)/libmsn_la-contact.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='contact.c' object='libmsn_la-contact.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-contact.lo `test -f 'contact.c' || echo '$(srcdir)/'`contact.c
--
--libmsn_la-directconn.lo: directconn.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-directconn.lo -MD -MP -MF $(DEPDIR)/libmsn_la-directconn.Tpo -c -o libmsn_la-directconn.lo `test -f 'directconn.c' || echo '$(srcdir)/'`directconn.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-directconn.Tpo $(DEPDIR)/libmsn_la-directconn.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='directconn.c' object='libmsn_la-directconn.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-directconn.lo `test -f 'directconn.c' || echo '$(srcdir)/'`directconn.c
--
--libmsn_la-error.lo: error.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-error.lo -MD -MP -MF $(DEPDIR)/libmsn_la-error.Tpo -c -o libmsn_la-error.lo `test -f 'error.c' || echo '$(srcdir)/'`error.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-error.Tpo $(DEPDIR)/libmsn_la-error.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='error.c' object='libmsn_la-error.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-error.lo `test -f 'error.c' || echo '$(srcdir)/'`error.c
--
--libmsn_la-group.lo: group.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-group.lo -MD -MP -MF $(DEPDIR)/libmsn_la-group.Tpo -c -o libmsn_la-group.lo `test -f 'group.c' || echo '$(srcdir)/'`group.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-group.Tpo $(DEPDIR)/libmsn_la-group.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='group.c' object='libmsn_la-group.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-group.lo `test -f 'group.c' || echo '$(srcdir)/'`group.c
--
--libmsn_la-history.lo: history.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-history.lo -MD -MP -MF $(DEPDIR)/libmsn_la-history.Tpo -c -o libmsn_la-history.lo `test -f 'history.c' || echo '$(srcdir)/'`history.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-history.Tpo $(DEPDIR)/libmsn_la-history.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='history.c' object='libmsn_la-history.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-history.lo `test -f 'history.c' || echo '$(srcdir)/'`history.c
--
--libmsn_la-httpconn.lo: httpconn.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-httpconn.lo -MD -MP -MF $(DEPDIR)/libmsn_la-httpconn.Tpo -c -o libmsn_la-httpconn.lo `test -f 'httpconn.c' || echo '$(srcdir)/'`httpconn.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-httpconn.Tpo $(DEPDIR)/libmsn_la-httpconn.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='httpconn.c' object='libmsn_la-httpconn.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-httpconn.lo `test -f 'httpconn.c' || echo '$(srcdir)/'`httpconn.c
--
--libmsn_la-msg.lo: msg.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-msg.lo -MD -MP -MF $(DEPDIR)/libmsn_la-msg.Tpo -c -o libmsn_la-msg.lo `test -f 'msg.c' || echo '$(srcdir)/'`msg.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-msg.Tpo $(DEPDIR)/libmsn_la-msg.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='msg.c' object='libmsn_la-msg.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-msg.lo `test -f 'msg.c' || echo '$(srcdir)/'`msg.c
--
--libmsn_la-msn.lo: msn.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-msn.lo -MD -MP -MF $(DEPDIR)/libmsn_la-msn.Tpo -c -o libmsn_la-msn.lo `test -f 'msn.c' || echo '$(srcdir)/'`msn.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-msn.Tpo $(DEPDIR)/libmsn_la-msn.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='msn.c' object='libmsn_la-msn.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-msn.lo `test -f 'msn.c' || echo '$(srcdir)/'`msn.c
--
--libmsn_la-nexus.lo: nexus.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-nexus.lo -MD -MP -MF $(DEPDIR)/libmsn_la-nexus.Tpo -c -o libmsn_la-nexus.lo `test -f 'nexus.c' || echo '$(srcdir)/'`nexus.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-nexus.Tpo $(DEPDIR)/libmsn_la-nexus.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nexus.c' object='libmsn_la-nexus.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-nexus.lo `test -f 'nexus.c' || echo '$(srcdir)/'`nexus.c
--
--libmsn_la-notification.lo: notification.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-notification.lo -MD -MP -MF $(DEPDIR)/libmsn_la-notification.Tpo -c -o libmsn_la-notification.lo `test -f 'notification.c' || echo '$(srcdir)/'`notification.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-notification.Tpo $(DEPDIR)/libmsn_la-notification.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='notification.c' object='libmsn_la-notification.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-notification.lo `test -f 'notification.c' || echo '$(srcdir)/'`notification.c
--
--libmsn_la-object.lo: object.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-object.lo -MD -MP -MF $(DEPDIR)/libmsn_la-object.Tpo -c -o libmsn_la-object.lo `test -f 'object.c' || echo '$(srcdir)/'`object.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-object.Tpo $(DEPDIR)/libmsn_la-object.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='object.c' object='libmsn_la-object.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-object.lo `test -f 'object.c' || echo '$(srcdir)/'`object.c
--
--libmsn_la-oim.lo: oim.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-oim.lo -MD -MP -MF $(DEPDIR)/libmsn_la-oim.Tpo -c -o libmsn_la-oim.lo `test -f 'oim.c' || echo '$(srcdir)/'`oim.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-oim.Tpo $(DEPDIR)/libmsn_la-oim.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oim.c' object='libmsn_la-oim.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-oim.lo `test -f 'oim.c' || echo '$(srcdir)/'`oim.c
--
--libmsn_la-p2p.lo: p2p.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-p2p.lo -MD -MP -MF $(DEPDIR)/libmsn_la-p2p.Tpo -c -o libmsn_la-p2p.lo `test -f 'p2p.c' || echo '$(srcdir)/'`p2p.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-p2p.Tpo $(DEPDIR)/libmsn_la-p2p.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='p2p.c' object='libmsn_la-p2p.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-p2p.lo `test -f 'p2p.c' || echo '$(srcdir)/'`p2p.c
--
--libmsn_la-page.lo: page.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-page.lo -MD -MP -MF $(DEPDIR)/libmsn_la-page.Tpo -c -o libmsn_la-page.lo `test -f 'page.c' || echo '$(srcdir)/'`page.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-page.Tpo $(DEPDIR)/libmsn_la-page.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='page.c' object='libmsn_la-page.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-page.lo `test -f 'page.c' || echo '$(srcdir)/'`page.c
--
--libmsn_la-servconn.lo: servconn.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-servconn.lo -MD -MP -MF $(DEPDIR)/libmsn_la-servconn.Tpo -c -o libmsn_la-servconn.lo `test -f 'servconn.c' || echo '$(srcdir)/'`servconn.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-servconn.Tpo $(DEPDIR)/libmsn_la-servconn.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='servconn.c' object='libmsn_la-servconn.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-servconn.lo `test -f 'servconn.c' || echo '$(srcdir)/'`servconn.c
--
--libmsn_la-session.lo: session.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-session.lo -MD -MP -MF $(DEPDIR)/libmsn_la-session.Tpo -c -o libmsn_la-session.lo `test -f 'session.c' || echo '$(srcdir)/'`session.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-session.Tpo $(DEPDIR)/libmsn_la-session.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='session.c' object='libmsn_la-session.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-session.lo `test -f 'session.c' || echo '$(srcdir)/'`session.c
--
--libmsn_la-slp.lo: slp.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-slp.lo -MD -MP -MF $(DEPDIR)/libmsn_la-slp.Tpo -c -o libmsn_la-slp.lo `test -f 'slp.c' || echo '$(srcdir)/'`slp.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-slp.Tpo $(DEPDIR)/libmsn_la-slp.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='slp.c' object='libmsn_la-slp.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-slp.lo `test -f 'slp.c' || echo '$(srcdir)/'`slp.c
--
--libmsn_la-slpcall.lo: slpcall.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-slpcall.lo -MD -MP -MF $(DEPDIR)/libmsn_la-slpcall.Tpo -c -o libmsn_la-slpcall.lo `test -f 'slpcall.c' || echo '$(srcdir)/'`slpcall.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-slpcall.Tpo $(DEPDIR)/libmsn_la-slpcall.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='slpcall.c' object='libmsn_la-slpcall.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-slpcall.lo `test -f 'slpcall.c' || echo '$(srcdir)/'`slpcall.c
--
--libmsn_la-slplink.lo: slplink.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-slplink.lo -MD -MP -MF $(DEPDIR)/libmsn_la-slplink.Tpo -c -o libmsn_la-slplink.lo `test -f 'slplink.c' || echo '$(srcdir)/'`slplink.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-slplink.Tpo $(DEPDIR)/libmsn_la-slplink.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='slplink.c' object='libmsn_la-slplink.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-slplink.lo `test -f 'slplink.c' || echo '$(srcdir)/'`slplink.c
--
--libmsn_la-slpmsg.lo: slpmsg.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-slpmsg.lo -MD -MP -MF $(DEPDIR)/libmsn_la-slpmsg.Tpo -c -o libmsn_la-slpmsg.lo `test -f 'slpmsg.c' || echo '$(srcdir)/'`slpmsg.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-slpmsg.Tpo $(DEPDIR)/libmsn_la-slpmsg.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='slpmsg.c' object='libmsn_la-slpmsg.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-slpmsg.lo `test -f 'slpmsg.c' || echo '$(srcdir)/'`slpmsg.c
--
--libmsn_la-slpmsg_part.lo: slpmsg_part.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-slpmsg_part.lo -MD -MP -MF $(DEPDIR)/libmsn_la-slpmsg_part.Tpo -c -o libmsn_la-slpmsg_part.lo `test -f 'slpmsg_part.c' || echo '$(srcdir)/'`slpmsg_part.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-slpmsg_part.Tpo $(DEPDIR)/libmsn_la-slpmsg_part.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='slpmsg_part.c' object='libmsn_la-slpmsg_part.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-slpmsg_part.lo `test -f 'slpmsg_part.c' || echo '$(srcdir)/'`slpmsg_part.c
--
--libmsn_la-soap.lo: soap.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-soap.lo -MD -MP -MF $(DEPDIR)/libmsn_la-soap.Tpo -c -o libmsn_la-soap.lo `test -f 'soap.c' || echo '$(srcdir)/'`soap.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-soap.Tpo $(DEPDIR)/libmsn_la-soap.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soap.c' object='libmsn_la-soap.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-soap.lo `test -f 'soap.c' || echo '$(srcdir)/'`soap.c
--
--libmsn_la-state.lo: state.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-state.lo -MD -MP -MF $(DEPDIR)/libmsn_la-state.Tpo -c -o libmsn_la-state.lo `test -f 'state.c' || echo '$(srcdir)/'`state.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-state.Tpo $(DEPDIR)/libmsn_la-state.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='state.c' object='libmsn_la-state.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-state.lo `test -f 'state.c' || echo '$(srcdir)/'`state.c
--
--libmsn_la-sbconn.lo: sbconn.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-sbconn.lo -MD -MP -MF $(DEPDIR)/libmsn_la-sbconn.Tpo -c -o libmsn_la-sbconn.lo `test -f 'sbconn.c' || echo '$(srcdir)/'`sbconn.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-sbconn.Tpo $(DEPDIR)/libmsn_la-sbconn.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbconn.c' object='libmsn_la-sbconn.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-sbconn.lo `test -f 'sbconn.c' || echo '$(srcdir)/'`sbconn.c
--
--libmsn_la-switchboard.lo: switchboard.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-switchboard.lo -MD -MP -MF $(DEPDIR)/libmsn_la-switchboard.Tpo -c -o libmsn_la-switchboard.lo `test -f 'switchboard.c' || echo '$(srcdir)/'`switchboard.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-switchboard.Tpo $(DEPDIR)/libmsn_la-switchboard.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='switchboard.c' object='libmsn_la-switchboard.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-switchboard.lo `test -f 'switchboard.c' || echo '$(srcdir)/'`switchboard.c
--
--libmsn_la-table.lo: table.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-table.lo -MD -MP -MF $(DEPDIR)/libmsn_la-table.Tpo -c -o libmsn_la-table.lo `test -f 'table.c' || echo '$(srcdir)/'`table.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-table.Tpo $(DEPDIR)/libmsn_la-table.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='table.c' object='libmsn_la-table.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-table.lo `test -f 'table.c' || echo '$(srcdir)/'`table.c
--
--libmsn_la-tlv.lo: tlv.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-tlv.lo -MD -MP -MF $(DEPDIR)/libmsn_la-tlv.Tpo -c -o libmsn_la-tlv.lo `test -f 'tlv.c' || echo '$(srcdir)/'`tlv.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-tlv.Tpo $(DEPDIR)/libmsn_la-tlv.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tlv.c' object='libmsn_la-tlv.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-tlv.lo `test -f 'tlv.c' || echo '$(srcdir)/'`tlv.c
--
--libmsn_la-transaction.lo: transaction.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-transaction.lo -MD -MP -MF $(DEPDIR)/libmsn_la-transaction.Tpo -c -o libmsn_la-transaction.lo `test -f 'transaction.c' || echo '$(srcdir)/'`transaction.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-transaction.Tpo $(DEPDIR)/libmsn_la-transaction.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='transaction.c' object='libmsn_la-transaction.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-transaction.lo `test -f 'transaction.c' || echo '$(srcdir)/'`transaction.c
--
--libmsn_la-user.lo: user.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-user.lo -MD -MP -MF $(DEPDIR)/libmsn_la-user.Tpo -c -o libmsn_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-user.Tpo $(DEPDIR)/libmsn_la-user.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user.c' object='libmsn_la-user.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c
--
--libmsn_la-userlist.lo: userlist.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-userlist.lo -MD -MP -MF $(DEPDIR)/libmsn_la-userlist.Tpo -c -o libmsn_la-userlist.lo `test -f 'userlist.c' || echo '$(srcdir)/'`userlist.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-userlist.Tpo $(DEPDIR)/libmsn_la-userlist.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='userlist.c' object='libmsn_la-userlist.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-userlist.lo `test -f 'userlist.c' || echo '$(srcdir)/'`userlist.c
--
--libmsn_la-xfer.lo: xfer.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-xfer.lo -MD -MP -MF $(DEPDIR)/libmsn_la-xfer.Tpo -c -o libmsn_la-xfer.lo `test -f 'xfer.c' || echo '$(srcdir)/'`xfer.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-xfer.Tpo $(DEPDIR)/libmsn_la-xfer.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xfer.c' object='libmsn_la-xfer.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-xfer.lo `test -f 'xfer.c' || echo '$(srcdir)/'`xfer.c
--
--libmsn_la-msnutils.lo: msnutils.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-msnutils.lo -MD -MP -MF $(DEPDIR)/libmsn_la-msnutils.Tpo -c -o libmsn_la-msnutils.lo `test -f 'msnutils.c' || echo '$(srcdir)/'`msnutils.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-msnutils.Tpo $(DEPDIR)/libmsn_la-msnutils.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='msnutils.c' object='libmsn_la-msnutils.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-msnutils.lo `test -f 'msnutils.c' || echo '$(srcdir)/'`msnutils.c
--
--mostlyclean-libtool:
-- -rm -f *.lo
--
--clean-libtool:
-- -rm -rf .libs _libs
--
--ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- mkid -fID $$unique
--tags: TAGS
--
--TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
-- $(TAGS_FILES) $(LISP)
-- set x; \
-- here=`pwd`; \
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- shift; \
-- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-- test -n "$$unique" || unique=$$empty_fix; \
-- if test $$# -gt 0; then \
-- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-- "$$@" $$unique; \
-- else \
-- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-- $$unique; \
-- fi; \
-- fi
--ctags: CTAGS
--CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
-- $(TAGS_FILES) $(LISP)
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- test -z "$(CTAGS_ARGS)$$unique" \
-- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-- $$unique
--
--GTAGS:
-- here=`$(am__cd) $(top_builddir) && pwd` \
-- && $(am__cd) $(top_srcdir) \
-- && gtags -i $(GTAGS_ARGS) "$$here"
--
--distclean-tags:
-- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
--
--distdir: $(DISTFILES)
-- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-- list='$(DISTFILES)'; \
-- dist_files=`for file in $$list; do echo $$file; done | \
-- sed -e "s|^$$srcdirstrip/||;t" \
-- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-- case $$dist_files in \
-- */*) $(MKDIR_P) `echo "$$dist_files" | \
-- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-- sort -u` ;; \
-- esac; \
-- for file in $$dist_files; do \
-- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-- if test -d $$d/$$file; then \
-- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-- if test -d "$(distdir)/$$file"; then \
-- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-- fi; \
-- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-- fi; \
-- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-- else \
-- test -f "$(distdir)/$$file" \
-- || cp -p $$d/$$file "$(distdir)/$$file" \
-- || exit 1; \
-- fi; \
-- done
--check-am: all-am
--check: check-am
--all-am: Makefile $(LTLIBRARIES)
--installdirs:
-- for dir in "$(DESTDIR)$(pkgdir)"; do \
-- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
-- done
--install: install-am
--install-exec: install-exec-am
--install-data: install-data-am
--uninstall: uninstall-am
--
--install-am: all-am
-- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
--
--installcheck: installcheck-am
--install-strip:
-- if test -z '$(STRIP)'; then \
-- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-- install; \
-- else \
-- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-- fi
--mostlyclean-generic:
--
--clean-generic:
--
--distclean-generic:
-- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
--
--maintainer-clean-generic:
-- @echo "This command is intended for maintainers to use"
-- @echo "it deletes files that may require special tools to rebuild."
--clean: clean-am
--
--clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
-- clean-pkgLTLIBRARIES mostlyclean-am
--
--distclean: distclean-am
-- -rm -rf ./$(DEPDIR)
-- -rm -f Makefile
--distclean-am: clean-am distclean-compile distclean-generic \
-- distclean-tags
--
--dvi: dvi-am
--
--dvi-am:
--
--html: html-am
--
--html-am:
--
--info: info-am
--
--info-am:
--
--install-data-am: install-pkgLTLIBRARIES
--
--install-dvi: install-dvi-am
--
--install-dvi-am:
--
--install-exec-am:
--
--install-html: install-html-am
--
--install-html-am:
--
--install-info: install-info-am
--
--install-info-am:
--
--install-man:
--
--install-pdf: install-pdf-am
--
--install-pdf-am:
--
--install-ps: install-ps-am
--
--install-ps-am:
--
--installcheck-am:
--
--maintainer-clean: maintainer-clean-am
-- -rm -rf ./$(DEPDIR)
-- -rm -f Makefile
--maintainer-clean-am: distclean-am maintainer-clean-generic
--
--mostlyclean: mostlyclean-am
--
--mostlyclean-am: mostlyclean-compile mostlyclean-generic \
-- mostlyclean-libtool
--
--pdf: pdf-am
--
--pdf-am:
--
--ps: ps-am
--
--ps-am:
--
--uninstall-am: uninstall-pkgLTLIBRARIES
--
--.MAKE: install-am install-strip
--
--.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
-- clean-libtool clean-noinstLTLIBRARIES clean-pkgLTLIBRARIES \
-- ctags distclean distclean-compile distclean-generic \
-- distclean-libtool distclean-tags distdir dvi dvi-am html \
-- html-am info info-am install install-am install-data \
-- install-data-am install-dvi install-dvi-am install-exec \
-- install-exec-am install-html install-html-am install-info \
-- install-info-am install-man install-pdf install-pdf-am \
-- install-pkgLTLIBRARIES install-ps install-ps-am install-strip \
-- installcheck installcheck-am installdirs maintainer-clean \
-- maintainer-clean-generic mostlyclean mostlyclean-compile \
-- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-- tags uninstall uninstall-am uninstall-pkgLTLIBRARIES
--
--
--# Tell versions [3.59,3.63) of GNU make to not export all variables.
--# Otherwise a system limit (for SysV at least) may be exceeded.
--.NOEXPORT:
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/msn/Makefile.mingw
---- pidgin-2.10.7/libpurple/protocols/msn/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,110 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of libmsn
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = libmsn
--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)
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = cmdproc.c \
-- command.c \
-- contact.c\
-- directconn.c \
-- error.c \
-- group.c \
-- history.c \
-- httpconn.c \
-- msg.c \
-- msn.c \
-- nexus.c \
-- notification.c \
-- object.c \
-- oim.c\
-- p2p.c \
-- page.c \
-- servconn.c \
-- session.c \
-- slp.c \
-- slpcall.c \
-- slplink.c \
-- slpmsg.c \
-- slpmsg_part.c \
-- soap.c\
-- state.c \
-- sbconn.c \
-- switchboard.c \
-- table.c \
-- tlv.c \
-- transaction.c \
-- user.c \
-- userlist.c \
-- xfer.c \
-- msnutils.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lintl \
-- -lws2_32 \
-- -lpurple
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll
--
--install: all $(DLL_INSTALL_DIR)
-- cp $(TARGET).dll $(DLL_INSTALL_DIR)
--
--$(OBJECTS): $(PURPLE_CONFIG_H)
--
--$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -f $(OBJECTS)
-- rm -f $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/msg.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/msg.c
---- pidgin-2.10.7/libpurple/protocols/msn/msg.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/msg.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1215 +0,0 @@
--/**
-- * @file msg.c Message functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "msn.h"
--#include "msg.h"
--#include "msnutils.h"
--#include "slpmsg.h"
--#include "slpmsg_part.h"
--
--MsnMessage *
--msn_message_new(MsnMsgType type)
--{
-- MsnMessage *msg;
--
-- msg = g_new0(MsnMessage, 1);
-- msg->type = type;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "message new (%p)(%d)\n", msg, type);
--
-- msg->header_table = g_hash_table_new_full(g_str_hash, g_str_equal,
-- g_free, g_free);
--
-- msn_message_ref(msg);
--
-- return msg;
--}
--
--/**
-- * Destroys a message.
-- *
-- * @param msg The message to destroy.
-- */
--static void
--msn_message_destroy(MsnMessage *msg)
--{
-- g_return_if_fail(msg != NULL);
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "message destroy (%p)\n", msg);
--
-- g_free(msg->remote_user);
-- g_free(msg->body);
-- g_free(msg->content_type);
-- g_free(msg->charset);
--
-- g_hash_table_destroy(msg->header_table);
-- g_list_free(msg->header_list);
-- if (msg->part)
-- msn_slpmsgpart_unref(msg->part);
--
-- g_free(msg);
--}
--
--MsnMessage *
--msn_message_ref(MsnMessage *msg)
--{
-- g_return_val_if_fail(msg != NULL, NULL);
--
-- msg->ref_count++;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "message ref (%p)[%u]\n", msg, msg->ref_count);
--
-- return msg;
--}
--
--void
--msn_message_unref(MsnMessage *msg)
--{
-- g_return_if_fail(msg != NULL);
-- g_return_if_fail(msg->ref_count > 0);
--
-- msg->ref_count--;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "message unref (%p)[%u]\n", msg, msg->ref_count);
--
-- if (msg->ref_count == 0)
-- msn_message_destroy(msg);
--}
--
--MsnMessage *
--msn_message_new_plain(const char *message)
--{
-- MsnMessage *msg;
-- char *message_cr;
--
-- msg = msn_message_new(MSN_MSG_TEXT);
-- msg->retries = 1;
-- msn_message_set_header(msg, "User-Agent", PACKAGE_NAME "/" VERSION);
-- msn_message_set_content_type(msg, "text/plain");
-- msn_message_set_charset(msg, "UTF-8");
-- msn_message_set_flag(msg, 'A');
-- msn_message_set_header(msg, "X-MMS-IM-Format",
-- "FN=Segoe%20UI; EF=; CO=0; CS=1;PF=0");
--
-- message_cr = purple_str_add_cr(message);
-- msn_message_set_bin_data(msg, message_cr, strlen(message_cr));
-- g_free(message_cr);
--
-- return msg;
--}
--
--MsnMessage *
--msn_message_new_msnslp(void)
--{
-- MsnMessage *msg;
--
-- msg = msn_message_new(MSN_MSG_SLP);
--
-- msn_message_set_header(msg, "User-Agent", NULL);
--
-- msn_message_set_flag(msg, 'D');
-- msn_message_set_content_type(msg, "application/x-msnmsgrp2p");
--
-- return msg;
--}
--
--MsnMessage *
--msn_message_new_nudge(void)
--{
-- MsnMessage *msg;
--
-- msg = msn_message_new(MSN_MSG_NUDGE);
-- msn_message_set_content_type(msg, "text/x-msnmsgr-datacast");
-- msn_message_set_flag(msg, 'N');
-- msn_message_set_bin_data(msg, "ID: 1\r\n", 7);
--
-- return msg;
--}
--
--void
--msn_message_parse_payload(MsnMessage *msg,
-- const char *payload, size_t payload_len,
-- const char *line_dem,const char *body_dem)
--{
-- char *tmp_base, *tmp;
-- const char *content_type;
-- char *end;
-- char **elems, **cur, **tokens;
--
-- g_return_if_fail(payload != NULL);
-- tmp_base = tmp = g_malloc(payload_len + 1);
-- memcpy(tmp_base, payload, payload_len);
-- tmp_base[payload_len] = '\0';
--
-- /* Find the end of the headers */
-- end = strstr(tmp, body_dem);
-- /* TODO? some clients use \r delimiters instead of \r\n, the official client
-- * doesn't send such messages, but does handle receiving them. We'll just
-- * avoid crashing for now */
-- if (end == NULL) {
-- g_free(tmp_base);
-- g_return_if_reached();
-- }
-- *end = '\0';
--
-- /* Split the headers and parse each one */
-- elems = g_strsplit(tmp, line_dem, 0);
-- for (cur = elems; *cur != NULL; cur++)
-- {
-- const char *key, *value;
--
-- /* If this line starts with whitespace, it's been folded from the
-- previous line and won't have ':'. */
-- if ((**cur == ' ') || (**cur == '\t')) {
-- tokens = g_strsplit(g_strchug(*cur), "=\"", 2);
-- key = tokens[0];
-- value = tokens[1];
--
-- /* The only one I care about is 'boundary' (which is folded from
-- the key 'Content-Type'), so only process that. */
-- if (!strcmp(key, "boundary")) {
-- char *end = strchr(value, '\"');
-- *end = '\0';
-- msn_message_set_header(msg, key, value);
-- }
--
-- g_strfreev(tokens);
-- continue;
-- }
--
-- tokens = g_strsplit(*cur, ": ", 2);
--
-- key = tokens[0];
-- value = tokens[1];
--
-- /*if not MIME content ,then return*/
-- if (!strcmp(key, "MIME-Version"))
-- {
-- g_strfreev(tokens);
-- continue;
-- }
--
-- if (!strcmp(key, "Content-Type"))
-- {
-- char *charset, *c;
--
-- if ((c = strchr(value, ';')) != NULL)
-- {
-- if ((charset = strchr(c, '=')) != NULL)
-- {
-- charset++;
-- msn_message_set_charset(msg, charset);
-- }
--
-- *c = '\0';
-- }
--
-- msn_message_set_content_type(msg, value);
-- }
-- else
-- {
-- msn_message_set_header(msg, key, value);
-- }
--
-- g_strfreev(tokens);
-- }
-- g_strfreev(elems);
--
-- /* Proceed to the end of the "\r\n\r\n" */
-- tmp = end + strlen(body_dem);
--
-- /* Now we *should* be at the body. */
-- content_type = msn_message_get_content_type(msg);
--
-- if (payload_len - (tmp - tmp_base) > 0) {
-- msg->body_len = payload_len - (tmp - tmp_base);
-- g_free(msg->body);
-- msg->body = g_malloc(msg->body_len + 1);
-- memcpy(msg->body, tmp, msg->body_len);
-- msg->body[msg->body_len] = '\0';
-- }
--
-- if (msg->body && content_type && purple_str_has_prefix(content_type, "text/")) {
-- char *body = NULL;
--
-- if (msg->charset == NULL || g_str_equal(msg->charset, "UTF-8")) {
-- /* Charset is UTF-8 */
-- if (!g_utf8_validate(msg->body, msg->body_len, NULL)) {
-- purple_debug_warning("msn", "Message contains invalid "
-- "UTF-8. Attempting to salvage.\n");
-- body = purple_utf8_salvage(msg->body);
-- payload_len = strlen(body);
-- }
-- } else {
-- /* Charset is something other than UTF-8 */
-- GError *err = NULL;
-- body = g_convert(msg->body, msg->body_len, "UTF-8",
-- msg->charset, NULL, &payload_len, &err);
-- if (!body || err) {
-- purple_debug_warning("msn", "Unable to convert message from "
-- "%s to UTF-8: %s\n", msg->charset,
-- err ? err->message : "Unknown error");
-- if (err)
-- g_error_free(err);
--
-- /* Fallback to ISO-8859-1 */
-- g_free(body);
-- body = g_convert(msg->body, msg->body_len, "UTF-8",
-- "ISO-8859-1", NULL, &payload_len, NULL);
-- if (!body) {
-- g_free(msg->body);
-- msg->body = NULL;
-- msg->body_len = 0;
-- }
-- }
-- }
--
-- if (body) {
-- g_free(msg->body);
-- msg->body = body;
-- msg->body_len = payload_len;
-- msn_message_set_charset(msg, "UTF-8");
-- }
-- }
--
-- g_free(tmp_base);
--}
--
--MsnMessage *
--msn_message_new_from_cmd(MsnSession *session, MsnCommand *cmd)
--{
-- MsnMessage *msg;
--
-- g_return_val_if_fail(cmd != NULL, NULL);
--
-- msg = msn_message_new(MSN_MSG_UNKNOWN);
--
-- msg->remote_user = g_strdup(cmd->params[0]);
-- /* msg->size = atoi(cmd->params[2]); */
-- msg->cmd = cmd;
--
-- return msg;
--}
--
--char *
--msn_message_gen_payload(MsnMessage *msg, size_t *ret_size)
--{
-- GList *l;
-- char *n, *base, *end;
-- int len;
-- size_t body_len = 0;
-- const void *body;
--
-- g_return_val_if_fail(msg != NULL, NULL);
--
-- len = MSN_BUF_LEN;
--
-- base = n = end = g_malloc(len + 1);
-- end += len;
--
-- /* Standard header. */
-- if (msg->charset == NULL)
-- {
-- g_snprintf(n, len,
-- "MIME-Version: 1.0\r\n"
-- "Content-Type: %s\r\n",
-- msg->content_type);
-- }
-- else
-- {
-- g_snprintf(n, len,
-- "MIME-Version: 1.0\r\n"
-- "Content-Type: %s; charset=%s\r\n",
-- msg->content_type, msg->charset);
-- }
--
-- n += strlen(n);
--
-- for (l = msg->header_list; l != NULL; l = l->next)
-- {
-- const char *key;
-- const char *value;
--
-- key = l->data;
-- value = msn_message_get_header_value(msg, key);
--
-- g_snprintf(n, end - n, "%s: %s\r\n", key, value);
-- n += strlen(n);
-- }
--
-- n += g_strlcpy(n, "\r\n", end - n);
--
-- body = msn_message_get_bin_data(msg, &body_len);
--
-- if (body != NULL)
-- {
-- memcpy(n, body, body_len);
-- n += body_len;
-- *n = '\0';
-- }
--
-- if (ret_size != NULL)
-- {
-- *ret_size = n - base;
--
-- if (*ret_size > 1664)
-- *ret_size = 1664;
-- }
--
-- return base;
--}
--
--void
--msn_message_set_flag(MsnMessage *msg, char flag)
--{
-- g_return_if_fail(msg != NULL);
-- g_return_if_fail(flag != 0);
--
-- msg->flag = flag;
--}
--
--char
--msn_message_get_flag(const MsnMessage *msg)
--{
-- g_return_val_if_fail(msg != NULL, 0);
--
-- return msg->flag;
--}
--
--void
--msn_message_set_bin_data(MsnMessage *msg, const void *data, size_t len)
--{
-- g_return_if_fail(msg != NULL);
--
-- /* There is no need to waste memory on data we cannot send anyway */
-- if (len > 1664)
-- len = 1664;
--
-- if (msg->body != NULL)
-- g_free(msg->body);
--
-- if (data != NULL && len > 0)
-- {
-- msg->body = g_malloc(len + 1);
-- memcpy(msg->body, data, len);
-- msg->body[len] = '\0';
-- msg->body_len = len;
-- }
-- else
-- {
-- msg->body = NULL;
-- msg->body_len = 0;
-- }
--}
--
--const void *
--msn_message_get_bin_data(const MsnMessage *msg, size_t *len)
--{
-- g_return_val_if_fail(msg != NULL, NULL);
--
-- if (len)
-- *len = msg->body_len;
--
-- return msg->body;
--}
--
--void
--msn_message_set_content_type(MsnMessage *msg, const char *type)
--{
-- g_return_if_fail(msg != NULL);
--
-- g_free(msg->content_type);
-- msg->content_type = g_strdup(type);
--}
--
--const char *
--msn_message_get_content_type(const MsnMessage *msg)
--{
-- g_return_val_if_fail(msg != NULL, NULL);
--
-- return msg->content_type;
--}
--
--void
--msn_message_set_charset(MsnMessage *msg, const char *charset)
--{
-- g_return_if_fail(msg != NULL);
--
-- g_free(msg->charset);
-- msg->charset = g_strdup(charset);
--}
--
--const char *
--msn_message_get_charset(const MsnMessage *msg)
--{
-- g_return_val_if_fail(msg != NULL, NULL);
--
-- return msg->charset;
--}
--
--void
--msn_message_set_header(MsnMessage *msg, const char *name, const char *value)
--{
-- const char *temp;
-- char *new_name;
--
-- g_return_if_fail(msg != NULL);
-- g_return_if_fail(name != NULL);
--
-- temp = msn_message_get_header_value(msg, name);
--
-- if (value == NULL)
-- {
-- if (temp != NULL)
-- {
-- GList *l;
--
-- for (l = msg->header_list; l != NULL; l = l->next)
-- {
-- if (!g_ascii_strcasecmp(l->data, name))
-- {
-- msg->header_list = g_list_remove(msg->header_list, l->data);
--
-- break;
-- }
-- }
--
-- g_hash_table_remove(msg->header_table, name);
-- }
--
-- return;
-- }
--
-- new_name = g_strdup(name);
--
-- g_hash_table_insert(msg->header_table, new_name, g_strdup(value));
--
-- if (temp == NULL)
-- msg->header_list = g_list_append(msg->header_list, new_name);
--}
--
--const char *
--msn_message_get_header_value(const MsnMessage *msg, const char *name)
--{
-- g_return_val_if_fail(msg != NULL, NULL);
-- g_return_val_if_fail(name != NULL, NULL);
--
-- return g_hash_table_lookup(msg->header_table, name);
--}
--
--GHashTable *
--msn_message_get_hashtable_from_body(const MsnMessage *msg)
--{
-- GHashTable *table;
-- size_t body_len;
-- const char *body;
-- char **elems, **cur, **tokens, *body_str;
--
-- g_return_val_if_fail(msg != NULL, NULL);
--
-- table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
--
-- body = msn_message_get_bin_data(msg, &body_len);
--
-- g_return_val_if_fail(body != NULL, NULL);
--
-- body_str = g_strndup(body, body_len);
-- elems = g_strsplit(body_str, "\r\n", 0);
-- g_free(body_str);
--
-- for (cur = elems; *cur != NULL; cur++)
-- {
-- if (**cur == '\0')
-- break;
--
-- tokens = g_strsplit(*cur, ": ", 2);
--
-- if (tokens[0] != NULL && tokens[1] != NULL) {
-- g_hash_table_insert(table, tokens[0], tokens[1]);
-- g_free(tokens);
-- } else
-- g_strfreev(tokens);
-- }
--
-- g_strfreev(elems);
--
-- return table;
--}
--
--char *
--msn_message_to_string(MsnMessage *msg)
--{
-- size_t body_len;
-- const char *body;
--
-- g_return_val_if_fail(msg != NULL, NULL);
-- g_return_val_if_fail(msg->type == MSN_MSG_TEXT, NULL);
--
-- body = msn_message_get_bin_data(msg, &body_len);
--
-- return g_strndup(body, body_len);
--}
--
--void
--msn_message_show_readable(MsnMessage *msg, const char *info,
-- gboolean text_body)
--{
-- GString *str;
-- size_t body_len;
-- const char *body;
-- GList *l;
--
-- g_return_if_fail(msg != NULL);
--
-- str = g_string_new(NULL);
--
-- /* Standard header. */
-- if (msg->charset == NULL)
-- {
-- g_string_append_printf(str,
-- "MIME-Version: 1.0\r\n"
-- "Content-Type: %s\r\n",
-- msg->content_type);
-- }
-- else
-- {
-- g_string_append_printf(str,
-- "MIME-Version: 1.0\r\n"
-- "Content-Type: %s; charset=%s\r\n",
-- msg->content_type, msg->charset);
-- }
--
-- for (l = msg->header_list; l; l = l->next)
-- {
-- char *key;
-- const char *value;
--
-- key = l->data;
-- value = msn_message_get_header_value(msg, key);
--
-- g_string_append_printf(str, "%s: %s\r\n", key, value);
-- }
--
-- g_string_append(str, "\r\n");
--
-- body = msn_message_get_bin_data(msg, &body_len);
--
-- if (body != NULL)
-- {
-- if (msg->type == MSN_MSG_TEXT)
-- {
-- g_string_append_len(str, body, body_len);
-- g_string_append(str, "\r\n");
-- }
-- else
-- {
-- size_t i;
-- for (i = 0; i < body_len; i++, body++)
-- {
-- g_string_append_printf(str, "%02x ", (unsigned char)*body);
-- if (i % 16 == 0 && i != 0)
-- g_string_append_c(str, '\n');
-- }
-- g_string_append_c(str, '\n');
-- }
-- }
--
-- purple_debug_info("msn", "Message %s:\n{%s}\n", info, str->str);
--
-- g_string_free(str, TRUE);
--}
--
--/**************************************************************************
-- * Message Handlers
-- **************************************************************************/
--void
--msn_plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
--{
-- PurpleConnection *gc;
-- const char *body;
-- char *body_enc;
-- char *body_final;
-- size_t body_len;
-- const char *passport;
-- const char *value;
--
-- gc = cmdproc->session->account->gc;
--
-- body = msn_message_get_bin_data(msg, &body_len);
-- body_enc = g_markup_escape_text(body, body_len);
--
-- passport = msg->remote_user;
--
-- if (!strcmp(passport, "messenger@microsoft.com") &&
-- strstr(body, "immediate security update"))
-- {
-- return;
-- }
--
--#if 0
-- if ((value = msn_message_get_header_value(msg, "User-Agent")) != NULL)
-- {
-- purple_debug_misc("msn", "User-Agent = '%s'\n", value);
-- }
--#endif
--
-- if ((value = msn_message_get_header_value(msg, "X-MMS-IM-Format")) != NULL)
-- {
-- char *pre, *post;
--
-- msn_parse_format(value, &pre, &post);
--
-- body_final = g_strdup_printf("%s%s%s", pre ? pre : "",
-- body_enc ? body_enc : "", post ? post : "");
--
-- g_free(pre);
-- g_free(post);
-- g_free(body_enc);
-- }
-- else
-- {
-- body_final = body_enc;
-- }
--
-- if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
-- MsnSwitchBoard *swboard = cmdproc->data;
--
-- swboard->flag |= MSN_SB_FLAG_IM;
--
-- if (swboard->current_users > 1 ||
-- ((swboard->conv != NULL) &&
-- purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
-- {
-- /* If current_users is always ok as it should then there is no need to
-- * check if this is a chat. */
-- if (swboard->current_users <= 1)
-- purple_debug_misc("msn", "plain_msg: current_users(%d)\n",
-- swboard->current_users);
--
-- serv_got_chat_in(gc, swboard->chat_id, passport, 0, body_final,
-- time(NULL));
-- if (swboard->conv == NULL)
-- {
-- swboard->conv = purple_find_chat(gc, swboard->chat_id);
-- swboard->flag |= MSN_SB_FLAG_IM;
-- }
-- }
-- else if (!g_str_equal(passport, purple_account_get_username(gc->account)))
-- {
-- /* Don't im ourselves ... */
-- serv_got_im(gc, passport, body_final, 0, time(NULL));
-- if (swboard->conv == NULL)
-- {
-- swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-- passport, purple_connection_get_account(gc));
-- swboard->flag |= MSN_SB_FLAG_IM;
-- }
-- }
--
-- } else {
-- serv_got_im(gc, passport, body_final, 0, time(NULL));
-- }
--
-- g_free(body_final);
--}
--
--void
--msn_control_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
--{
-- PurpleConnection *gc;
-- char *passport;
--
-- gc = cmdproc->session->account->gc;
-- passport = msg->remote_user;
--
-- if (msn_message_get_header_value(msg, "TypingUser") == NULL)
-- return;
--
-- if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
-- MsnSwitchBoard *swboard = cmdproc->data;
--
-- if (swboard->current_users == 1)
-- {
-- serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT,
-- PURPLE_TYPING);
-- }
--
-- } else {
-- serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT,
-- PURPLE_TYPING);
-- }
--}
--
--static void
--datacast_inform_user(MsnSwitchBoard *swboard, const char *who,
-- const char *msg, const char *filename)
--{
-- char *username, *str;
-- PurpleAccount *account;
-- PurpleBuddy *b;
-- PurpleConnection *pc;
-- gboolean chat;
--
-- account = swboard->session->account;
-- pc = purple_account_get_connection(account);
--
-- if ((b = purple_find_buddy(account, who)) != NULL)
-- username = g_markup_escape_text(purple_buddy_get_alias(b), -1);
-- else
-- username = g_markup_escape_text(who, -1);
-- str = g_strdup_printf(msg, username, filename);
-- g_free(username);
--
-- swboard->flag |= MSN_SB_FLAG_IM;
-- if (swboard->current_users > 1)
-- chat = TRUE;
-- else
-- chat = FALSE;
--
-- if (swboard->conv == NULL) {
-- if (chat)
-- swboard->conv = purple_find_chat(account->gc, swboard->chat_id);
-- else {
-- swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-- who, account);
-- if (swboard->conv == NULL)
-- swboard->conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, who);
-- }
-- }
--
-- if (chat)
-- serv_got_chat_in(pc,
-- purple_conv_chat_get_id(PURPLE_CONV_CHAT(swboard->conv)),
-- who, PURPLE_MESSAGE_RECV|PURPLE_MESSAGE_SYSTEM, str,
-- time(NULL));
-- else
-- serv_got_im(pc, who, str, PURPLE_MESSAGE_RECV|PURPLE_MESSAGE_SYSTEM,
-- time(NULL));
-- g_free(str);
--
--}
--
--/* TODO: Make these not be such duplicates of each other */
--static void
--got_wink_cb(MsnSlpCall *slpcall, const guchar *data, gsize size)
--{
-- FILE *f = NULL;
-- char *path = NULL;
-- const char *who = slpcall->slplink->remote_user;
-- purple_debug_info("msn", "Received wink from %s\n", who);
--
-- if ((f = purple_mkstemp(&path, TRUE)) &&
-- (fwrite(data, 1, size, f) == size)) {
-- datacast_inform_user(slpcall->slplink->swboard,
-- who,
-- _("%s sent a wink. <a href='msn-wink://%s'>Click here to play it</a>"),
-- path);
-- } else {
-- purple_debug_error("msn", "Couldn\'t create temp file to store wink\n");
-- datacast_inform_user(slpcall->slplink->swboard,
-- who,
-- _("%s sent a wink, but it could not be saved"),
-- NULL);
-- }
-- if (f)
-- fclose(f);
-- g_free(path);
--}
--
--static void
--got_voiceclip_cb(MsnSlpCall *slpcall, const guchar *data, gsize size)
--{
-- FILE *f = NULL;
-- char *path = NULL;
-- const char *who = slpcall->slplink->remote_user;
-- purple_debug_info("msn", "Received voice clip from %s\n", who);
--
-- if ((f = purple_mkstemp(&path, TRUE)) &&
-- (fwrite(data, 1, size, f) == size)) {
-- datacast_inform_user(slpcall->slplink->swboard,
-- who,
-- _("%s sent a voice clip. <a href='audio://%s'>Click here to play it</a>"),
-- path);
-- } else {
-- purple_debug_error("msn", "Couldn\'t create temp file to store sound\n");
-- datacast_inform_user(slpcall->slplink->swboard,
-- who,
-- _("%s sent a voice clip, but it could not be saved"),
-- NULL);
-- }
-- if (f)
-- fclose(f);
-- g_free(path);
--}
--
--void
--msn_p2p_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
--{
-- MsnSession *session;
-- MsnSlpLink *slplink;
-- MsnP2PVersion p2p;
--
-- session = cmdproc->servconn->session;
-- slplink = msn_session_get_slplink(session, msg->remote_user);
--
-- if (slplink->swboard == NULL)
-- {
-- /*
-- * We will need swboard in order to change its flags. If its
-- * NULL, something has probably gone wrong earlier on. I
-- * didn't want to do this, but MSN 7 is somehow causing us
-- * to crash here, I couldn't reproduce it to debug more,
-- * and people are reporting bugs. Hopefully this doesn't
-- * cause more crashes. Stu.
-- */
-- if (cmdproc->data == NULL)
-- g_warning("msn_p2p_msg cmdproc->data was NULL\n");
-- else {
-- slplink->swboard = (MsnSwitchBoard *)cmdproc->data;
-- slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink);
-- }
-- }
--
-- p2p = msn_slplink_get_p2p_version(slplink);
-- msg->part = msn_slpmsgpart_new_from_data(p2p, msg->body, msg->body_len);
--
-- if (msg->part)
-- msn_slplink_process_msg(slplink, msg->part);
-- else
-- purple_debug_warning("msn", "P2P message failed to parse.\n");
--}
--
--static void
--got_emoticon(MsnSlpCall *slpcall,
-- const guchar *data, gsize size)
--{
-- PurpleConversation *conv;
-- MsnSwitchBoard *swboard;
--
-- swboard = slpcall->slplink->swboard;
-- conv = swboard->conv;
--
-- if (conv) {
-- /* FIXME: it would be better if we wrote the data as we received it
-- instead of all at once, calling write multiple times and
-- close once at the very end
-- */
-- purple_conv_custom_smiley_write(conv, slpcall->data_info, data, size);
-- purple_conv_custom_smiley_close(conv, slpcall->data_info );
-- }
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "Got smiley: %s\n", slpcall->data_info);
--}
--
--void msn_emoticon_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
--{
-- MsnSession *session;
-- MsnSlpLink *slplink;
-- MsnSwitchBoard *swboard;
-- MsnObject *obj;
-- char **tokens;
-- char *smile, *body_str;
-- const char *body, *who, *sha1;
-- guint tok;
-- size_t body_len;
--
-- PurpleConversation *conv;
--
-- session = cmdproc->servconn->session;
--
-- if (!purple_account_get_bool(session->account, "custom_smileys", TRUE))
-- return;
--
-- swboard = cmdproc->data;
-- conv = swboard->conv;
--
-- body = msn_message_get_bin_data(msg, &body_len);
-- if (!body || !body_len)
-- return;
-- body_str = g_strndup(body, body_len);
--
-- /* MSN Messenger 7 may send more than one MSNObject in a single message...
-- * Maybe 10 tokens is a reasonable max value. */
-- tokens = g_strsplit(body_str, "\t", 10);
--
-- g_free(body_str);
--
-- for (tok = 0; tok < 9; tok += 2) {
-- if (tokens[tok] == NULL || tokens[tok + 1] == NULL) {
-- break;
-- }
--
-- smile = tokens[tok];
-- obj = msn_object_new_from_string(purple_url_decode(tokens[tok + 1]));
--
-- if (obj == NULL)
-- break;
--
-- who = msn_object_get_creator(obj);
-- sha1 = msn_object_get_sha1(obj);
--
-- slplink = msn_session_get_slplink(session, who);
-- if (slplink->swboard != swboard) {
-- if (slplink->swboard != NULL)
-- /*
-- * Apparently we're using a different switchboard now or
-- * something? I don't know if this is normal, but it
-- * definitely happens. So make sure the old switchboard
-- * doesn't still have a reference to us.
-- */
-- slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink);
-- slplink->swboard = swboard;
-- slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink);
-- }
--
-- /* If the conversation doesn't exist then this is a custom smiley
-- * used in the first message in a MSN conversation: we need to create
-- * the conversation now, otherwise the custom smiley won't be shown.
-- * This happens because every GtkIMHtml has its own smiley tree: if
-- * the conversation doesn't exist then we cannot associate the new
-- * smiley with its GtkIMHtml widget. */
-- if (!conv) {
-- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, session->account, who);
-- }
--
-- if (purple_conv_custom_smiley_add(conv, smile, "sha1", sha1, TRUE)) {
-- msn_slplink_request_object(slplink, smile, got_emoticon, NULL, obj);
-- }
--
-- msn_object_destroy(obj);
-- obj = NULL;
-- who = NULL;
-- sha1 = NULL;
-- }
-- g_strfreev(tokens);
--}
--
--void
--msn_datacast_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
--{
-- GHashTable *body;
-- const char *id;
-- body = msn_message_get_hashtable_from_body(msg);
--
-- id = g_hash_table_lookup(body, "ID");
--
-- if (!strcmp(id, "1")) {
-- /* Nudge */
-- PurpleAccount *account;
-- const char *user;
--
-- account = cmdproc->session->account;
-- user = msg->remote_user;
--
-- if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
-- MsnSwitchBoard *swboard = cmdproc->data;
-- if (swboard->current_users > 1 ||
-- ((swboard->conv != NULL) &&
-- purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
-- purple_prpl_got_attention_in_chat(account->gc, swboard->chat_id, user, MSN_NUDGE);
--
-- else
-- purple_prpl_got_attention(account->gc, user, MSN_NUDGE);
-- } else {
-- purple_prpl_got_attention(account->gc, user, MSN_NUDGE);
-- }
--
-- } else if (!strcmp(id, "2")) {
-- /* Wink */
-- MsnSession *session;
-- MsnSlpLink *slplink;
-- MsnObject *obj;
-- const char *who;
-- const char *data;
--
-- session = cmdproc->session;
--
-- data = g_hash_table_lookup(body, "Data");
-- obj = msn_object_new_from_string(data);
-- who = msn_object_get_creator(obj);
--
-- slplink = msn_session_get_slplink(session, who);
-- msn_slplink_request_object(slplink, data, got_wink_cb, NULL, obj);
--
-- msn_object_destroy(obj);
--
--
-- } else if (!strcmp(id, "3")) {
-- /* Voiceclip */
-- MsnSession *session;
-- MsnSlpLink *slplink;
-- MsnObject *obj;
-- const char *who;
-- const char *data;
--
-- session = cmdproc->session;
--
-- data = g_hash_table_lookup(body, "Data");
-- obj = msn_object_new_from_string(data);
-- who = msn_object_get_creator(obj);
--
-- slplink = msn_session_get_slplink(session, who);
-- msn_slplink_request_object(slplink, data, got_voiceclip_cb, NULL, obj);
--
-- msn_object_destroy(obj);
--
-- } else if (!strcmp(id, "4")) {
-- /* Action */
--
-- } else {
-- purple_debug_warning("msn", "Got unknown datacast with ID %s.\n", id);
-- }
--
-- g_hash_table_destroy(body);
--}
--
--void
--msn_invite_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
--{
-- GHashTable *body;
-- const gchar *command;
-- const gchar *cookie;
-- gboolean accepted = FALSE;
--
-- g_return_if_fail(cmdproc != NULL);
-- g_return_if_fail(msg != NULL);
--
-- body = msn_message_get_hashtable_from_body(msg);
--
-- if (body == NULL) {
-- purple_debug_warning("msn",
-- "Unable to parse invite msg body.\n");
-- return;
-- }
--
-- /*
-- * GUID is NOT always present but Invitation-Command and Invitation-Cookie
-- * are mandatory.
-- */
-- command = g_hash_table_lookup(body, "Invitation-Command");
-- cookie = g_hash_table_lookup(body, "Invitation-Cookie");
--
-- if (command == NULL || cookie == NULL) {
-- purple_debug_warning("msn",
-- "Invalid invitation message: either Invitation-Command "
-- "or Invitation-Cookie is missing or invalid.\n"
-- );
-- return;
--
-- } else if (!strcmp(command, "INVITE")) {
-- const gchar *guid = g_hash_table_lookup(body, "Application-GUID");
--
-- if (guid == NULL) {
-- purple_debug_warning("msn",
-- "Invite msg missing Application-GUID.\n");
--
-- accepted = TRUE;
--
-- } else if (!strcmp(guid, MSN_FT_GUID)) {
--
-- } else if (!strcmp(guid, "{02D3C01F-BF30-4825-A83A-DE7AF41648AA}")) {
-- purple_debug_info("msn", "Computer call\n");
--
-- if (cmdproc->session) {
-- PurpleConversation *conv = NULL;
-- gchar *from = msg->remote_user;
-- gchar *buf = NULL;
--
-- if (from)
-- conv = purple_find_conversation_with_account(
-- PURPLE_CONV_TYPE_IM, from,
-- cmdproc->session->account);
-- if (conv)
-- buf = g_strdup_printf(
-- _("%s sent you a voice chat "
-- "invite, which is not yet "
-- "supported."), from);
-- if (buf) {
-- purple_conversation_write(conv, NULL, buf,
-- PURPLE_MESSAGE_SYSTEM |
-- PURPLE_MESSAGE_NOTIFY,
-- time(NULL));
-- g_free(buf);
-- }
-- }
-- } else {
-- const gchar *application = g_hash_table_lookup(body, "Application-Name");
-- purple_debug_warning("msn", "Unhandled invite msg with GUID %s: %s.\n",
-- guid, application ? application : "(null)");
-- }
--
-- if (!accepted) {
-- MsnSwitchBoard *swboard = cmdproc->data;
-- char *text;
-- MsnMessage *cancel;
--
-- cancel = msn_message_new(MSN_MSG_TEXT);
-- msn_message_set_content_type(cancel, "text/x-msmsgsinvite");
-- msn_message_set_charset(cancel, "UTF-8");
-- msn_message_set_flag(cancel, 'U');
--
-- text = g_strdup_printf("Invitation-Command: CANCEL\r\n"
-- "Invitation-Cookie: %s\r\n"
-- "Cancel-Code: REJECT_NOT_INSTALLED\r\n",
-- cookie);
-- msn_message_set_bin_data(cancel, text, strlen(text));
-- g_free(text);
--
-- msn_switchboard_send_msg(swboard, cancel, TRUE);
-- msn_message_unref(cancel);
-- }
--
-- } else if (!strcmp(command, "CANCEL")) {
-- const gchar *code = g_hash_table_lookup(body, "Cancel-Code");
-- purple_debug_info("msn", "MSMSGS invitation cancelled: %s.\n",
-- code ? code : "no reason given");
--
-- } else {
-- /*
-- * Some other already established invitation session.
-- * Can be retrieved by Invitation-Cookie.
-- */
-- }
--
-- g_hash_table_destroy(body);
--}
--
--/* Only called from chats. Handwritten messages for IMs come as a SLP message */
--void
--msn_handwritten_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
--{
-- const char *body;
-- size_t body_len;
--
-- body = msn_message_get_bin_data(msg, &body_len);
-- msn_switchboard_show_ink(cmdproc->data, msg->remote_user, body);
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/msg.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/msg.h
---- pidgin-2.10.7/libpurple/protocols/msn/msg.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/msg.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,325 +0,0 @@
--/**
-- * @file msg.h Message functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_MSG_H
--#define MSN_MSG_H
--
--typedef struct _MsnMessage MsnMessage;
--
--/*
--typedef enum
--{
-- MSN_MSG_NORMAL,
-- MSN_MSG_SLP_SB,
-- MSN_MSG_SLP_DC
--} MsnMsgType;
--*/
--
--typedef enum
--{
-- MSN_MSG_UNKNOWN,
-- MSN_MSG_TEXT,
-- MSN_MSG_TYPING,
-- MSN_MSG_CAPS,
-- MSN_MSG_SLP,
-- MSN_MSG_NUDGE
--} MsnMsgType;
--
--typedef enum
--{
-- MSN_MSG_ERROR_NONE, /**< No error. */
-- MSN_MSG_ERROR_TIMEOUT, /**< The message timedout. */
-- MSN_MSG_ERROR_NAK, /**< The message could not be sent. */
-- MSN_MSG_ERROR_SB, /**< The error comes from the switchboard. */
-- MSN_MSG_ERROR_UNKNOWN /**< An unknown error occurred. */
--} MsnMsgErrorType;
--
--#include "command.h"
--#include "session.h"
--#include "transaction.h"
--#include "user.h"
--#include "slpmsg.h"
--#include "slpmsg_part.h"
--
--typedef void (*MsnMsgCb)(MsnMessage *, void *data);
--
--#define MSG_BODY_DEM "\r\n\r\n"
--#define MSG_LINE_DEM "\r\n"
--
--#define MSG_OIM_BODY_DEM "\n\n"
--#define MSG_OIM_LINE_DEM "\n"
--
--/**
-- * A message.
-- */
--struct _MsnMessage
--{
-- guint ref_count; /**< The reference count. */
--
-- MsnMsgType type;
--
-- MsnSlpMessagePart *part;
--
-- char *remote_user;
-- char flag;
--
-- char *content_type;
-- char *charset;
-- char *body;
-- gsize body_len;
-- guint total_chunks; /**< How many chunks in this multi-part message */
-- guint received_chunks; /**< How many chunks we've received so far */
--
-- GHashTable *header_table;
-- GList *header_list;
--
-- gboolean ack_ref; /**< A flag that states if this message has
-- been ref'ed for using it in a callback. */
--
-- MsnCommand *cmd;
--
-- MsnMsgCb ack_cb; /**< The callback to call when we receive an ACK of this
-- message. */
-- MsnMsgCb nak_cb; /**< The callback to call when we receive a NAK of this
-- message. */
-- void *ack_data; /**< The data used by callbacks. */
--
-- guint32 retries;
--};
--
--/**
-- * Creates a new, empty message.
-- *
-- * @return A new message.
-- */
--MsnMessage *msn_message_new(MsnMsgType type);
--
--/**
-- * Creates a new, empty MSNSLP message.
-- *
-- * @return A new MSNSLP message.
-- */
--MsnMessage *msn_message_new_msnslp(void);
--
--/**
-- * Creates a new nudge message.
-- *
-- * @return A new nudge message.
-- */
--MsnMessage *msn_message_new_nudge(void);
--
--/**
-- * Creates a new plain message.
-- *
-- * @return A new plain message.
-- */
--MsnMessage *msn_message_new_plain(const char *message);
--
--/**
-- * Creates a new message based off a command.
-- *
-- * @param session The MSN session.
-- * @param cmd The command.
-- *
-- * @return The new message.
-- */
--MsnMessage *msn_message_new_from_cmd(MsnSession *session, MsnCommand *cmd);
--
--/**
-- * Parses the payload of a message.
-- *
-- * @param msg The message.
-- * @param payload The payload.
-- * @param payload_len The length of the payload.
-- */
--void msn_message_parse_payload(MsnMessage *msg, const char *payload,
-- size_t payload_len,
-- const char *line_dem,const char *body_dem);
--
--/**
-- * Increments the reference count on a message.
-- *
-- * @param msg The message.
-- *
-- * @return @a msg
-- */
--MsnMessage *msn_message_ref(MsnMessage *msg);
--
--/**
-- * Decrements the reference count on a message.
-- *
-- * This will destroy the structure if the count hits 0.
-- *
-- * @param msg The message.
-- *
-- * @return @a msg, or @c NULL if the new count is 0.
-- */
--void msn_message_unref(MsnMessage *msg);
--
--/**
-- * Generates the payload data of a message.
-- *
-- * @param msg The message.
-- * @param ret_size The returned size of the payload.
-- *
-- * @return The payload data of the message.
-- */
--char *msn_message_gen_payload(MsnMessage *msg, size_t *ret_size);
--
--/**
-- * Sets the flag for an outgoing message.
-- *
-- * @param msg The message.
-- * @param flag The flag.
-- */
--void msn_message_set_flag(MsnMessage *msg, char flag);
--
--/**
-- * Returns the flag for an outgoing message.
-- *
-- * @param msg The message.
-- *
-- * @return The flag.
-- */
--char msn_message_get_flag(const MsnMessage *msg);
--
--/**
-- * Sets the binary content of the message.
-- *
-- * @param msg The message.
-- * @param data The binary data.
-- * @param len The length of the data.
-- */
--void msn_message_set_bin_data(MsnMessage *msg, const void *data, size_t len);
--
--/**
-- * Returns the binary content of the message.
-- *
-- * @param msg The message.
-- * @param len The returned length of the data.
-- *
-- * @return The binary data.
-- */
--const void *msn_message_get_bin_data(const MsnMessage *msg, size_t *len);
--
--/**
-- * Sets the content type in a message.
-- *
-- * @param msg The message.
-- * @param type The content-type.
-- */
--void msn_message_set_content_type(MsnMessage *msg, const char *type);
--
--/**
-- * Returns the content type in a message.
-- *
-- * @param msg The message.
-- *
-- * @return The content-type.
-- */
--const char *msn_message_get_content_type(const MsnMessage *msg);
--
--/**
-- * Sets the charset in a message.
-- *
-- * @param msg The message.
-- * @param charset The charset.
-- */
--void msn_message_set_charset(MsnMessage *msg, const char *charset);
--
--/**
-- * Returns the charset in a message.
-- *
-- * @param msg The message.
-- *
-- * @return The charset.
-- */
--const char *msn_message_get_charset(const MsnMessage *msg);
--
--/**
-- * Sets a header in a message.
-- *
-- * @param msg The message.
-- * @param header The header name.
-- * @param value The header value.
-- */
--void msn_message_set_header(MsnMessage *msg, const char *name,
-- const char *value);
--
--/**
-- * Returns the value of a header from a message.
-- *
-- * @param msg The message.
-- * @param header The header value.
-- *
-- * @return The value, or @c NULL if not found.
-- */
--const char *msn_message_get_header_value(const MsnMessage *msg, const char *name);
--
--/**
-- * Parses the body and returns it in the form of a hashtable.
-- *
-- * @param msg The message.
-- *
-- * @return The resulting hashtable.
-- */
--GHashTable *msn_message_get_hashtable_from_body(const MsnMessage *msg);
--
--void msn_message_show_readable(MsnMessage *msg, const char *info,
-- gboolean text_body);
--
--char *msn_message_to_string(MsnMessage *msg);
--
--void msn_plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
--
--void msn_control_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
--
--/**
-- * Processes peer to peer messages.
-- *
-- * @param cmdproc The command processor.
-- * @param msg The message.
-- */
--void msn_p2p_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
--
--/**
-- * Processes emoticon messages.
-- *
-- * @param cmdproc The command processor.
-- * @param msg The message.
-- */
--void msn_emoticon_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
--
--void msn_datacast_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
--
--/**
-- * Processes INVITE messages.
-- *
-- * @param cmdproc The command processor.
-- * @param msg The message.
-- */
--void msn_invite_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
--
--void msn_handwritten_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
--
--#endif /* MSN_MSG_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/msn.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/msn.c
---- pidgin-2.10.7/libpurple/protocols/msn/msn.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/msn.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,3070 +0,0 @@
--/**
-- * @file msn.c The MSN protocol plugin
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#define PHOTO_SUPPORT 1
--
--#include "internal.h"
--
--#include "debug.h"
--#include "request.h"
--
--#include "accountopt.h"
--#include "contact.h"
--#include "msg.h"
--#include "page.h"
--#include "pluginpref.h"
--#include "prefs.h"
--#include "session.h"
--#include "smiley.h"
--#include "state.h"
--#include "util.h"
--#include "cmds.h"
--#include "core.h"
--#include "prpl.h"
--#include "msnutils.h"
--#include "version.h"
--
--#include "error.h"
--#include "msg.h"
--#include "switchboard.h"
--#include "notification.h"
--#include "slplink.h"
--
--#if PHOTO_SUPPORT
--#define MAX_HTTP_BUDDYICON_BYTES (200 * 1024)
--#include "imgstore.h"
--#endif
--
--typedef struct
--{
-- PurpleConnection *gc;
-- const char *passport;
--
--} MsnMobileData;
--
--typedef struct
--{
-- PurpleConnection *gc;
-- char *name;
--
--} MsnGetInfoData;
--
--typedef struct
--{
-- MsnGetInfoData *info_data;
-- char *stripped;
-- char *url_buffer;
-- PurpleNotifyUserInfo *user_info;
-- char *photo_url_text;
--
--} MsnGetInfoStepTwoData;
--
--typedef struct
--{
-- PurpleConnection *gc;
-- const char *who;
-- char *msg;
-- PurpleMessageFlags flags;
-- time_t when;
--} MsnIMData;
--
--typedef struct
--{
-- char *smile;
-- PurpleSmiley *ps;
-- MsnObject *obj;
--} MsnEmoticon;
--
--static const char *
--msn_normalize(const PurpleAccount *account, const char *str)
--{
-- static char buf[BUF_LEN];
-- char *tmp;
--
-- g_return_val_if_fail(str != NULL, NULL);
--
-- tmp = g_strchomp(g_utf8_strdown(str, -1));
-- g_snprintf(buf, sizeof(buf), "%s%s", tmp,
-- (strchr(tmp, '@') ? "" : "@hotmail.com"));
-- g_free(tmp);
--
-- return buf;
--}
--
--static gboolean
--msn_send_attention(PurpleConnection *gc, const char *username, guint type)
--{
-- MsnMessage *msg;
-- MsnSession *session;
-- MsnSwitchBoard *swboard;
--
-- msg = msn_message_new_nudge();
-- session = gc->proto_data;
-- swboard = msn_session_get_swboard(session, username, MSN_SB_FLAG_IM);
--
-- msn_switchboard_send_msg(swboard, msg, TRUE);
-- msn_message_unref(msg);
--
-- return TRUE;
--}
--
--static GList *
--msn_attention_types(PurpleAccount *account)
--{
-- static GList *list = NULL;
--
-- if (!list) {
-- list = g_list_append(list, purple_attention_type_new("Nudge", _("Nudge"),
-- _("%s has nudged you!"), _("Nudging %s...")));
-- }
--
-- return list;
--}
--
--static GHashTable *
--msn_get_account_text_table(PurpleAccount *unused)
--{
-- GHashTable *table;
--
-- table = g_hash_table_new(g_str_hash, g_str_equal);
--
-- g_hash_table_insert(table, "login_label", (gpointer)_("Email Address..."));
--
-- return table;
--}
--
--static PurpleCmdRet
--msn_cmd_nudge(PurpleConversation *conv, const gchar *cmd, gchar **args, gchar **error, void *data)
--{
-- PurpleAccount *account = purple_conversation_get_account(conv);
-- PurpleConnection *gc = purple_account_get_connection(account);
-- const gchar *username;
--
-- username = purple_conversation_get_name(conv);
--
-- purple_prpl_send_attention(gc, username, MSN_NUDGE);
--
-- return PURPLE_CMD_RET_OK;
--}
--
--struct public_alias_closure
--{
-- PurpleAccount *account;
-- gpointer success_cb;
-- gpointer failure_cb;
--};
--
--static gboolean
--set_public_alias_length_error(gpointer data)
--{
-- struct public_alias_closure *closure = data;
-- PurpleSetPublicAliasFailureCallback failure_cb = closure->failure_cb;
--
-- failure_cb(closure->account, _("Your new MSN friendly name is too long."));
-- g_free(closure);
--
-- return FALSE;
--}
--
--static void
--prp_success_cb(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- const char *type, *friendlyname;
-- struct public_alias_closure *closure;
--
-- g_return_if_fail(cmd->param_count >= 3);
-- type = cmd->params[1];
-- g_return_if_fail(!strcmp(type, "MFN"));
--
-- closure = cmd->trans->data;
-- friendlyname = purple_url_decode(cmd->params[2]);
--
-- msn_update_contact(cmdproc->session, "Me", MSN_UPDATE_DISPLAY, friendlyname);
--
-- purple_connection_set_display_name(
-- purple_account_get_connection(closure->account),
-- friendlyname);
-- purple_account_set_string(closure->account, "display-name", friendlyname);
--
-- if (closure->success_cb) {
-- PurpleSetPublicAliasSuccessCallback success_cb = closure->success_cb;
-- success_cb(closure->account, friendlyname);
-- }
--}
--
--static void
--prp_error_cb(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
--{
-- struct public_alias_closure *closure = trans->data;
-- PurpleSetPublicAliasFailureCallback failure_cb = closure->failure_cb;
-- gboolean debug;
-- const char *error_text;
--
-- error_text = msn_error_get_text(error, &debug);
-- failure_cb(closure->account, error_text);
--}
--
--static void
--prp_timeout_cb(MsnCmdProc *cmdproc, MsnTransaction *trans)
--{
-- struct public_alias_closure *closure = trans->data;
-- PurpleSetPublicAliasFailureCallback failure_cb = closure->failure_cb;
-- failure_cb(closure->account, _("Connection Timeout"));
--}
--
--void
--msn_set_public_alias(PurpleConnection *pc, const char *alias,
-- PurpleSetPublicAliasSuccessCallback success_cb,
-- PurpleSetPublicAliasFailureCallback failure_cb)
--{
-- MsnCmdProc *cmdproc;
-- MsnSession *session;
-- MsnTransaction *trans;
-- PurpleAccount *account;
-- char real_alias[BUDDY_ALIAS_MAXLEN + 1];
-- struct public_alias_closure *closure;
--
-- session = purple_connection_get_protocol_data(pc);
-- cmdproc = session->notification->cmdproc;
-- account = purple_connection_get_account(pc);
--
-- if (alias && *alias) {
-- if (!msn_encode_spaces(alias, real_alias, BUDDY_ALIAS_MAXLEN + 1)) {
-- if (failure_cb) {
-- struct public_alias_closure *closure =
-- g_new0(struct public_alias_closure, 1);
-- closure->account = account;
-- closure->failure_cb = failure_cb;
-- purple_timeout_add(0, set_public_alias_length_error, closure);
-- } else {
-- purple_notify_error(pc, NULL,
-- _("Your new MSN friendly name is too long."),
-- NULL);
-- }
-- return;
-- }
--
-- if (real_alias[0] == '\0')
-- g_strlcpy(real_alias, purple_account_get_username(account), sizeof(real_alias));
-- } else
-- g_strlcpy(real_alias, purple_account_get_username(account), sizeof(real_alias));
--
-- closure = g_new0(struct public_alias_closure, 1);
-- closure->account = account;
-- closure->success_cb = success_cb;
-- closure->failure_cb = failure_cb;
--
-- trans = msn_transaction_new(cmdproc, "PRP", "MFN %s", real_alias);
-- msn_transaction_set_data(trans, closure);
-- msn_transaction_set_data_free(trans, g_free);
-- msn_transaction_add_cb(trans, "PRP", prp_success_cb);
-- if (failure_cb) {
-- msn_transaction_set_error_cb(trans, prp_error_cb);
-- msn_transaction_set_timeout_cb(trans, prp_timeout_cb);
-- }
-- msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--static gboolean
--get_public_alias_cb(gpointer data)
--{
-- struct public_alias_closure *closure = data;
-- PurpleGetPublicAliasSuccessCallback success_cb = closure->success_cb;
-- const char *alias;
--
-- alias = purple_account_get_string(closure->account, "display-name",
-- purple_account_get_username(closure->account));
-- success_cb(closure->account, alias);
-- g_free(closure);
--
-- return FALSE;
--}
--
--static void
--msn_get_public_alias(PurpleConnection *pc,
-- PurpleGetPublicAliasSuccessCallback success_cb,
-- PurpleGetPublicAliasFailureCallback failure_cb)
--{
-- struct public_alias_closure *closure = g_new0(struct public_alias_closure, 1);
-- PurpleAccount *account = purple_connection_get_account(pc);
--
-- closure->account = account;
-- closure->success_cb = success_cb;
-- purple_timeout_add(0, get_public_alias_cb, closure);
--}
--
--static void
--msn_act_id(PurpleConnection *gc, const char *entry)
--{
-- msn_set_public_alias(gc, entry, NULL, NULL);
--}
--
--static void
--msn_set_prp(PurpleConnection *gc, const char *type, const char *entry)
--{
-- MsnCmdProc *cmdproc;
-- MsnSession *session;
-- MsnTransaction *trans;
--
-- session = gc->proto_data;
-- cmdproc = session->notification->cmdproc;
--
-- if (entry == NULL || *entry == '\0')
-- {
-- trans = msn_transaction_new(cmdproc, "PRP", "%s", type);
-- }
-- else
-- {
-- trans = msn_transaction_new(cmdproc, "PRP", "%s %s", type,
-- purple_url_encode(entry));
-- }
-- msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--static void
--msn_set_home_phone_cb(PurpleConnection *gc, const char *entry)
--{
-- msn_set_prp(gc, "PHH", entry);
--}
--
--static void
--msn_set_work_phone_cb(PurpleConnection *gc, const char *entry)
--{
-- msn_set_prp(gc, "PHW", entry);
--}
--
--static void
--msn_set_mobile_phone_cb(PurpleConnection *gc, const char *entry)
--{
-- msn_set_prp(gc, "PHM", entry);
--}
--
--static void
--enable_msn_pages_cb(PurpleConnection *gc)
--{
-- msn_set_prp(gc, "MOB", "Y");
--}
--
--static void
--disable_msn_pages_cb(PurpleConnection *gc)
--{
-- msn_set_prp(gc, "MOB", "N");
--}
--
--static void
--send_to_mobile(PurpleConnection *gc, const char *who, const char *entry)
--{
-- MsnTransaction *trans;
-- MsnSession *session;
-- MsnCmdProc *cmdproc;
-- MsnPage *page;
-- MsnMessage *msg;
-- MsnUser *user;
-- char *payload = NULL;
-- const char *mobile_number = NULL;
-- gsize payload_len;
--
-- session = gc->proto_data;
-- cmdproc = session->notification->cmdproc;
--
-- page = msn_page_new();
-- msn_page_set_body(page, entry);
--
-- payload = msn_page_gen_payload(page, &payload_len);
--
-- if ((user = msn_userlist_find_user(session->userlist, who)) &&
-- (mobile_number = msn_user_get_mobile_phone(user)) &&
-- mobile_number[0] == '+') {
-- /* if msn_user_get_mobile_phone() has a + in front, it's a number
-- that from the buddy's contact card */
-- trans = msn_transaction_new(cmdproc, "PGD", "tel:%s 1 %" G_GSIZE_FORMAT,
-- mobile_number, payload_len);
-- } else {
-- /* otherwise we send to whatever phone number the buddy registered
-- with msn */
-- trans = msn_transaction_new(cmdproc, "PGD", "%s 1 %" G_GSIZE_FORMAT,
-- who, payload_len);
-- }
--
-- msn_transaction_set_payload(trans, payload, payload_len);
-- g_free(payload);
--
-- msg = msn_message_new_plain(entry);
-- msn_transaction_set_data(trans, msg);
--
-- msn_page_destroy(page);
--
-- msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--static void
--send_to_mobile_cb(MsnMobileData *data, const char *entry)
--{
-- send_to_mobile(data->gc, data->passport, entry);
-- g_free(data);
--}
--
--static void
--close_mobile_page_cb(MsnMobileData *data, const char *entry)
--{
-- g_free(data);
--}
--
--/* -- */
--
--static void
--msn_show_set_friendly_name(PurplePluginAction *action)
--{
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- char *tmp;
--
-- gc = (PurpleConnection *) action->context;
-- account = purple_connection_get_account(gc);
--
-- tmp = g_strdup_printf(_("Set friendly name for %s."),
-- purple_account_get_username(account));
-- purple_request_input(gc, _("Set Friendly Name"), tmp,
-- _("This is the name that other MSN buddies will "
-- "see you as."),
-- purple_connection_get_display_name(gc), FALSE, FALSE, NULL,
-- _("OK"), G_CALLBACK(msn_act_id),
-- _("Cancel"), NULL,
-- account, NULL, NULL,
-- gc);
-- g_free(tmp);
--}
--
--typedef struct MsnLocationData {
-- PurpleAccount *account;
-- MsnSession *session;
-- PurpleRequestFieldGroup *group;
--} MsnLocationData;
--
--static void
--update_endpoint_cb(MsnLocationData *data, PurpleRequestFields *fields)
--{
-- PurpleAccount *account;
-- MsnSession *session;
-- const char *old_name;
-- const char *name;
-- GList *others;
--
-- session = data->session;
-- account = data->account;
--
-- /* Update the current location's name */
-- old_name = purple_account_get_string(account, "endpoint-name", NULL);
-- name = purple_request_fields_get_string(fields, "endpoint-name");
-- if (!g_str_equal(old_name, name)) {
-- purple_account_set_string(account, "endpoint-name", name);
-- msn_notification_send_uux_private_endpointdata(session);
-- }
--
-- /* Sign out other locations */
-- for (others = purple_request_field_group_get_fields(data->group);
-- others;
-- others = g_list_next(others)) {
-- PurpleRequestField *field = others->data;
-- if (purple_request_field_get_type(field) != PURPLE_REQUEST_FIELD_BOOLEAN)
-- continue;
-- if (purple_request_field_bool_get_value(field)) {
-- const char *id = purple_request_field_get_id(field);
-- char *user;
-- purple_debug_info("msn", "Disconnecting Endpoint %s\n", id);
--
-- user = g_strdup_printf("%s;%s", purple_account_get_username(account), id);
-- msn_notification_send_uun(session, user, MSN_UNIFIED_NOTIFICATION_MPOP, "goawyplzthxbye");
-- g_free(user);
-- }
-- }
--
-- g_free(data);
--}
--
--static void
--msn_show_locations(PurplePluginAction *action)
--{
-- PurpleConnection *pc;
-- PurpleAccount *account;
-- MsnSession *session;
-- PurpleRequestFields *fields;
-- PurpleRequestFieldGroup *group;
-- PurpleRequestField *field;
-- gboolean have_other_endpoints;
-- GSList *l;
-- MsnLocationData *data;
--
-- pc = (PurpleConnection *)action->context;
-- account = purple_connection_get_account(pc);
-- session = purple_connection_get_protocol_data(pc);
--
-- fields = purple_request_fields_new();
--
-- group = purple_request_field_group_new(_("This Location"));
-- purple_request_fields_add_group(fields, group);
-- field = purple_request_field_label_new("endpoint-label", _("This is the name that identifies this location"));
-- purple_request_field_group_add_field(group, field);
-- field = purple_request_field_string_new("endpoint-name",
-- _("Name"),
-- purple_account_get_string(account, "endpoint-name", NULL),
-- FALSE);
-- purple_request_field_set_required(field, TRUE);
-- purple_request_field_group_add_field(group, field);
--
-- group = purple_request_field_group_new(_("Other Locations"));
-- purple_request_fields_add_group(fields, group);
--
-- have_other_endpoints = FALSE;
-- for (l = session->user->endpoints; l; l = l->next) {
-- MsnUserEndpoint *ep = l->data;
--
-- if (ep->id[0] != '\0' && strncasecmp(ep->id + 1, session->guid, 36) == 0)
-- /* Don't add myself to the list */
-- continue;
--
-- if (!have_other_endpoints) {
-- /* We do in fact have an endpoint other than ourselves... let's
-- add a label */
-- field = purple_request_field_label_new("others-label",
-- _("You can sign out from other locations here"));
-- purple_request_field_group_add_field(group, field);
-- }
--
-- have_other_endpoints = TRUE;
-- field = purple_request_field_bool_new(ep->id, ep->name, FALSE);
-- purple_request_field_group_add_field(group, field);
-- }
-- if (!have_other_endpoints) {
-- /* TODO: Due to limitations in our current request field API, the
-- following string will show up with a trailing colon. This should
-- be fixed either by adding an "include_colon" boolean, or creating
-- a separate purple_request_field_label_new_without_colon function,
-- or by never automatically adding the colon and requiring that
-- callers add the colon themselves. */
-- field = purple_request_field_label_new("others-label", _("You are not signed in from any other locations."));
-- purple_request_field_group_add_field(group, field);
-- }
--
-- data = g_new0(MsnLocationData, 1);
-- data->account = account;
-- data->session = session;
-- data->group = group;
--
-- purple_request_fields(pc, NULL, NULL, NULL,
-- fields,
-- _("OK"), G_CALLBACK(update_endpoint_cb),
-- _("Cancel"), G_CALLBACK(g_free),
-- account, NULL, NULL,
-- data);
--}
--
--static void
--enable_mpop_cb(PurpleConnection *pc)
--{
-- MsnSession *session = purple_connection_get_protocol_data(pc);
--
-- purple_debug_info("msn", "Enabling MPOP\n");
--
-- session->enable_mpop = TRUE;
-- msn_annotate_contact(session, "Me", "MSN.IM.MPOP", "1", NULL);
--
-- purple_prpl_got_account_actions(purple_connection_get_account(pc));
--}
--
--static void
--disable_mpop_cb(PurpleConnection *pc)
--{
-- PurpleAccount *account = purple_connection_get_account(pc);
-- MsnSession *session = purple_connection_get_protocol_data(pc);
-- GSList *l;
--
-- purple_debug_info("msn", "Disabling MPOP\n");
--
-- session->enable_mpop = FALSE;
-- msn_annotate_contact(session, "Me", "MSN.IM.MPOP", "0", NULL);
--
-- for (l = session->user->endpoints; l; l = l->next) {
-- MsnUserEndpoint *ep = l->data;
-- char *user;
--
-- if (ep->id[0] != '\0' && strncasecmp(ep->id + 1, session->guid, 36) == 0)
-- /* Don't kick myself */
-- continue;
--
-- purple_debug_info("msn", "Disconnecting Endpoint %s\n", ep->id);
--
-- user = g_strdup_printf("%s;%s", purple_account_get_username(account), ep->id);
-- msn_notification_send_uun(session, user, MSN_UNIFIED_NOTIFICATION_MPOP, "goawyplzthxbye");
-- g_free(user);
-- }
--
-- purple_prpl_got_account_actions(account);
--}
--
--static void
--msn_show_set_mpop(PurplePluginAction *action)
--{
-- PurpleConnection *pc;
--
-- pc = (PurpleConnection *)action->context;
--
-- purple_request_action(pc, NULL, _("Allow multiple logins?"),
-- _("Do you want to allow or disallow connecting from "
-- "multiple locations simultaneously?"),
-- PURPLE_DEFAULT_ACTION_NONE,
-- purple_connection_get_account(pc), NULL, NULL,
-- pc, 3,
-- _("Allow"), G_CALLBACK(enable_mpop_cb),
-- _("Disallow"), G_CALLBACK(disable_mpop_cb),
-- _("Cancel"), NULL);
--}
--
--static void
--msn_show_set_home_phone(PurplePluginAction *action)
--{
-- PurpleConnection *gc;
-- MsnSession *session;
--
-- gc = (PurpleConnection *) action->context;
-- session = gc->proto_data;
--
-- purple_request_input(gc, NULL, _("Set your home phone number."), NULL,
-- msn_user_get_home_phone(session->user), FALSE, FALSE, NULL,
-- _("OK"), G_CALLBACK(msn_set_home_phone_cb),
-- _("Cancel"), NULL,
-- purple_connection_get_account(gc), NULL, NULL,
-- gc);
--}
--
--static void
--msn_show_set_work_phone(PurplePluginAction *action)
--{
-- PurpleConnection *gc;
-- MsnSession *session;
--
-- gc = (PurpleConnection *) action->context;
-- session = gc->proto_data;
--
-- purple_request_input(gc, NULL, _("Set your work phone number."), NULL,
-- msn_user_get_work_phone(session->user), FALSE, FALSE, NULL,
-- _("OK"), G_CALLBACK(msn_set_work_phone_cb),
-- _("Cancel"), NULL,
-- purple_connection_get_account(gc), NULL, NULL,
-- gc);
--}
--
--static void
--msn_show_set_mobile_phone(PurplePluginAction *action)
--{
-- PurpleConnection *gc;
-- MsnSession *session;
--
-- gc = (PurpleConnection *) action->context;
-- session = gc->proto_data;
--
-- purple_request_input(gc, NULL, _("Set your mobile phone number."), NULL,
-- msn_user_get_mobile_phone(session->user), FALSE, FALSE, NULL,
-- _("OK"), G_CALLBACK(msn_set_mobile_phone_cb),
-- _("Cancel"), NULL,
-- purple_connection_get_account(gc), NULL, NULL,
-- gc);
--}
--
--static void
--msn_show_set_mobile_pages(PurplePluginAction *action)
--{
-- PurpleConnection *gc;
--
-- gc = (PurpleConnection *) action->context;
--
-- purple_request_action(gc, NULL, _("Allow MSN Mobile pages?"),
-- _("Do you want to allow or disallow people on "
-- "your buddy list to send you MSN Mobile pages "
-- "to your cell phone or other mobile device?"),
-- PURPLE_DEFAULT_ACTION_NONE,
-- purple_connection_get_account(gc), NULL, NULL,
-- gc, 3,
-- _("Allow"), G_CALLBACK(enable_msn_pages_cb),
-- _("Disallow"), G_CALLBACK(disable_msn_pages_cb),
-- _("Cancel"), NULL);
--}
--
--/* QuLogic: Disabled until confirmed correct. */
--#if 0
--static void
--msn_show_blocked_text(PurplePluginAction *action)
--{
-- PurpleConnection *pc = (PurpleConnection *) action->context;
-- MsnSession *session;
-- char *title;
--
-- session = pc->proto_data;
--
-- title = g_strdup_printf(_("Blocked Text for %s"), session->account->username);
-- if (session->blocked_text == NULL) {
-- purple_notify_formatted(pc, title, title, NULL, _("No text is blocked for this account."), NULL, NULL);
-- } else {
-- char *blocked_text;
-- blocked_text = g_strdup_printf(_("MSN servers are currently blocking the following regular expressions:<br/>%s"),
-- session->blocked_text);
--
-- purple_notify_formatted(pc, title, title, NULL, blocked_text, NULL, NULL);
-- g_free(blocked_text);
-- }
-- g_free(title);
--}
--#endif
--
--static void
--msn_show_hotmail_inbox(PurplePluginAction *action)
--{
-- PurpleConnection *gc;
-- MsnSession *session;
--
-- gc = (PurpleConnection *) action->context;
-- session = gc->proto_data;
--
-- if (!session->passport_info.email_enabled) {
-- purple_notify_error(gc, NULL,
-- _("This account does not have email enabled."), NULL);
-- return;
-- }
--
-- /** apparently the correct value is 777, use 750 as a failsafe */
-- if ((session->passport_info.mail_url == NULL)
-- || (time (NULL) - session->passport_info.mail_timestamp >= 750)) {
-- MsnTransaction *trans;
-- MsnCmdProc *cmdproc;
--
-- cmdproc = session->notification->cmdproc;
--
-- trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
-- msn_transaction_set_data(trans, GUINT_TO_POINTER(TRUE));
--
-- msn_cmdproc_send_trans(cmdproc, trans);
--
-- } else
-- purple_notify_uri(gc, session->passport_info.mail_url);
--}
--
--static void
--show_send_to_mobile_cb(PurpleBlistNode *node, gpointer ignored)
--{
-- PurpleBuddy *buddy;
-- PurpleConnection *gc;
-- MsnMobileData *data;
-- PurpleAccount *account;
-- const char *name;
--
-- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
--
-- buddy = (PurpleBuddy *) node;
-- account = purple_buddy_get_account(buddy);
-- gc = purple_account_get_connection(account);
-- name = purple_buddy_get_name(buddy);
--
-- data = g_new0(MsnMobileData, 1);
-- data->gc = gc;
-- data->passport = name;
--
-- purple_request_input(gc, NULL, _("Send a mobile message."), NULL,
-- NULL, TRUE, FALSE, NULL,
-- _("Page"), G_CALLBACK(send_to_mobile_cb),
-- _("Close"), G_CALLBACK(close_mobile_page_cb),
-- account, name, NULL,
-- data);
--}
--
--static gboolean
--msn_offline_message(const PurpleBuddy *buddy) {
-- return TRUE;
--}
--
--void
--msn_send_privacy(PurpleConnection *gc)
--{
-- PurpleAccount *account;
-- MsnSession *session;
-- MsnCmdProc *cmdproc;
-- MsnTransaction *trans;
--
-- account = purple_connection_get_account(gc);
-- session = gc->proto_data;
-- cmdproc = session->notification->cmdproc;
--
-- if (account->perm_deny == PURPLE_PRIVACY_ALLOW_ALL ||
-- account->perm_deny == PURPLE_PRIVACY_DENY_USERS)
-- trans = msn_transaction_new(cmdproc, "BLP", "%s", "AL");
-- else
-- trans = msn_transaction_new(cmdproc, "BLP", "%s", "BL");
--
-- msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--static void
--initiate_chat_cb(PurpleBlistNode *node, gpointer data)
--{
-- PurpleBuddy *buddy;
-- PurpleConnection *gc;
-- PurpleAccount *account;
--
-- MsnSession *session;
-- MsnSwitchBoard *swboard;
--
-- const char *alias;
--
-- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
--
-- buddy = (PurpleBuddy *) node;
-- account = purple_buddy_get_account(buddy);
-- gc = purple_account_get_connection(account);
--
-- session = gc->proto_data;
--
-- swboard = msn_switchboard_new(session);
-- msn_switchboard_request(swboard);
-- msn_switchboard_request_add_user(swboard, purple_buddy_get_name(buddy));
--
-- /* TODO: This might move somewhere else, after USR might be */
-- swboard->chat_id = msn_switchboard_get_chat_id();
-- swboard->conv = serv_got_joined_chat(gc, swboard->chat_id, "MSN Chat");
-- swboard->flag = MSN_SB_FLAG_IM;
--
-- /* Local alias > Display name > Username */
-- if ((alias = purple_account_get_alias(account)) == NULL)
-- if ((alias = purple_connection_get_display_name(gc)) == NULL)
-- alias = purple_account_get_username(account);
--
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv),
-- alias, NULL, PURPLE_CBFLAGS_NONE, TRUE);
--}
--
--static void
--t_msn_xfer_init(PurpleXfer *xfer)
--{
-- msn_request_ft(xfer);
--}
--
--static void
--t_msn_xfer_cancel_send(PurpleXfer *xfer)
--{
-- MsnSlpLink *slplink = xfer->data;
-- msn_slplink_unref(slplink);
--}
--
--static PurpleXfer*
--msn_new_xfer(PurpleConnection *gc, const char *who)
--{
-- MsnSession *session;
-- PurpleXfer *xfer;
--
-- session = gc->proto_data;
--
-- xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who);
--
-- g_return_val_if_fail(xfer != NULL, NULL);
--
-- xfer->data = msn_slplink_ref(msn_session_get_slplink(session, who));
--
-- purple_xfer_set_init_fnc(xfer, t_msn_xfer_init);
-- purple_xfer_set_cancel_send_fnc(xfer, t_msn_xfer_cancel_send);
--
-- return xfer;
--}
--
--static void
--msn_send_file(PurpleConnection *gc, const char *who, const char *file)
--{
-- PurpleXfer *xfer = msn_new_xfer(gc, who);
--
-- if (file)
-- purple_xfer_request_accepted(xfer, file);
-- else
-- purple_xfer_request(xfer);
--}
--
--static gboolean
--msn_can_receive_file(PurpleConnection *gc, const char *who)
--{
-- PurpleAccount *account;
-- gchar *normal;
-- gboolean ret;
--
-- account = purple_connection_get_account(gc);
--
-- normal = g_strdup(msn_normalize(account, purple_account_get_username(account)));
-- ret = strcmp(normal, msn_normalize(account, who));
-- g_free(normal);
--
-- if (ret) {
-- MsnSession *session = gc->proto_data;
-- if (session) {
-- MsnUser *user = msn_userlist_find_user(session->userlist, who);
-- if (user) {
-- /* Include these too: MSN_CAP_MOBILE_ON|MSN_CAP_WEB_WATCH ? */
-- if ((user->clientid & MSN_CAP_VIA_WEBIM) ||
-- user->networkid == MSN_NETWORK_YAHOO)
-- ret = FALSE;
-- else
-- ret = TRUE;
-- }
-- } else
-- ret = FALSE;
-- }
--
-- return ret;
--}
--
--/**************************************************************************
-- * Protocol Plugin ops
-- **************************************************************************/
--
--static const char *
--msn_list_icon(PurpleAccount *a, PurpleBuddy *b)
--{
-- return "msn";
--}
--
--static const char *
--msn_list_emblems(PurpleBuddy *b)
--{
-- MsnUser *user = purple_buddy_get_protocol_data(b);
--
-- if (user != NULL) {
-- if (user->clientid & MSN_CAP_BOT)
-- return "bot";
-- if (user->clientid & MSN_CAP_VIA_MOBILE)
-- return "mobile";
--#if 0
-- /* XXX: Since we don't support this, there's no point in showing it just yet */
-- if (user->clientid & MSN_CAP_SCHANNEL)
-- return "secure";
--#endif
-- if (user->clientid & MSN_CAP_VIA_WEBIM)
-- return "external";
-- if (user->networkid == MSN_NETWORK_YAHOO)
-- return "yahoo";
-- }
--
-- return NULL;
--}
--
--/*
-- * Set the User status text
-- */
--static char *
--msn_status_text(PurpleBuddy *buddy)
--{
-- PurplePresence *presence;
-- PurpleStatus *status;
-- const char *msg;
--
-- presence = purple_buddy_get_presence(buddy);
-- status = purple_presence_get_active_status(presence);
--
-- /* Official client says media takes precedence over message */
-- /* I say message take precedence over media! Plus prpl-jabber agrees
-- too */
-- msg = purple_status_get_attr_string(status, "message");
-- if (msg && *msg)
-- return g_markup_escape_text(msg, -1);
--
-- if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
-- const char *title, *game, *office;
-- char *media, *esc;
-- status = purple_presence_get_status(presence, "tune");
-- title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
--
-- game = purple_status_get_attr_string(status, "game");
-- office = purple_status_get_attr_string(status, "office");
--
-- if (title && *title) {
-- const char *artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
-- const char *album = purple_status_get_attr_string(status, PURPLE_TUNE_ALBUM);
-- media = purple_util_format_song_info(title, artist, album, NULL);
-- return media;
-- }
-- else if (game && *game)
-- media = g_strdup_printf("Playing %s", game);
-- else if (office && *office)
-- media = g_strdup_printf("Editing %s", office);
-- else
-- return NULL;
-- esc = g_markup_escape_text(media, -1);
-- g_free(media);
-- return esc;
-- }
--
-- return NULL;
--}
--
--static void
--msn_tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full)
--{
-- MsnUser *user;
-- PurplePresence *presence = purple_buddy_get_presence(buddy);
-- PurpleStatus *status = purple_presence_get_active_status(presence);
--
-- user = purple_buddy_get_protocol_data(buddy);
--
-- if (purple_presence_is_online(presence))
-- {
-- const char *psm, *name;
-- const char *mediatype = NULL;
-- char *currentmedia = NULL;
--
-- psm = purple_status_get_attr_string(status, "message");
-- if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
-- PurpleStatus *tune = purple_presence_get_status(presence, "tune");
-- const char *title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE);
-- const char *game = purple_status_get_attr_string(tune, "game");
-- const char *office = purple_status_get_attr_string(tune, "office");
-- if (title && *title) {
-- const char *artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST);
-- const char *album = purple_status_get_attr_string(tune, PURPLE_TUNE_ALBUM);
-- mediatype = _("Now Listening");
-- currentmedia = purple_util_format_song_info(title, artist, album, NULL);
-- } else if (game && *game) {
-- mediatype = _("Playing a game");
-- currentmedia = g_strdup(game);
-- } else if (office && *office) {
-- mediatype = _("Working");
-- currentmedia = g_strdup(office);
-- }
-- }
--
-- if (!purple_status_is_available(status)) {
-- name = purple_status_get_name(status);
-- } else {
-- name = NULL;
-- }
--
-- if (name != NULL && *name) {
-- char *tmp2;
--
-- tmp2 = g_markup_escape_text(name, -1);
-- if (purple_presence_is_idle(presence)) {
-- char *idle;
-- char *tmp3;
-- /* Never know what those translations might end up like... */
-- idle = g_markup_escape_text(_("Idle"), -1);
-- tmp3 = g_strdup_printf("%s/%s", tmp2, idle);
-- g_free(idle);
-- g_free(tmp2);
-- tmp2 = tmp3;
-- }
--
-- if (psm != NULL && *psm) {
-- purple_notify_user_info_add_pair_plaintext(user_info, tmp2, psm);
-- } else {
-- purple_notify_user_info_add_pair(user_info, _("Status"), tmp2);
-- }
--
-- g_free(tmp2);
-- } else {
-- if (psm != NULL && *psm) {
-- if (purple_presence_is_idle(presence)) {
-- purple_notify_user_info_add_pair_plaintext(user_info, _("Idle"), psm);
-- } else {
-- purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), psm);
-- }
-- } else {
-- if (purple_presence_is_idle(presence)) {
-- purple_notify_user_info_add_pair(user_info, _("Status"),
-- _("Idle"));
-- } else {
-- purple_notify_user_info_add_pair(user_info, _("Status"),
-- purple_status_get_name(status));
-- }
-- }
-- }
--
-- if (currentmedia) {
-- purple_notify_user_info_add_pair(user_info, mediatype, currentmedia);
-- g_free(currentmedia);
-- }
-- }
--
-- /* XXX: This is being shown in non-full tooltips because the
-- * XXX: blocked icon overlay isn't always accurate for MSN.
-- * XXX: This can die as soon as purple_privacy_check() knows that
-- * XXX: this prpl always honors both the allow and deny lists. */
-- /* While the above comment may be strictly correct (the privacy API needs
-- * rewriteing), purple_privacy_check() is going to be more accurate at
-- * indicating whether a particular buddy is going to be able to message
-- * you, which is the important information that this is trying to convey.
-- */
-- if (full && user)
-- {
-- const char *phone;
--
-- purple_notify_user_info_add_pair(user_info, _("Has you"),
-- ((user->list_op & (1 << MSN_LIST_RL)) ? _("Yes") : _("No")));
--
-- purple_notify_user_info_add_pair(user_info, _("Blocked"),
-- ((user->list_op & (1 << MSN_LIST_BL)) ? _("Yes") : _("No")));
--
-- phone = msn_user_get_home_phone(user);
-- if (phone != NULL)
-- purple_notify_user_info_add_pair(user_info, _("Home Phone Number"), phone);
--
-- phone = msn_user_get_work_phone(user);
-- if (phone != NULL)
-- purple_notify_user_info_add_pair(user_info, _("Work Phone Number"), phone);
--
-- phone = msn_user_get_mobile_phone(user);
-- if (phone != NULL)
-- purple_notify_user_info_add_pair(user_info, _("Mobile Phone Number"), phone);
-- }
--}
--
--static GList *
--msn_status_types(PurpleAccount *account)
--{
-- PurpleStatusType *status;
-- GList *types = NULL;
--
-- status = purple_status_type_new_with_attrs(
-- PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE,
-- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- types = g_list_append(types, status);
--
-- status = purple_status_type_new_with_attrs(
-- PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE,
-- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- types = g_list_append(types, status);
--
-- status = purple_status_type_new_with_attrs(
-- PURPLE_STATUS_AWAY, "brb", _("Be Right Back"), TRUE, TRUE, FALSE,
-- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- types = g_list_append(types, status);
--
-- status = purple_status_type_new_with_attrs(
-- PURPLE_STATUS_UNAVAILABLE, "busy", _("Busy"), TRUE, TRUE, FALSE,
-- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- types = g_list_append(types, status);
-- status = purple_status_type_new_with_attrs(
-- PURPLE_STATUS_UNAVAILABLE, "phone", _("On the Phone"), TRUE, TRUE, FALSE,
-- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- types = g_list_append(types, status);
-- status = purple_status_type_new_with_attrs(
-- PURPLE_STATUS_AWAY, "lunch", _("Out to Lunch"), TRUE, TRUE, FALSE,
-- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- types = g_list_append(types, status);
--
-- status = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE,
-- NULL, NULL, TRUE, TRUE, FALSE);
-- types = g_list_append(types, status);
--
-- status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE,
-- NULL, NULL, TRUE, TRUE, FALSE);
-- types = g_list_append(types, status);
--
-- status = purple_status_type_new_full(PURPLE_STATUS_MOBILE,
-- "mobile", NULL, FALSE, FALSE, TRUE);
-- types = g_list_append(types, status);
--
-- status = purple_status_type_new_with_attrs(PURPLE_STATUS_TUNE,
-- "tune", NULL, FALSE, TRUE, TRUE,
-- PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
-- PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING),
-- PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
-- "game", _("Game Title"), purple_value_new(PURPLE_TYPE_STRING),
-- "office", _("Office Title"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- types = g_list_append(types, status);
--
-- return types;
--}
--
--static GList *
--msn_actions(PurplePlugin *plugin, gpointer context)
--{
-- PurpleConnection *gc;
-- MsnSession *session;
-- GList *m = NULL;
-- PurplePluginAction *act;
--
-- gc = (PurpleConnection *) context;
-- session = gc->proto_data;
--
-- act = purple_plugin_action_new(_("Set Friendly Name..."),
-- msn_show_set_friendly_name);
-- m = g_list_append(m, act);
-- m = g_list_append(m, NULL);
--
-- if (session->enable_mpop)
-- {
-- act = purple_plugin_action_new(_("View Locations..."),
-- msn_show_locations);
-- m = g_list_append(m, act);
-- m = g_list_append(m, NULL);
-- }
--
-- act = purple_plugin_action_new(_("Set Home Phone Number..."),
-- msn_show_set_home_phone);
-- m = g_list_append(m, act);
--
-- act = purple_plugin_action_new(_("Set Work Phone Number..."),
-- msn_show_set_work_phone);
-- m = g_list_append(m, act);
--
-- act = purple_plugin_action_new(_("Set Mobile Phone Number..."),
-- msn_show_set_mobile_phone);
-- m = g_list_append(m, act);
-- m = g_list_append(m, NULL);
--
--#if 0
-- act = purple_plugin_action_new(_("Enable/Disable Mobile Devices..."),
-- msn_show_set_mobile_support);
-- m = g_list_append(m, act);
--#endif
--
-- act = purple_plugin_action_new(_("Allow/Disallow Multiple Logins..."),
-- msn_show_set_mpop);
-- m = g_list_append(m, act);
--
-- act = purple_plugin_action_new(_("Allow/Disallow Mobile Pages..."),
-- msn_show_set_mobile_pages);
-- m = g_list_append(m, act);
--
--/* QuLogic: Disabled until confirmed correct. */
--#if 0
-- m = g_list_append(m, NULL);
-- act = purple_plugin_action_new(_("View Blocked Text..."),
-- msn_show_blocked_text);
-- m = g_list_append(m, act);
--#endif
--
-- m = g_list_append(m, NULL);
-- act = purple_plugin_action_new(_("Open Hotmail Inbox"),
-- msn_show_hotmail_inbox);
-- m = g_list_append(m, act);
--
-- return m;
--}
--
--static GList *
--msn_buddy_menu(PurpleBuddy *buddy)
--{
-- MsnUser *user;
--
-- GList *m = NULL;
-- PurpleMenuAction *act;
--
-- g_return_val_if_fail(buddy != NULL, NULL);
--
-- user = purple_buddy_get_protocol_data(buddy);
--
-- if (user != NULL)
-- {
-- if (user->mobile)
-- {
-- act = purple_menu_action_new(_("Send to Mobile"),
-- PURPLE_CALLBACK(show_send_to_mobile_cb),
-- NULL, NULL);
-- m = g_list_append(m, act);
-- }
-- }
--
-- if (g_ascii_strcasecmp(purple_buddy_get_name(buddy),
-- purple_account_get_username(purple_buddy_get_account(buddy))))
-- {
-- act = purple_menu_action_new(_("Initiate _Chat"),
-- PURPLE_CALLBACK(initiate_chat_cb),
-- NULL, NULL);
-- m = g_list_append(m, act);
-- }
--
-- return m;
--}
--
--static GList *
--msn_blist_node_menu(PurpleBlistNode *node)
--{
-- if(PURPLE_BLIST_NODE_IS_BUDDY(node))
-- {
-- return msn_buddy_menu((PurpleBuddy *) node);
-- }
-- else
-- {
-- return NULL;
-- }
--}
--
--static void
--msn_login(PurpleAccount *account)
--{
-- PurpleConnection *gc;
-- MsnSession *session;
-- const char *username;
-- const char *host;
-- gboolean http_method = FALSE;
-- int port;
--
-- gc = purple_account_get_connection(account);
--
-- if (!purple_ssl_is_supported())
-- {
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
-- _("SSL support is needed for MSN. Please install a supported "
-- "SSL library."));
-- return;
-- }
--
-- http_method = purple_account_get_bool(account, "http_method", FALSE);
--
-- if (http_method)
-- host = purple_account_get_string(account, "http_method_server", MSN_HTTPCONN_SERVER);
-- else
-- host = purple_account_get_string(account, "server", MSN_SERVER);
-- port = purple_account_get_int(account, "port", MSN_PORT);
--
-- session = msn_session_new(account);
--
-- gc->proto_data = session;
-- gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_FORMATTING_WBFO | PURPLE_CONNECTION_NO_BGCOLOR |
-- PURPLE_CONNECTION_NO_FONTSIZE | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY;
--
-- msn_session_set_login_step(session, MSN_LOGIN_STEP_START);
--
-- /* Hmm, I don't like this. */
-- /* XXX shx: Me neither */
-- username = msn_normalize(account, purple_account_get_username(account));
--
-- if (strcmp(username, purple_account_get_username(account)))
-- purple_account_set_username(account, username);
--
-- username = purple_account_get_string(account, "display-name", NULL);
-- purple_connection_set_display_name(gc, username);
--
-- if (purple_account_get_string(account, "endpoint-name", NULL) == NULL) {
-- GHashTable *ui_info = purple_core_get_ui_info();
-- const gchar *ui_name = ui_info ? g_hash_table_lookup(ui_info, "name") : NULL;
-- purple_account_set_string(account, "endpoint-name",
-- ui_name && *ui_name ? ui_name : PACKAGE_NAME);
-- }
--
-- if (!msn_session_connect(session, host, port, http_method))
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Unable to connect"));
--}
--
--static void
--msn_close(PurpleConnection *gc)
--{
-- MsnSession *session;
--
-- session = gc->proto_data;
--
-- g_return_if_fail(session != NULL);
--
-- msn_session_destroy(session);
--
-- gc->proto_data = NULL;
--}
--
--static gboolean
--msn_send_me_im(gpointer data)
--{
-- MsnIMData *imdata = data;
-- serv_got_im(imdata->gc, imdata->who, imdata->msg, imdata->flags, imdata->when);
-- g_free(imdata->msg);
-- g_free(imdata);
-- return FALSE;
--}
--
--static GString*
--msn_msg_emoticon_add(GString *current, MsnEmoticon *emoticon)
--{
-- MsnObject *obj;
-- char *strobj;
--
-- if (emoticon == NULL)
-- return current;
--
-- obj = emoticon->obj;
--
-- if (!obj)
-- return current;
--
-- strobj = msn_object_to_string(obj);
--
-- if (current)
-- g_string_append_printf(current, "\t%s\t%s", emoticon->smile, strobj);
-- else {
-- current = g_string_new("");
-- g_string_printf(current, "%s\t%s", emoticon->smile, strobj);
-- }
--
-- g_free(strobj);
--
-- return current;
--}
--
--static void
--msn_send_emoticons(MsnSwitchBoard *swboard, GString *body)
--{
-- MsnMessage *msg;
--
-- g_return_if_fail(body != NULL);
--
-- msg = msn_message_new(MSN_MSG_SLP);
-- msn_message_set_content_type(msg, "text/x-mms-emoticon");
-- msn_message_set_flag(msg, 'N');
-- msn_message_set_bin_data(msg, body->str, body->len);
--
-- msn_switchboard_send_msg(swboard, msg, TRUE);
-- msn_message_unref(msg);
--}
--
--static void msn_emoticon_destroy(MsnEmoticon *emoticon)
--{
-- if (emoticon->obj)
-- msn_object_destroy(emoticon->obj);
-- g_free(emoticon->smile);
-- g_free(emoticon);
--}
--
--static GSList* msn_msg_grab_emoticons(const char *msg, const char *username)
--{
-- GSList *list;
-- GList *smileys;
-- PurpleSmiley *smiley;
-- PurpleStoredImage *img;
-- char *ptr;
-- MsnEmoticon *emoticon;
-- int length;
--
-- list = NULL;
-- smileys = purple_smileys_get_all();
-- length = strlen(msg);
--
-- for (; smileys; smileys = g_list_delete_link(smileys, smileys)) {
-- smiley = smileys->data;
--
-- ptr = g_strstr_len(msg, length, purple_smiley_get_shortcut(smiley));
--
-- if (!ptr)
-- continue;
--
-- img = purple_smiley_get_stored_image(smiley);
--
-- emoticon = g_new0(MsnEmoticon, 1);
-- emoticon->smile = g_strdup(purple_smiley_get_shortcut(smiley));
-- emoticon->ps = smiley;
-- emoticon->obj = msn_object_new_from_image(img,
-- purple_imgstore_get_filename(img),
-- username, MSN_OBJECT_EMOTICON);
--
-- purple_imgstore_unref(img);
-- list = g_slist_prepend(list, emoticon);
-- }
--
-- return list;
--}
--
--void
--msn_send_im_message(MsnSession *session, MsnMessage *msg)
--{
-- MsnEmoticon *smile;
-- GSList *smileys;
-- GString *emoticons = NULL;
-- const char *username = purple_account_get_username(session->account);
-- MsnSwitchBoard *swboard = msn_session_get_swboard(session, msg->remote_user, MSN_SB_FLAG_IM);
--
-- smileys = msn_msg_grab_emoticons(msg->body, username);
-- while (smileys) {
-- smile = (MsnEmoticon *)smileys->data;
-- emoticons = msn_msg_emoticon_add(emoticons, smile);
-- msn_emoticon_destroy(smile);
-- smileys = g_slist_delete_link(smileys, smileys);
-- }
--
-- if (emoticons) {
-- msn_send_emoticons(swboard, emoticons);
-- g_string_free(emoticons, TRUE);
-- }
--
-- msn_switchboard_send_msg(swboard, msg, TRUE);
--}
--
--static int
--msn_send_im(PurpleConnection *gc, const char *who, const char *message,
-- PurpleMessageFlags flags)
--{
-- PurpleAccount *account;
-- PurpleBuddy *buddy = purple_find_buddy(gc->account, who);
-- MsnSession *session;
-- MsnSwitchBoard *swboard;
-- MsnMessage *msg;
-- char *msgformat;
-- char *msgtext;
-- size_t msglen;
-- const char *username;
--
-- purple_debug_info("msn", "send IM {%s} to %s\n", message, who);
-- account = purple_connection_get_account(gc);
-- username = purple_account_get_username(account);
--
-- session = gc->proto_data;
-- swboard = msn_session_find_swboard(session, who);
--
-- if (!strncmp("tel:+", who, 5)) {
-- char *text = purple_markup_strip_html(message);
-- send_to_mobile(gc, who, text);
-- g_free(text);
-- return 1;
-- }
--
-- if (buddy) {
-- PurplePresence *p = purple_buddy_get_presence(buddy);
-- if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_MOBILE)) {
-- char *text = purple_markup_strip_html(message);
-- send_to_mobile(gc, who, text);
-- g_free(text);
-- return 1;
-- }
-- }
--
-- msn_import_html(message, &msgformat, &msgtext);
-- msglen = strlen(msgtext);
-- if (msglen == 0) {
-- /* Stuff like <hr> will be ignored. Don't send an empty message
-- if that's all there is. */
-- g_free(msgtext);
-- g_free(msgformat);
--
-- return 0;
-- }
--
-- if (msglen + strlen(msgformat) + strlen(VERSION) > 1564)
-- {
-- g_free(msgformat);
-- g_free(msgtext);
--
-- return -E2BIG;
-- }
--
-- msg = msn_message_new_plain(msgtext);
-- msg->remote_user = g_strdup(who);
-- msn_message_set_header(msg, "X-MMS-IM-Format", msgformat);
--
-- g_free(msgformat);
-- g_free(msgtext);
--
-- purple_debug_info("msn", "prepare to send online Message\n");
-- if (g_ascii_strcasecmp(who, username))
-- {
-- if (flags & PURPLE_MESSAGE_AUTO_RESP) {
-- msn_message_set_flag(msg, 'U');
-- }
--
-- if (msn_user_is_yahoo(account, who) || !(msn_user_is_online(account, who) || swboard != NULL)) {
-- /*we send the online and offline Message to Yahoo User via UBM*/
-- purple_debug_info("msn", "send to Yahoo User\n");
-- msn_notification_send_uum(session, msg);
-- } else {
-- purple_debug_info("msn", "send via switchboard\n");
-- msn_send_im_message(session, msg);
-- }
-- }
-- else
-- {
-- char *body_str, *body_enc, *pre, *post;
-- const char *format;
-- MsnIMData *imdata = g_new0(MsnIMData, 1);
-- /*
-- * In MSN, you can't send messages to yourself, so
-- * we'll fake like we received it ;)
-- */
-- body_str = msn_message_to_string(msg);
-- body_enc = g_markup_escape_text(body_str, -1);
-- g_free(body_str);
--
-- format = msn_message_get_header_value(msg, "X-MMS-IM-Format");
-- msn_parse_format(format, &pre, &post);
-- body_str = g_strdup_printf("%s%s%s", pre ? pre : "",
-- body_enc ? body_enc : "", post ? post : "");
-- g_free(body_enc);
-- g_free(pre);
-- g_free(post);
--
-- serv_got_typing_stopped(gc, who);
-- imdata->gc = gc;
-- imdata->who = who;
-- imdata->msg = body_str;
-- imdata->flags = flags & ~PURPLE_MESSAGE_SEND;
-- imdata->when = time(NULL);
-- purple_timeout_add(0, msn_send_me_im, imdata);
-- }
--
-- msn_message_unref(msg);
--
-- return 1;
--}
--
--static unsigned int
--msn_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state)
--{
-- PurpleAccount *account;
-- MsnSession *session;
-- MsnSwitchBoard *swboard;
-- MsnMessage *msg;
--
-- account = purple_connection_get_account(gc);
-- session = gc->proto_data;
--
-- /*
-- * TODO: I feel like this should be "if (state != PURPLE_TYPING)"
-- * but this is how it was before, and I don't want to break
-- * anything. --KingAnt
-- */
-- if (state == PURPLE_NOT_TYPING)
-- return 0;
--
-- if (!g_ascii_strcasecmp(who, purple_account_get_username(account)))
-- {
-- /* We'll just fake it, since we're sending to ourself. */
-- serv_got_typing(gc, who, MSN_TYPING_RECV_TIMEOUT, PURPLE_TYPING);
--
-- return MSN_TYPING_SEND_TIMEOUT;
-- }
--
-- swboard = msn_session_find_swboard(session, who);
--
-- if (swboard == NULL || !msn_switchboard_can_send(swboard))
-- return 0;
--
-- swboard->flag |= MSN_SB_FLAG_IM;
--
-- msg = msn_message_new(MSN_MSG_TYPING);
-- msn_message_set_content_type(msg, "text/x-msmsgscontrol");
-- msn_message_set_flag(msg, 'U');
-- msn_message_set_header(msg, "TypingUser",
-- purple_account_get_username(account));
-- msn_message_set_bin_data(msg, "\r\n", 2);
--
-- msn_switchboard_send_msg(swboard, msg, FALSE);
--
-- msn_message_unref(msg);
--
-- return MSN_TYPING_SEND_TIMEOUT;
--}
--
--static void
--msn_set_status(PurpleAccount *account, PurpleStatus *status)
--{
-- PurpleConnection *gc;
-- MsnSession *session;
--
-- gc = purple_account_get_connection(account);
--
-- if (gc != NULL)
-- {
-- session = gc->proto_data;
-- msn_change_status(session);
-- }
--}
--
--static void
--msn_set_idle(PurpleConnection *gc, int idle)
--{
-- MsnSession *session;
--
-- session = gc->proto_data;
--
-- msn_change_status(session);
--}
--
--/*
-- * Actually adds a buddy once we have the response from FQY
-- */
--static void
--add_pending_buddy(MsnSession *session,
-- const char *who,
-- MsnNetwork network,
-- MsnUser *user)
--{
-- char *group;
-- MsnUserList *userlist;
-- MsnUser *user2;
--
-- g_return_if_fail(user != NULL);
--
-- if (network == MSN_NETWORK_UNKNOWN) {
-- purple_debug_error("msn", "Network in FQY response was unknown. "
-- "Assuming %s is a passport user and adding anyway.\n", who);
-- network = MSN_NETWORK_PASSPORT;
-- }
--
-- group = msn_user_remove_pending_group(user);
--
-- userlist = session->userlist;
-- user2 = msn_userlist_find_user(userlist, who);
-- if (user2 != NULL) {
-- /* User already in userlist, so just update it. */
-- msn_user_unref(user);
-- user = user2;
-- } else {
-- msn_userlist_add_user(userlist, user);
-- msn_user_unref(user);
-- }
--
-- msn_user_set_network(user, network);
-- msn_userlist_add_buddy(userlist, who, group);
--
-- g_free(group);
--}
--
--static void
--msn_add_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group, const char *message)
--{
-- PurpleAccount *account;
-- const char *bname, *gname;
-- MsnSession *session;
-- MsnUserList *userlist;
-- MsnUser *user;
--
-- account = purple_connection_get_account(pc);
-- session = purple_connection_get_protocol_data(pc);
-- bname = purple_buddy_get_name(buddy);
--
-- if (!session->logged_in)
-- {
-- purple_debug_error("msn", "msn_add_buddy called before connected\n");
--
-- return;
-- }
--
-- /* XXX - Would group ever be NULL here? I don't think so...
-- * shx: Yes it should; MSN handles non-grouped buddies, and this is only
-- * internal.
-- * KingAnt: But PurpleBuddys must always exist inside PurpleGroups, so
-- * won't group always be non-NULL here?
-- */
-- bname = msn_normalize(account, bname);
-- gname = group ? purple_group_get_name(group) : NULL;
-- purple_debug_info("msn", "Add user:%s to group:%s\n",
-- bname, gname ? gname : "(null)");
--
-- if (!msn_email_is_valid(bname)) {
-- gchar *buf;
-- buf = g_strdup_printf(_("Unable to add the buddy %s because the username is invalid. Usernames must be valid email addresses."), bname);
-- if (!purple_conv_present_error(bname, account, buf))
-- purple_notify_error(pc, NULL, _("Unable to Add"), buf);
-- g_free(buf);
--
-- /* Remove from local list */
-- purple_blist_remove_buddy(buddy);
--
-- return;
-- }
--
-- /* Make sure name is normalized */
-- purple_blist_rename_buddy(buddy, bname);
--
-- userlist = session->userlist;
-- user = msn_userlist_find_user(userlist, bname);
-- if (user && user->authorized) {
-- message = NULL;
-- }
-- if ((user != NULL) && (user->networkid != MSN_NETWORK_UNKNOWN)) {
-- /* We already know this buddy and their network. This function knows
-- what to do with users already in the list and stuff... */
-- msn_user_set_invite_message(user, message);
-- msn_userlist_add_buddy(userlist, bname, gname);
-- } else {
-- char **tokens;
-- char *fqy;
-- /* We need to check the network for this buddy first */
-- user = msn_user_new(userlist, bname, NULL);
-- msn_user_set_invite_message(user, message);
-- msn_user_set_pending_group(user, gname);
-- msn_user_set_network(user, MSN_NETWORK_UNKNOWN);
-- /* Should probably re-use the msn_add_contact_xml function here */
-- tokens = g_strsplit(bname, "@", 2);
-- fqy = g_strdup_printf("<ml><d n=\"%s\"><c n=\"%s\"/></d></ml>",
-- tokens[1],
-- tokens[0]);
-- /* TODO: I think user will leak if we disconnect before receiving
-- a response to this FQY request */
-- msn_notification_send_fqy(session, fqy, strlen(fqy),
-- (MsnFqyCb)add_pending_buddy, user);
-- g_free(fqy);
-- g_strfreev(tokens);
-- }
--}
--
--static void
--msn_rem_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
--{
-- MsnSession *session;
-- MsnUserList *userlist;
--
-- session = gc->proto_data;
-- userlist = session->userlist;
--
-- if (!session->logged_in)
-- return;
--
-- /* XXX - Does buddy->name need to be msn_normalize'd here? --KingAnt */
-- msn_userlist_rem_buddy(userlist, purple_buddy_get_name(buddy));
--}
--
--static void
--msn_add_permit(PurpleConnection *gc, const char *who)
--{
-- MsnSession *session;
-- MsnUserList *userlist;
-- MsnUser *user;
--
-- session = gc->proto_data;
-- userlist = session->userlist;
-- user = msn_userlist_find_user(userlist, who);
--
-- if (!session->logged_in)
-- return;
--
-- if (user != NULL && user->list_op & MSN_LIST_BL_OP) {
-- msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_BL);
--
-- /* delete contact from Block list and add it to Allow in the callback */
-- msn_del_contact_from_list(session, NULL, who, MSN_LIST_BL);
-- } else {
-- /* just add the contact to Allow list */
-- msn_add_contact_to_list(session, NULL, who, MSN_LIST_AL);
-- }
--
--
-- msn_userlist_add_buddy_to_list(userlist, who, MSN_LIST_AL);
--}
--
--static void
--msn_add_deny(PurpleConnection *gc, const char *who)
--{
-- MsnSession *session;
-- MsnUserList *userlist;
-- MsnUser *user;
--
-- session = gc->proto_data;
-- userlist = session->userlist;
-- user = msn_userlist_find_user(userlist, who);
--
-- if (!session->logged_in)
-- return;
--
-- if (user != NULL && user->list_op & MSN_LIST_AL_OP) {
-- msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_AL);
--
-- /* delete contact from Allow list and add it to Block in the callback */
-- msn_del_contact_from_list(session, NULL, who, MSN_LIST_AL);
-- } else {
-- /* just add the contact to Block list */
-- msn_add_contact_to_list(session, NULL, who, MSN_LIST_BL);
-- }
--
-- msn_userlist_add_buddy_to_list(userlist, who, MSN_LIST_BL);
--}
--
--static void
--msn_rem_permit(PurpleConnection *gc, const char *who)
--{
-- MsnSession *session;
-- MsnUserList *userlist;
-- MsnUser *user;
--
-- session = gc->proto_data;
-- userlist = session->userlist;
--
-- if (!session->logged_in)
-- return;
--
-- user = msn_userlist_find_user(userlist, who);
--
-- msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_AL);
--
-- msn_del_contact_from_list(session, NULL, who, MSN_LIST_AL);
--
-- if (user != NULL && user->list_op & MSN_LIST_RL_OP)
-- msn_userlist_add_buddy_to_list(userlist, who, MSN_LIST_BL);
--}
--
--static void
--msn_rem_deny(PurpleConnection *gc, const char *who)
--{
-- MsnSession *session;
-- MsnUserList *userlist;
-- MsnUser *user;
--
-- session = gc->proto_data;
-- userlist = session->userlist;
--
-- if (!session->logged_in)
-- return;
--
-- user = msn_userlist_find_user(userlist, who);
--
-- msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_BL);
--
-- msn_del_contact_from_list(session, NULL, who, MSN_LIST_BL);
--
-- if (user != NULL && user->list_op & MSN_LIST_RL_OP)
-- msn_userlist_add_buddy_to_list(userlist, who, MSN_LIST_AL);
--}
--
--static void
--msn_set_permit_deny(PurpleConnection *gc)
--{
-- msn_send_privacy(gc);
--}
--
--static void
--msn_chat_invite(PurpleConnection *gc, int id, const char *msg,
-- const char *who)
--{
-- MsnSession *session;
-- MsnSwitchBoard *swboard;
--
-- session = gc->proto_data;
--
-- swboard = msn_session_find_swboard_with_id(session, id);
--
-- if (swboard == NULL)
-- {
-- /* if we have no switchboard, everyone else left the chat already */
-- swboard = msn_switchboard_new(session);
-- msn_switchboard_request(swboard);
-- swboard->chat_id = id;
-- swboard->conv = purple_find_chat(gc, id);
-- }
--
-- swboard->flag |= MSN_SB_FLAG_IM;
--
-- msn_switchboard_request_add_user(swboard, who);
--}
--
--static void
--msn_chat_leave(PurpleConnection *gc, int id)
--{
-- MsnSession *session;
-- MsnSwitchBoard *swboard;
-- PurpleConversation *conv;
--
-- session = gc->proto_data;
--
-- swboard = msn_session_find_swboard_with_id(session, id);
--
-- /* if swboard is NULL we were the only person left anyway */
-- if (swboard == NULL)
-- return;
--
-- conv = swboard->conv;
--
-- msn_switchboard_release(swboard, MSN_SB_FLAG_IM);
--
-- /* If other switchboards managed to associate themselves with this
-- * conv, make sure they know it's gone! */
-- if (conv != NULL)
-- {
-- while ((swboard = msn_session_find_swboard_with_conv(session, conv)) != NULL)
-- swboard->conv = NULL;
-- }
--}
--
--static int
--msn_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)
--{
-- PurpleAccount *account;
-- MsnSession *session;
-- const char *username;
-- MsnSwitchBoard *swboard;
-- MsnMessage *msg;
-- char *msgformat;
-- char *msgtext;
-- size_t msglen;
-- MsnEmoticon *smile;
-- GSList *smileys;
-- GString *emoticons = NULL;
--
-- account = purple_connection_get_account(gc);
-- session = gc->proto_data;
-- username = purple_account_get_username(account);
-- swboard = msn_session_find_swboard_with_id(session, id);
--
-- if (swboard == NULL)
-- return -EINVAL;
--
-- if (!swboard->ready)
-- return 0;
--
-- swboard->flag |= MSN_SB_FLAG_IM;
--
-- msn_import_html(message, &msgformat, &msgtext);
-- msglen = strlen(msgtext);
--
-- if ((msglen == 0) || (msglen + strlen(msgformat) + strlen(VERSION) > 1564))
-- {
-- g_free(msgformat);
-- g_free(msgtext);
--
-- return -E2BIG;
-- }
--
-- msg = msn_message_new_plain(msgtext);
-- msn_message_set_header(msg, "X-MMS-IM-Format", msgformat);
--
-- smileys = msn_msg_grab_emoticons(msg->body, username);
-- while (smileys) {
-- smile = (MsnEmoticon *)smileys->data;
-- emoticons = msn_msg_emoticon_add(emoticons, smile);
-- if (purple_conv_custom_smiley_add(swboard->conv, smile->smile,
-- "sha1", purple_smiley_get_checksum(smile->ps),
-- FALSE)) {
-- gconstpointer data;
-- size_t len;
-- data = purple_smiley_get_data(smile->ps, &len);
-- purple_conv_custom_smiley_write(swboard->conv, smile->smile, data, len);
-- purple_conv_custom_smiley_close(swboard->conv, smile->smile);
-- }
-- msn_emoticon_destroy(smile);
-- smileys = g_slist_delete_link(smileys, smileys);
-- }
--
-- if (emoticons) {
-- msn_send_emoticons(swboard, emoticons);
-- g_string_free(emoticons, TRUE);
-- }
--
-- msn_switchboard_send_msg(swboard, msg, FALSE);
-- msn_message_unref(msg);
--
-- g_free(msgformat);
-- g_free(msgtext);
--
-- serv_got_chat_in(gc, id, purple_account_get_username(account), flags,
-- message, time(NULL));
--
-- return 0;
--}
--
--static void
--msn_keepalive(PurpleConnection *gc)
--{
-- MsnSession *session;
-- MsnTransaction *trans;
--
-- session = gc->proto_data;
--
-- if (!session->http_method)
-- {
-- MsnCmdProc *cmdproc;
--
-- cmdproc = session->notification->cmdproc;
--
-- trans = msn_transaction_new(cmdproc, "PNG", NULL);
-- msn_transaction_set_saveable(trans, FALSE);
-- msn_cmdproc_send_trans(cmdproc, trans);
-- }
--}
--
--static void msn_alias_buddy(PurpleConnection *pc, const char *name, const char *alias)
--{
-- MsnSession *session;
--
-- session = pc->proto_data;
--
-- msn_update_contact(session, name, MSN_UPDATE_ALIAS, alias);
--}
--
--static void
--msn_group_buddy(PurpleConnection *gc, const char *who,
-- const char *old_group_name, const char *new_group_name)
--{
-- MsnSession *session;
-- MsnUserList *userlist;
--
-- session = gc->proto_data;
-- userlist = session->userlist;
--
-- msn_userlist_move_buddy(userlist, who, old_group_name, new_group_name);
--}
--
--static void
--msn_rename_group(PurpleConnection *gc, const char *old_name,
-- PurpleGroup *group, GList *moved_buddies)
--{
-- MsnSession *session;
-- const char *gname;
--
-- session = gc->proto_data;
--
-- g_return_if_fail(session != NULL);
-- g_return_if_fail(session->userlist != NULL);
--
-- gname = purple_group_get_name(group);
-- if (msn_userlist_find_group_with_name(session->userlist, old_name) != NULL)
-- {
-- msn_contact_rename_group(session, old_name, gname);
-- }
-- else
-- {
-- /* not found */
-- msn_add_group(session, NULL, gname);
-- }
--}
--
--static void
--msn_convo_closed(PurpleConnection *gc, const char *who)
--{
-- MsnSession *session;
-- MsnSwitchBoard *swboard;
-- PurpleConversation *conv;
--
-- session = gc->proto_data;
--
-- swboard = msn_session_find_swboard(session, who);
--
-- /*
-- * Don't perform an assertion here. If swboard is NULL, then the
-- * switchboard was either closed by the other party, or the person
-- * is talking to himself.
-- */
-- if (swboard == NULL)
-- return;
--
-- conv = swboard->conv;
--
-- /* If we release the switchboard here, it may still have messages
-- pending ACK which would result in incorrect unsent message errors.
-- Just let it timeout... This is *so* going to screw with people who
-- use dumb clients that report "User has closed the conversation window" */
-- /* msn_switchboard_release(swboard, MSN_SB_FLAG_IM); */
-- swboard->conv = NULL;
--
-- /* If other switchboards managed to associate themselves with this
-- * conv, make sure they know it's gone! */
-- if (conv != NULL)
-- {
-- while ((swboard = msn_session_find_swboard_with_conv(session, conv)) != NULL)
-- swboard->conv = NULL;
-- }
--}
--
--static void
--msn_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img)
--{
-- MsnSession *session;
-- MsnUser *user;
--
-- session = gc->proto_data;
-- user = session->user;
--
-- msn_user_set_buddy_icon(user, img);
--
-- msn_change_status(session);
--}
--
--static void
--msn_remove_group(PurpleConnection *gc, PurpleGroup *group)
--{
-- MsnSession *session;
-- const char *gname;
--
-- session = gc->proto_data;
-- gname = purple_group_get_name(group);
--
-- purple_debug_info("msn", "Remove group %s\n", gname);
-- /*we can't delete the default group*/
-- if(!strcmp(gname, MSN_INDIVIDUALS_GROUP_NAME)||
-- !strcmp(gname, MSN_NON_IM_GROUP_NAME))
-- {
-- purple_debug_info("msn", "This group can't be removed, returning.\n");
-- return ;
-- }
--
-- msn_del_group(session, gname);
--}
--
--/**
-- * Extract info text from info_data and add it to user_info
-- */
--static gboolean
--msn_tooltip_extract_info_text(PurpleNotifyUserInfo *user_info, MsnGetInfoData *info_data)
--{
-- PurpleBuddy *b;
--
-- b = purple_find_buddy(purple_connection_get_account(info_data->gc),
-- info_data->name);
--
-- if (b)
-- {
-- char *tmp;
-- const char *alias;
--
-- alias = purple_buddy_get_local_buddy_alias(b);
-- if (alias && alias[0])
-- {
-- purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), alias);
-- }
--
-- if ((alias = purple_buddy_get_server_alias(b)) != NULL)
-- {
-- char *nicktext = g_markup_escape_text(alias, -1);
-- tmp = g_strdup_printf("<font sml=\"msn\">%s</font>", nicktext);
-- purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp);
-- g_free(tmp);
-- g_free(nicktext);
-- }
--
-- /* Add the tooltip information */
-- msn_tooltip_text(b, user_info, TRUE);
--
-- return TRUE;
-- }
--
-- return FALSE;
--}
--
--#if PHOTO_SUPPORT
--
--static char *
--msn_get_photo_url(const char *url_text)
--{
-- char *p, *q;
--
-- if ((p = strstr(url_text, PHOTO_URL)) != NULL)
-- {
-- p += strlen(PHOTO_URL);
-- }
-- if (p && (strncmp(p, "http://", strlen("http://")) == 0) && ((q = strchr(p, '"')) != NULL))
-- return g_strndup(p, q - p);
--
-- return NULL;
--}
--
--static void msn_got_photo(PurpleUtilFetchUrlData *url_data, gpointer data,
-- const gchar *url_text, gsize len, const gchar *error_message);
--
--#endif
--
--#if 0
--static char *msn_info_date_reformat(const char *field, size_t len)
--{
-- char *tmp = g_strndup(field, len);
-- time_t t = purple_str_to_time(tmp, FALSE, NULL, NULL, NULL);
--
-- g_free(tmp);
-- return g_strdup(purple_date_format_short(localtime(&t)));
--}
--#endif
--
--#define MSN_GOT_INFO_GET_FIELD(a, b) \
-- found = purple_markup_extract_info_field(stripped, stripped_len, user_info, \
-- "\n" a ":", 0, "\n", 0, "Undisclosed", b, 0, NULL, NULL); \
-- if (found) \
-- sect_info = TRUE;
--
--#define MSN_GOT_INFO_GET_FIELD_NO_SEARCH(a, b) \
-- found = purple_markup_extract_info_field(stripped, stripped_len, user_info, \
-- "\n" a ":", 0, "\n", 0, "Undisclosed", b, 0, NULL, msn_info_strip_search_link); \
-- if (found) \
-- sect_info = TRUE;
--
--static char *
--msn_info_strip_search_link(const char *field, size_t len)
--{
-- const char *c;
-- if ((c = strstr(field, " (http://")) == NULL)
-- return g_strndup(field, len);
-- return g_strndup(field, c - field);
--}
--
--static void
--msn_got_info(PurpleUtilFetchUrlData *url_data, gpointer data,
-- const gchar *url_text, size_t len, const gchar *error_message)
--{
-- MsnGetInfoData *info_data = (MsnGetInfoData *)data;
-- MsnSession *session;
-- PurpleNotifyUserInfo *user_info;
-- char *stripped, *p, *q, *tmp;
-- char *user_url = NULL;
-- gboolean found;
-- gboolean has_tooltip_text = FALSE;
-- gboolean has_info = FALSE;
-- gboolean sect_info = FALSE;
-- gboolean has_contact_info = FALSE;
-- char *url_buffer;
-- int stripped_len;
--#if PHOTO_SUPPORT
-- char *photo_url_text = NULL;
-- MsnGetInfoStepTwoData *info2_data = NULL;
--#endif
--
-- purple_debug_info("msn", "In msn_got_info,url_text:{%s}\n",url_text);
--
-- session = purple_connection_get_protocol_data(info_data->gc);
-- session->url_datas = g_slist_remove(session->url_datas, url_data);
--
-- user_info = purple_notify_user_info_new();
-- has_tooltip_text = msn_tooltip_extract_info_text(user_info, info_data);
--
-- if (error_message != NULL || url_text == NULL || strcmp(url_text, "") == 0)
-- {
-- purple_notify_user_info_add_pair(user_info,
-- _("Error retrieving profile"), NULL);
--
-- purple_notify_userinfo(info_data->gc, info_data->name, user_info, NULL, NULL);
-- purple_notify_user_info_destroy(user_info);
--
-- g_free(info_data->name);
-- g_free(info_data);
-- return;
-- }
--
-- url_buffer = g_strdup(url_text);
--
-- /* If they have a homepage link, MSN masks it such that we need to
-- * fetch the url out before purple_markup_strip_html() nukes it */
-- /* I don't think this works with the new spaces profiles - Stu 3/2/06 */
-- if ((p = strstr(url_text,
-- "Take a look at my </font><A class=viewDesc title=\"")) != NULL)
-- {
-- p += 50;
--
-- if ((q = strchr(p, '"')) != NULL)
-- user_url = g_strndup(p, q - p);
-- }
--
-- /*
-- * purple_markup_strip_html() doesn't strip out character entities like &nbsp;
-- * and &#183;
-- */
-- while ((p = strstr(url_buffer, "&nbsp;")) != NULL)
-- {
-- *p = ' '; /* Turn &nbsp;'s into ordinary blanks */
-- p += 1;
-- memmove(p, p + 5, strlen(p + 5));
-- url_buffer[strlen(url_buffer) - 5] = '\0';
-- }
--
-- while ((p = strstr(url_buffer, "&#183;")) != NULL)
-- {
-- memmove(p, p + 6, strlen(p + 6));
-- url_buffer[strlen(url_buffer) - 6] = '\0';
-- }
--
-- /* Nuke the nasty \r's that just get in the way */
-- purple_str_strip_char(url_buffer, '\r');
--
-- /* MSN always puts in &#39; for apostrophes...replace them */
-- while ((p = strstr(url_buffer, "&#39;")) != NULL)
-- {
-- *p = '\'';
-- memmove(p + 1, p + 5, strlen(p + 5));
-- url_buffer[strlen(url_buffer) - 4] = '\0';
-- }
--
-- /* Nuke the html, it's easier than trying to parse the horrid stuff */
-- stripped = purple_markup_strip_html(url_buffer);
-- stripped_len = strlen(stripped);
--
-- purple_debug_misc("msn", "stripped = %p\n", stripped);
-- purple_debug_misc("msn", "url_buffer = %p\n", url_buffer);
--
-- /* General section header */
-- if (has_tooltip_text)
-- purple_notify_user_info_add_section_break(user_info);
--
-- purple_notify_user_info_add_section_header(user_info, _("General"));
--
-- /* Extract their Name and put it in */
-- MSN_GOT_INFO_GET_FIELD("Name", _("Name"));
--
-- /* General */
-- MSN_GOT_INFO_GET_FIELD("Nickname", _("Nickname"));
-- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Age", _("Age"));
-- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Gender", _("Gender"));
-- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Occupation", _("Occupation"));
-- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Location", _("Location"));
--
-- /* Extract their Interests and put it in */
-- found = purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- "\nInterests\t", 0, " (/default.aspx?page=searchresults", 0,
-- "Undisclosed", _("Hobbies and Interests") /* _("Interests") */,
-- 0, NULL, NULL);
--
-- if (found)
-- sect_info = TRUE;
--
-- MSN_GOT_INFO_GET_FIELD("More about me", _("A Little About Me"));
--
-- if (sect_info)
-- {
-- has_info = TRUE;
-- sect_info = FALSE;
-- }
-- else
-- {
-- /* Remove the section header */
-- purple_notify_user_info_remove_last_item(user_info);
-- if (has_tooltip_text)
-- purple_notify_user_info_remove_last_item(user_info);
-- }
--
-- /* Social */
-- purple_notify_user_info_add_section_break(user_info);
-- purple_notify_user_info_add_section_header(user_info, _("Social"));
--
-- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Marital status", _("Marital Status"));
-- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Interested in", _("Interests"));
-- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Pets", _("Pets"));
-- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Hometown", _("Hometown"));
-- MSN_GOT_INFO_GET_FIELD("Places lived", _("Places Lived"));
-- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Fashion", _("Fashion"));
-- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Humor", _("Humor"));
-- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Music", _("Music"));
-- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Favorite quote", _("Favorite Quote"));
--
-- if (sect_info)
-- {
-- has_info = TRUE;
-- sect_info = FALSE;
-- }
-- else
-- {
-- /* Remove the section header */
-- purple_notify_user_info_remove_last_item(user_info);
-- purple_notify_user_info_remove_last_item(user_info);
-- }
--
-- /* Contact Info */
-- /* Personal */
-- purple_notify_user_info_add_section_break(user_info);
-- purple_notify_user_info_add_section_header(user_info, _("Contact Info"));
-- purple_notify_user_info_add_section_header(user_info, _("Personal"));
--
-- MSN_GOT_INFO_GET_FIELD("Name", _("Name"));
-- MSN_GOT_INFO_GET_FIELD("Significant other", _("Significant Other"));
-- MSN_GOT_INFO_GET_FIELD("Home phone", _("Home Phone"));
-- MSN_GOT_INFO_GET_FIELD("Home phone 2", _("Home Phone 2"));
-- MSN_GOT_INFO_GET_FIELD("Home address", _("Home Address"));
-- MSN_GOT_INFO_GET_FIELD("Personal Mobile", _("Personal Mobile"));
-- MSN_GOT_INFO_GET_FIELD("Home fax", _("Home Fax"));
-- MSN_GOT_INFO_GET_FIELD("Personal email", _("Personal Email"));
-- MSN_GOT_INFO_GET_FIELD("Personal IM", _("Personal IM"));
-- MSN_GOT_INFO_GET_FIELD("Birthday", _("Birthday"));
-- MSN_GOT_INFO_GET_FIELD("Anniversary", _("Anniversary"));
-- MSN_GOT_INFO_GET_FIELD("Notes", _("Notes"));
--
-- if (sect_info)
-- {
-- has_info = TRUE;
-- sect_info = FALSE;
-- has_contact_info = TRUE;
-- }
-- else
-- {
-- /* Remove the section header */
-- purple_notify_user_info_remove_last_item(user_info);
-- }
--
-- /* Business */
-- purple_notify_user_info_add_section_header(user_info, _("Work"));
-- MSN_GOT_INFO_GET_FIELD("Name", _("Name"));
-- MSN_GOT_INFO_GET_FIELD("Job title", _("Job Title"));
-- MSN_GOT_INFO_GET_FIELD("Company", _("Company"));
-- MSN_GOT_INFO_GET_FIELD("Department", _("Department"));
-- MSN_GOT_INFO_GET_FIELD("Profession", _("Profession"));
-- MSN_GOT_INFO_GET_FIELD("Work phone 1", _("Work Phone"));
-- MSN_GOT_INFO_GET_FIELD("Work phone 2", _("Work Phone 2"));
-- MSN_GOT_INFO_GET_FIELD("Work address", _("Work Address"));
-- MSN_GOT_INFO_GET_FIELD("Work mobile", _("Work Mobile"));
-- MSN_GOT_INFO_GET_FIELD("Work pager", _("Work Pager"));
-- MSN_GOT_INFO_GET_FIELD("Work fax", _("Work Fax"));
-- MSN_GOT_INFO_GET_FIELD("Work email", _("Work Email"));
-- MSN_GOT_INFO_GET_FIELD("Work IM", _("Work IM"));
-- MSN_GOT_INFO_GET_FIELD("Start date", _("Start Date"));
-- MSN_GOT_INFO_GET_FIELD("Notes", _("Notes"));
--
-- if (sect_info)
-- {
-- has_info = TRUE;
-- sect_info = FALSE;
-- has_contact_info = TRUE;
-- }
-- else
-- {
-- /* Remove the section header */
-- purple_notify_user_info_remove_last_item(user_info);
-- }
--
-- if (!has_contact_info)
-- {
-- /* Remove the Contact Info section header */
-- purple_notify_user_info_remove_last_item(user_info);
-- }
--
--#if 0 /* these probably don't show up any more */
-- /*
-- * The fields, 'A Little About Me', 'Favorite Things', 'Hobbies
-- * and Interests', 'Favorite Quote', and 'My Homepage' may or may
-- * not appear, in any combination. However, they do appear in
-- * certain order, so we can successively search to pin down the
-- * distinct values.
-- */
--
-- /* Check if they have A Little About Me */
-- found = purple_markup_extract_info_field(stripped, stripped_len, s,
-- " A Little About Me \n\n", 0, "Favorite Things", '\n', NULL,
-- _("A Little About Me"), 0, NULL, NULL);
--
-- if (!found)
-- {
-- found = purple_markup_extract_info_field(stripped, stripped_len, s,
-- " A Little About Me \n\n", 0, "Hobbies and Interests", '\n',
-- NULL, _("A Little About Me"), 0, NULL, NULL);
-- }
--
-- if (!found)
-- {
-- found = purple_markup_extract_info_field(stripped, stripped_len, s,
-- " A Little About Me \n\n", 0, "Favorite Quote", '\n', NULL,
-- _("A Little About Me"), 0, NULL, NULL);
-- }
--
-- if (!found)
-- {
-- found = purple_markup_extract_info_field(stripped, stripped_len, s,
-- " A Little About Me \n\n", 0, "My Homepage \n\nTake a look",
-- '\n',
-- NULL, _("A Little About Me"), 0, NULL, NULL);
-- }
--
-- if (!found)
-- {
-- purple_markup_extract_info_field(stripped, stripped_len, s,
-- " A Little About Me \n\n", 0, "last updated", '\n', NULL,
-- _("A Little About Me"), 0, NULL, NULL);
-- }
--
-- if (found)
-- has_info = TRUE;
--
-- /* Check if they have Favorite Things */
-- found = purple_markup_extract_info_field(stripped, stripped_len, s,
-- " Favorite Things \n\n", 0, "Hobbies and Interests", '\n', NULL,
-- _("Favorite Things"), 0, NULL, NULL);
--
-- if (!found)
-- {
-- found = purple_markup_extract_info_field(stripped, stripped_len, s,
-- " Favorite Things \n\n", 0, "Favorite Quote", '\n', NULL,
-- _("Favorite Things"), 0, NULL, NULL);
-- }
--
-- if (!found)
-- {
-- found = purple_markup_extract_info_field(stripped, stripped_len, s,
-- " Favorite Things \n\n", 0, "My Homepage \n\nTake a look", '\n',
-- NULL, _("Favorite Things"), 0, NULL, NULL);
-- }
--
-- if (!found)
-- {
-- purple_markup_extract_info_field(stripped, stripped_len, s,
-- " Favorite Things \n\n", 0, "last updated", '\n', NULL,
-- _("Favorite Things"), 0, NULL, NULL);
-- }
--
-- if (found)
-- has_info = TRUE;
--
-- /* Check if they have Hobbies and Interests */
-- found = purple_markup_extract_info_field(stripped, stripped_len, s,
-- " Hobbies and Interests \n\n", 0, "Favorite Quote", '\n', NULL,
-- _("Hobbies and Interests"), 0, NULL, NULL);
--
-- if (!found)
-- {
-- found = purple_markup_extract_info_field(stripped, stripped_len, s,
-- " Hobbies and Interests \n\n", 0, "My Homepage \n\nTake a look",
-- '\n', NULL, _("Hobbies and Interests"), 0, NULL, NULL);
-- }
--
-- if (!found)
-- {
-- purple_markup_extract_info_field(stripped, stripped_len, s,
-- " Hobbies and Interests \n\n", 0, "last updated", '\n', NULL,
-- _("Hobbies and Interests"), 0, NULL, NULL);
-- }
--
-- if (found)
-- has_info = TRUE;
--
-- /* Check if they have Favorite Quote */
-- found = purple_markup_extract_info_field(stripped, stripped_len, s,
-- "Favorite Quote \n\n", 0, "My Homepage \n\nTake a look", '\n', NULL,
-- _("Favorite Quote"), 0, NULL, NULL);
--
-- if (!found)
-- {
-- purple_markup_extract_info_field(stripped, stripped_len, s,
-- "Favorite Quote \n\n", 0, "last updated", '\n', NULL,
-- _("Favorite Quote"), 0, NULL, NULL);
-- }
--
-- if (found)
-- has_info = TRUE;
--
-- /* Extract the last updated date and put it in */
-- found = purple_markup_extract_info_field(stripped, stripped_len, s,
-- " last updated:", 1, "\n", 0, NULL, _("Last Updated"), 0,
-- NULL, msn_info_date_reformat);
--
-- if (found)
-- has_info = TRUE;
--#endif
--
-- /* If we were able to fetch a homepage url earlier, stick it in there */
-- if (user_url != NULL)
-- {
-- tmp = g_strdup_printf("<a href=\"%s\">%s</a>", user_url, user_url);
-- purple_notify_user_info_add_pair(user_info, _("Homepage"), tmp);
-- g_free(tmp);
-- g_free(user_url);
--
-- has_info = TRUE;
-- }
--
-- if (!has_info)
-- {
-- /* MSN doesn't actually distinguish between "unknown member" and
-- * a known member with an empty profile. Try to explain this fact.
-- * Note that if we have a nonempty tooltip_text, we know the user
-- * exists.
-- */
-- /* This doesn't work with the new spaces profiles - Stu 3/2/06
-- char *p = strstr(url_buffer, "Unknown Member </TITLE>");
-- * This might not work for long either ... */
-- /* Nope, it failed some time before 5/2/07 :(
-- char *p = strstr(url_buffer, "form id=\"SpacesSearch\" name=\"SpacesSearch\"");
-- * Let's see how long this one holds out for ... */
-- char *p = strstr(url_buffer, "<form id=\"profile_form\" name=\"profile_form\" action=\"http&#58;&#47;&#47;spaces.live.com&#47;profile.aspx&#63;cid&#61;0\"");
-- PurpleBuddy *b = purple_find_buddy
-- (purple_connection_get_account(info_data->gc), info_data->name);
-- purple_notify_user_info_add_pair(user_info,
-- _("Error retrieving profile"), NULL);
-- purple_notify_user_info_add_pair(user_info, NULL,
-- ((p && b) ? _("The user has not created a public profile.") :
-- (p ? _("MSN reported not being able to find the user's profile. "
-- "This either means that the user does not exist, "
-- "or that the user exists "
-- "but has not created a public profile.") :
-- _("Could not find " /* This should never happen */
-- "any information in the user's profile. "
-- "The user most likely does not exist."))));
-- }
--
-- /* put a link to the actual profile URL */
-- purple_notify_user_info_add_section_break(user_info);
-- tmp = g_strdup_printf("<a href=\"%s%s\">%s</a>",
-- PROFILE_URL, info_data->name, _("View web profile"));
-- purple_notify_user_info_add_pair(user_info, NULL, tmp);
-- g_free(tmp);
--
--#if PHOTO_SUPPORT
-- /* Find the URL to the photo; must be before the marshalling [Bug 994207] */
-- photo_url_text = msn_get_photo_url(url_text);
-- purple_debug_info("msn", "photo url:{%s}\n", photo_url_text ? photo_url_text : "(null)");
--
-- /* Marshall the existing state */
-- info2_data = g_new0(MsnGetInfoStepTwoData, 1);
-- info2_data->info_data = info_data;
-- info2_data->stripped = stripped;
-- info2_data->url_buffer = url_buffer;
-- info2_data->user_info = user_info;
-- info2_data->photo_url_text = photo_url_text;
--
-- /* Try to put the photo in there too, if there's one */
-- if (photo_url_text)
-- {
-- url_data = purple_util_fetch_url_len(photo_url_text, FALSE, NULL, FALSE,
-- MAX_HTTP_BUDDYICON_BYTES,
-- msn_got_photo, info2_data);
-- session->url_datas = g_slist_prepend(session->url_datas, url_data);
-- }
-- else
-- {
-- /* Finish the Get Info and show the user something */
-- msn_got_photo(NULL, info2_data, NULL, 0, NULL);
-- }
--}
--
--static void
--msn_got_photo(PurpleUtilFetchUrlData *url_data, gpointer user_data,
-- const gchar *url_text, gsize len, const gchar *error_message)
--{
-- MsnGetInfoStepTwoData *info2_data = (MsnGetInfoStepTwoData *)user_data;
-- int id = -1;
--
-- /* Unmarshall the saved state */
-- MsnGetInfoData *info_data = info2_data->info_data;
-- char *stripped = info2_data->stripped;
-- char *url_buffer = info2_data->url_buffer;
-- PurpleNotifyUserInfo *user_info = info2_data->user_info;
-- char *photo_url_text = info2_data->photo_url_text;
--
-- if (url_data) {
-- MsnSession *session = purple_connection_get_protocol_data(info_data->gc);
-- session->url_datas = g_slist_remove(session->url_datas, url_data);
-- }
--
-- if (url_text && error_message)
-- {
-- purple_debug_warning("msn", "invalid connection. ignoring buddy photo info.\n");
-- g_free(stripped);
-- g_free(url_buffer);
-- purple_notify_user_info_destroy(user_info);
-- g_free(info_data->name);
-- g_free(info_data);
-- g_free(photo_url_text);
-- g_free(info2_data);
--
-- return;
-- }
--
-- /* Try to put the photo in there too, if there's one and is readable */
-- if (user_data && url_text && len != 0)
-- {
-- if (strstr(url_text, "400 Bad Request")
-- || strstr(url_text, "403 Forbidden")
-- || strstr(url_text, "404 Not Found"))
-- {
--
-- purple_debug_info("msn", "Error getting %s: %s\n",
-- photo_url_text, url_text);
-- }
-- else
-- {
-- char buf[1024];
-- purple_debug_info("msn", "%s is %" G_GSIZE_FORMAT " bytes\n", photo_url_text, len);
-- id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL);
-- g_snprintf(buf, sizeof(buf), "<img id=\"%d\"><br>", id);
-- purple_notify_user_info_prepend_pair(user_info, NULL, buf);
-- }
-- }
--
-- /* We continue here from msn_got_info, as if nothing has happened */
--#endif
-- purple_notify_userinfo(info_data->gc, info_data->name, user_info, NULL, NULL);
--
-- g_free(stripped);
-- g_free(url_buffer);
-- purple_notify_user_info_destroy(user_info);
-- g_free(info_data->name);
-- g_free(info_data);
--#if PHOTO_SUPPORT
-- g_free(photo_url_text);
-- g_free(info2_data);
-- if (id != -1)
-- purple_imgstore_unref_by_id(id);
--#endif
--}
--
--static void
--msn_get_info(PurpleConnection *gc, const char *name)
--{
-- MsnSession *session = purple_connection_get_protocol_data(gc);
-- MsnGetInfoData *data;
-- char *url;
-- PurpleUtilFetchUrlData *url_data;
--
-- data = g_new0(MsnGetInfoData, 1);
-- data->gc = gc;
-- data->name = g_strdup(name);
--
-- url = g_strdup_printf("%s%s", PROFILE_URL, name);
--
-- url_data = purple_util_fetch_url(url, FALSE,
-- "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
-- TRUE, msn_got_info, data);
-- session->url_datas = g_slist_prepend(session->url_datas, url_data);
--
-- g_free(url);
--}
--
--static gboolean msn_load(PurplePlugin *plugin)
--{
-- msn_notification_init();
-- msn_switchboard_init();
--
-- return TRUE;
--}
--
--static gboolean msn_unload(PurplePlugin *plugin)
--{
-- msn_notification_end();
-- msn_switchboard_end();
--
-- return TRUE;
--}
--
--static PurpleAccount *find_acct(const char *prpl, const char *acct_id)
--{
-- PurpleAccount *acct = NULL;
--
-- /* If we have a specific acct, use it */
-- if (acct_id) {
-- acct = purple_accounts_find(acct_id, prpl);
-- if (acct && !purple_account_is_connected(acct))
-- acct = NULL;
-- } else { /* Otherwise find an active account for the protocol */
-- GList *l = purple_accounts_get_all();
-- while (l) {
-- if (!strcmp(prpl, purple_account_get_protocol_id(l->data))
-- && purple_account_is_connected(l->data)) {
-- acct = l->data;
-- break;
-- }
-- l = l->next;
-- }
-- }
--
-- return acct;
--}
--
--static gboolean msn_uri_handler(const char *proto, const char *cmd, GHashTable *params)
--{
-- char *acct_id = g_hash_table_lookup(params, "account");
-- PurpleAccount *acct;
--
-- if (g_ascii_strcasecmp(proto, "msnim"))
-- return FALSE;
--
-- acct = find_acct("prpl-msn", acct_id);
--
-- if (!acct)
-- return FALSE;
--
-- /* msnim:chat?contact=user@domain.tld */
-- if (!g_ascii_strcasecmp(cmd, "Chat")) {
-- char *sname = g_hash_table_lookup(params, "contact");
-- if (sname) {
-- PurpleConversation *conv = purple_find_conversation_with_account(
-- PURPLE_CONV_TYPE_IM, sname, acct);
-- if (conv == NULL)
-- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, sname);
-- purple_conversation_present(conv);
-- }
-- /*else
-- **If pidgindialogs_im() was in the core, we could use it here.
-- * It is all purple_request_* based, but I'm not sure it really belongs in the core
-- pidgindialogs_im();*/
--
-- return TRUE;
-- }
-- /* msnim:add?contact=user@domain.tld */
-- else if (!g_ascii_strcasecmp(cmd, "Add")) {
-- char *name = g_hash_table_lookup(params, "contact");
-- purple_blist_request_add_buddy(acct, name, NULL, NULL);
-- return TRUE;
-- }
--
-- return FALSE;
--}
--
--
--static PurplePluginProtocolInfo prpl_info =
--{
-- OPT_PROTO_MAIL_CHECK|OPT_PROTO_INVITE_MESSAGE,
-- NULL, /* user_splits */
-- NULL, /* protocol_options */
-- {"png,gif", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_SEND}, /* icon_spec */
-- msn_list_icon, /* list_icon */
-- msn_list_emblems, /* list_emblems */
-- msn_status_text, /* status_text */
-- msn_tooltip_text, /* tooltip_text */
-- msn_status_types, /* away_states */
-- msn_blist_node_menu, /* blist_node_menu */
-- NULL, /* chat_info */
-- NULL, /* chat_info_defaults */
-- msn_login, /* login */
-- msn_close, /* close */
-- msn_send_im, /* send_im */
-- NULL, /* set_info */
-- msn_send_typing, /* send_typing */
-- msn_get_info, /* get_info */
-- msn_set_status, /* set_away */
-- msn_set_idle, /* set_idle */
-- NULL, /* change_passwd */
-- NULL, /* add_buddy */
-- NULL, /* add_buddies */
-- msn_rem_buddy, /* remove_buddy */
-- NULL, /* remove_buddies */
-- msn_add_permit, /* add_permit */
-- msn_add_deny, /* add_deny */
-- msn_rem_permit, /* rem_permit */
-- msn_rem_deny, /* rem_deny */
-- msn_set_permit_deny, /* set_permit_deny */
-- NULL, /* join_chat */
-- NULL, /* reject chat invite */
-- NULL, /* get_chat_name */
-- msn_chat_invite, /* chat_invite */
-- msn_chat_leave, /* chat_leave */
-- NULL, /* chat_whisper */
-- msn_chat_send, /* chat_send */
-- msn_keepalive, /* keepalive */
-- NULL, /* register_user */
-- NULL, /* get_cb_info */
-- NULL, /* get_cb_away */
-- msn_alias_buddy, /* alias_buddy */
-- msn_group_buddy, /* group_buddy */
-- msn_rename_group, /* rename_group */
-- NULL, /* buddy_free */
-- msn_convo_closed, /* convo_closed */
-- msn_normalize, /* normalize */
-- msn_set_buddy_icon, /* set_buddy_icon */
-- msn_remove_group, /* remove_group */
-- NULL, /* get_cb_real_name */
-- NULL, /* set_chat_topic */
-- NULL, /* find_blist_chat */
-- NULL, /* roomlist_get_list */
-- NULL, /* roomlist_cancel */
-- NULL, /* roomlist_expand_category */
-- msn_can_receive_file, /* can_receive_file */
-- msn_send_file, /* send_file */
-- msn_new_xfer, /* new_xfer */
-- msn_offline_message, /* offline_message */
-- NULL, /* whiteboard_prpl_ops */
-- NULL, /* send_raw */
-- NULL, /* roomlist_room_serialize */
-- NULL, /* unregister_user */
-- msn_send_attention, /* send_attention */
-- msn_attention_types, /* attention_types */
-- sizeof(PurplePluginProtocolInfo), /* struct_size */
-- msn_get_account_text_table, /* get_account_text_table */
-- NULL, /* initiate_media */
-- NULL, /* get_media_caps */
-- NULL, /* get_moods */
-- msn_set_public_alias, /* set_public_alias */
-- msn_get_public_alias, /* get_public_alias */
-- msn_add_buddy, /* 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-msn", /**< id */
-- "MSN", /**< name */
-- DISPLAY_VERSION, /**< version */
-- N_("Windows Live Messenger Protocol Plugin"), /**< summary */
-- N_("Windows Live Messenger Protocol Plugin"), /**< description */
-- NULL, /**< author */
-- PURPLE_WEBSITE, /**< homepage */
--
-- msn_load, /**< load */
-- msn_unload, /**< unload */
-- NULL, /**< destroy */
--
-- NULL, /**< ui_info */
-- &prpl_info, /**< extra_info */
-- NULL, /**< prefs_info */
-- msn_actions,
--
-- /* padding */
-- NULL,
-- NULL,
-- NULL,
-- NULL
--};
--
--static void
--init_plugin(PurplePlugin *plugin)
--{
-- PurpleAccountOption *option;
--
-- option = purple_account_option_string_new(_("Server"), "server",
-- MSN_SERVER);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-- option);
--
-- option = purple_account_option_int_new(_("Port"), "port", MSN_PORT);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-- option);
--
-- option = purple_account_option_bool_new(_("Use HTTP Method"),
-- "http_method", FALSE);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-- option);
--
-- option = purple_account_option_string_new(_("HTTP Method Server"),
-- "http_method_server", MSN_HTTPCONN_SERVER);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-- option);
--
-- option = purple_account_option_bool_new(_("Show custom smileys"),
-- "custom_smileys", TRUE);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-- option);
--
-- option = purple_account_option_bool_new(_("Allow direct connections"),
-- "direct_connect", TRUE);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-- option);
--
-- option = purple_account_option_bool_new(_("Allow connecting from multiple locations"),
-- "mpop", TRUE);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
-- option);
--
-- purple_cmd_register("nudge", "", PURPLE_CMD_P_PRPL,
-- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
-- "prpl-msn", msn_cmd_nudge,
-- _("nudge: nudge a user to get their attention"), NULL);
--
-- purple_prefs_remove("/plugins/prpl/msn");
--
-- purple_signal_connect(purple_get_core(), "uri-handler", plugin,
-- PURPLE_CALLBACK(msn_uri_handler), NULL);
--}
--
--PURPLE_INIT_PLUGIN(msn, init_plugin, info);
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/msn.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/msn.h
---- pidgin-2.10.7/libpurple/protocols/msn/msn.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/msn.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,158 +0,0 @@
--/**
-- * @file msn.h The MSN protocol plugin
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_H
--#define MSN_H
--
--typedef enum
--{
-- MSN_CAP_VIA_MOBILE = 0x0000001,
-- MSN_CAP_VIA_TEXAS = 0x0000002,
-- MSN_CAP_INK_GIF = 0x0000004,
-- MSN_CAP_INK_ISF = 0x0000008,
-- MSN_CAP_VIDEO_CHAT = 0x0000010,
-- MSN_CAP_PACKET = 0x0000020,
-- MSN_CAP_MOBILE_ON = 0x0000040,
-- MSN_CAP_WEB_WATCH = 0x0000080,
-- MSN_CAP_ACTIVITIES = 0x0000100,
-- MSN_CAP_VIA_WEBIM = 0x0000200,
-- MSN_CAP_MOBILE_DEV = 0x0000400,
-- MSN_CAP_VIA_FEDERATED = 0x0000800,
-- MSN_CAP_SPACE = 0x0001000,
-- MSN_CAP_MCE = 0x0002000,
-- MSN_CAP_DIRECTIM = 0x0004000,
-- MSN_CAP_WINKS = 0x0008000,
-- MSN_CAP_SEARCH = 0x0010000,
-- MSN_CAP_BOT = 0x0020000,
-- MSN_CAP_VOICEIM = 0x0040000,
-- MSN_CAP_SCHANNEL = 0x0080000,
-- MSN_CAP_SIP_INVITE = 0x0100000,
-- MSN_CAP_MULTI_VV = 0x0200000,
-- MSN_CAP_SDRIVE = 0x0400000,
-- MSN_CAP_PAGEMODE_MSG = 0x080000,
-- MSN_CAP_ONECARE = 0x1000000,
-- MSN_CAP_P2P_TURN = 0x2000000,
-- MSN_CAP_P2P_BOOTSTRAP_VIA_UUN = 0x4000000,
-- MSN_CAP_ALIASED = 0x8000000
--} MsnClientCaps;
--
--typedef enum
--{
-- MSN_EXT_CAP_SMS_ONLY = 0x1,
-- MSN_EXT_CAP_VOICE_OVER_MSNP = 0x2,
-- MSN_EXT_CAP_UUCP_SIP = 0x4,
-- MSN_EXT_CAP_APP_MSGS = 0x8,
-- MSN_EXT_CAP_RTC_VIDEO = 0x10,
-- MSN_EXT_CAP_P2PV2 = 0x20,
-- MSN_EXT_CAP_AUTH_WEBIM = 0x40,
-- MSN_EXT_CAP_1ON1_VIA_GROUP = 0x80,
-- MSN_EXT_CAP_OFFLINEIM = 0x100,
-- MSN_EXT_CAP_SHARING_VIDEO = 0x200,
-- MSN_EXT_CAP_NUDGE = 0x400,
-- MSN_EXT_CAP_CIRCLE_VOICEIM = 0x800,
-- MSN_EXT_CAP_SHARING = 0x1000,
-- MSN_EXT_CAP_P2P_MIXER_RELAY = 0x8000,
-- MSN_EXT_CAP_CONV_WINDOW_FT = 0x20000,
-- MSN_EXT_CAP_VIDEO_16x9 = 0x40000,
-- MSN_EXT_CAP_P2P_ENVELOPE = 0x80000,
-- MSN_EXT_CAP_YAHOOIM_DISABLE = 0x400000,
-- MSN_EXT_CAP_SIP_TUNNELv2 = 0x800000,
-- MSN_EXT_CAP_VOICE_CLIP_WMA = 0x1000000,
-- MSN_EXT_CAP_VOICE_CLIP_CIRCLEIM = 0x2000000,
-- MSN_EXT_CAP_SOCIAL_NEWS = 0x4000000,
-- MSN_EXT_CAP_CUSTOM_SMILEY = 0x8000000,
-- MSN_EXT_CAP_UTF8_MOODS = 0x10000000,
-- MSN_EXT_CAP_FTURN = 0x20000000,
-- MSN_EXT_CAP_P4_ACTIVITY = 0x40000000,
-- MSN_EXT_CAP_MUC = 0x80000000
--} MsnClientExtCaps;
--
--typedef enum
--{
-- MSN_CLIENT_VER_5_0 = 0x00,
-- MSN_CLIENT_VER_6_0 = 0x10, /* MSNC1 */
-- MSN_CLIENT_VER_6_1 = 0x20, /* MSNC2 */
-- MSN_CLIENT_VER_6_2 = 0x30, /* MSNC3 */
-- MSN_CLIENT_VER_7_0 = 0x40, /* MSNC4 */
-- MSN_CLIENT_VER_7_5 = 0x50, /* MSNC5 */
-- MSN_CLIENT_VER_8_0 = 0x60, /* MSNC6 */
-- MSN_CLIENT_VER_8_1 = 0x70, /* MSNC7 */
-- MSN_CLIENT_VER_8_5 = 0x80, /* MSNC8 */
-- MSN_CLIENT_VER_9_0 = 0x90, /* MSNC9 */
-- MSN_CLIENT_VER_14_0 = 0xA0, /* MSNC10 */
-- MSN_CLIENT_VER_15_0 = 0xB0 /* MSNC11 */
--} MsnClientVerId;
--
--#include "internal.h"
--
--#include "session.h"
--
--#include "msg.h"
--
--#define MSN_BUF_LEN 8192
--
--/* Windows Live Messenger Server*/
--#define MSN_SERVER "messenger.hotmail.com"
--#define MSN_HTTPCONN_SERVER "gateway.messenger.hotmail.com"
--#define MSN_PORT 1863
--#define WLM_PROT_VER 18
--
--#define WLM_MAX_PROTOCOL 18
--#define WLM_MIN_PROTOCOL 18
--
--#define MSN_TYPING_RECV_TIMEOUT 6
--#define MSN_TYPING_SEND_TIMEOUT 4
--
--#define PROFILE_URL "http://spaces.live.com/profile.aspx?mem="
--#define PHOTO_URL " contactparams:photopreauthurl=\""
--
--#define BUDDY_ALIAS_MAXLEN 387
--
--#define MSN_CAM_GUID "4BD96FC0-AB17-4425-A14A-439185962DC8"
--#define MSN_CAM_REQUEST_GUID "1C9AA97E-9C05-4583-A3BD-908A196F1E92"
--#define MSN_FT_GUID "5D3E02AB-6190-11D3-BBBB-00C04F795683"
--#define MSN_OBJ_GUID "A4268EEC-FEC5-49E5-95C3-F126696BDBF6"
--
--#define MSN_CLIENTINFO \
-- "Client-Name: Purple/" VERSION "\r\n" \
-- "Chat-Logging: Y\r\n"
--
--/* Index into attention_types */
--#define MSN_NUDGE 0
--
--#define MSN_CLIENT_ID_VERSION MSN_CLIENT_VER_9_0
--#define MSN_CLIENT_ID_CAPABILITIES (MSN_CAP_PACKET|MSN_CAP_INK_GIF|MSN_CAP_VOICEIM)
--#define MSN_CLIENT_ID_EXT_CAPS (0)
--
--#define MSN_CLIENT_ID \
-- ((MSN_CLIENT_ID_VERSION << 24) | \
-- (MSN_CLIENT_ID_CAPABILITIES))
--
--void
--msn_set_public_alias(PurpleConnection *gc, const char *alias,
-- PurpleSetPublicAliasSuccessCallback success_cb,
-- PurpleSetPublicAliasFailureCallback failure_cb);
--void msn_send_privacy(PurpleConnection *gc);
--void msn_send_im_message(MsnSession *session, MsnMessage *msg);
--
--#endif /* MSN_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/msnutils.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/msnutils.c
---- pidgin-2.10.7/libpurple/protocols/msn/msnutils.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/msnutils.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,718 +0,0 @@
--/**
-- * @file msnutils.c Utility functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--
--#include "msn.h"
--#include "msnutils.h"
--
--#include "cipher.h"
--
--/**************************************************************************
-- * Util
-- **************************************************************************/
--char *
--rand_guid(void)
--{
-- return g_strdup_printf("%4X%4X-%4X-%4X-%4X-%4X%4X%4X",
-- rand() % 0xAAFF + 0x1111,
-- rand() % 0xAAFF + 0x1111,
-- rand() % 0xAAFF + 0x1111,
-- rand() % 0xAAFF + 0x1111,
-- rand() % 0xAAFF + 0x1111,
-- rand() % 0xAAFF + 0x1111,
-- rand() % 0xAAFF + 0x1111,
-- rand() % 0xAAFF + 0x1111);
--}
--
--void
--msn_parse_format(const char *mime, char **pre_ret, char **post_ret)
--{
-- char *cur;
-- GString *pre = g_string_new(NULL);
-- GString *post = g_string_new(NULL);
-- unsigned int colors[3];
--
-- if (pre_ret != NULL) *pre_ret = NULL;
-- if (post_ret != NULL) *post_ret = NULL;
--
-- cur = strstr(mime, "FN=");
--
-- if (cur && (*(cur = cur + 3) != ';'))
-- {
-- pre = g_string_append(pre, "<FONT FACE=\"");
--
-- while (*cur && *cur != ';')
-- {
-- pre = g_string_append_c(pre, *cur);
-- cur++;
-- }
--
-- pre = g_string_append(pre, "\">");
-- post = g_string_prepend(post, "</FONT>");
-- }
--
-- cur = strstr(mime, "EF=");
--
-- if (cur && (*(cur = cur + 3) != ';'))
-- {
-- while (*cur && *cur != ';')
-- {
-- pre = g_string_append_c(pre, '<');
-- pre = g_string_append_c(pre, *cur);
-- pre = g_string_append_c(pre, '>');
-- post = g_string_prepend_c(post, '>');
-- post = g_string_prepend_c(post, *cur);
-- post = g_string_prepend_c(post, '/');
-- post = g_string_prepend_c(post, '<');
-- cur++;
-- }
-- }
--
-- cur = strstr(mime, "CO=");
--
-- if (cur && (*(cur = cur + 3) != ';'))
-- {
-- int i;
--
-- i = sscanf(cur, "%02x%02x%02x;", &colors[0], &colors[1], &colors[2]);
--
-- if (i > 0)
-- {
-- char tag[64];
--
-- if (i == 1)
-- {
-- colors[1] = 0;
-- colors[2] = 0;
-- }
-- else if (i == 2)
-- {
-- unsigned int temp = colors[0];
--
-- colors[0] = colors[1];
-- colors[1] = temp;
-- colors[2] = 0;
-- }
-- else if (i == 3)
-- {
-- unsigned int temp = colors[2];
--
-- colors[2] = colors[0];
-- colors[0] = temp;
-- }
--
-- g_snprintf(tag, sizeof(tag),
-- "<FONT COLOR=\"#%02hhx%02hhx%02hhx\">",
-- colors[0], colors[1], colors[2]);
--
-- pre = g_string_append(pre, tag);
-- post = g_string_prepend(post, "</FONT>");
-- }
-- }
--
-- cur = strstr(mime, "RL=");
--
-- if (cur && (*(cur = cur + 3) != ';'))
-- {
-- if (*cur == '1')
-- {
-- /* RTL text was received */
-- pre = g_string_append(pre, "<SPAN style=\"direction:rtl;text-align:right;\">");
-- post = g_string_prepend(post, "</SPAN>");
-- }
-- }
--
-- cur = g_strdup(purple_url_decode(pre->str));
-- g_string_free(pre, TRUE);
--
-- if (pre_ret != NULL)
-- *pre_ret = cur;
-- else
-- g_free(cur);
--
-- cur = g_strdup(purple_url_decode(post->str));
-- g_string_free(post, TRUE);
--
-- if (post_ret != NULL)
-- *post_ret = cur;
-- else
-- g_free(cur);
--}
--
--/*encode the str to RFC2047 style
-- * Currently only support the UTF-8 and base64 encode
-- */
--char *
--msn_encode_mime(const char *str)
--{
-- gchar *base64, *retval;
--
-- g_return_val_if_fail(str != NULL, NULL);
--
-- base64 = purple_base64_encode((guchar *)str, strlen(str));
-- retval = g_strdup_printf("=?utf-8?B?%s?=", base64);
-- g_free(base64);
--
-- return retval;
--}
--
--/*
-- * We need this because we're only supposed to encode spaces in the font
-- * names. purple_url_encode() isn't acceptable.
-- */
--gboolean
--msn_encode_spaces(const char *str, char *buf, size_t len)
--{
-- char *nonspace = buf;
--
-- while (isspace(*str))
-- str++;
--
-- for (; *str && len > 1; str++) {
-- if (*str == '%') {
-- if (len < 4)
-- break;
-- *buf++ = '%';
-- *buf++ = '2';
-- *buf++ = '5';
-- len -= 3;
-- nonspace = buf;
-- } else if (*str == ' ') {
-- if (len < 4)
-- break;
-- *buf++ = '%';
-- *buf++ = '2';
-- *buf++ = '0';
-- len -= 3;
-- } else {
-- *buf++ = *str;
-- len--;
-- nonspace = buf;
-- }
-- }
--
-- *nonspace = '\0';
--
-- return (*str == '\0');
--}
--
--/*
-- * Taken from the zephyr plugin.
-- * This parses HTML formatting (put out by one of the gtkimhtml widgets
-- * and converts it to msn formatting. It doesn't deal with the tag closing,
-- * but gtkimhtml widgets give valid html.
-- * It currently deals properly with <b>, <u>, <i>, <font face=...>,
-- * <font color=...>, <span dir=...>, <span style="direction: ...">.
-- * It ignores <font back=...> and <font size=...>
-- */
--void
--msn_import_html(const char *html, char **attributes, char **message)
--{
-- int len, retcount = 0;
-- const char *c;
-- char *msg;
-- char *fontface = NULL;
-- char fontface_encoded[BUF_LEN];
-- char fonteffect[5];
-- char fontcolor[7];
-- char direction = '0';
--
-- gboolean has_bold = FALSE;
-- gboolean has_italic = FALSE;
-- gboolean has_underline = FALSE;
-- gboolean has_strikethrough = FALSE;
--
-- g_return_if_fail(html != NULL);
-- g_return_if_fail(attributes != NULL);
-- g_return_if_fail(message != NULL);
--
-- len = strlen(html);
-- msg = g_malloc0(len + 1);
--
-- memset(fontcolor, 0, sizeof(fontcolor));
-- strcat(fontcolor, "0");
-- memset(fonteffect, 0, sizeof(fonteffect));
--
-- for (c = html; *c != '\0';)
-- {
-- if (*c == '<')
-- {
-- if (!g_ascii_strncasecmp(c + 1, "br>", 3))
-- {
-- msg[retcount++] = '\r';
-- msg[retcount++] = '\n';
-- c += 4;
-- }
-- else if (!g_ascii_strncasecmp(c + 1, "i>", 2))
-- {
-- if (!has_italic)
-- {
-- strcat(fonteffect, "I");
-- has_italic = TRUE;
-- }
-- c += 3;
-- }
-- else if (!g_ascii_strncasecmp(c + 1, "b>", 2))
-- {
-- if (!has_bold)
-- {
-- strcat(fonteffect, "B");
-- has_bold = TRUE;
-- }
-- c += 3;
-- }
-- else if (!g_ascii_strncasecmp(c + 1, "u>", 2))
-- {
-- if (!has_underline)
-- {
-- strcat(fonteffect, "U");
-- has_underline = TRUE;
-- }
-- c += 3;
-- }
-- else if (!g_ascii_strncasecmp(c + 1, "s>", 2))
-- {
-- if (!has_strikethrough)
-- {
-- strcat(fonteffect, "S");
-- has_strikethrough = TRUE;
-- }
-- c += 3;
-- }
-- else if (!g_ascii_strncasecmp(c + 1, "a href=\"", 8))
-- {
-- c += 9;
--
-- if (!g_ascii_strncasecmp(c, "mailto:", 7))
-- c += 7;
--
-- while ((*c != '\0') && g_ascii_strncasecmp(c, "\">", 2))
-- msg[retcount++] = *c++;
--
-- if (*c != '\0')
-- c += 2;
--
-- /* ignore descriptive string */
-- while ((*c != '\0') && g_ascii_strncasecmp(c, "</a>", 4))
-- c++;
--
-- if (*c != '\0')
-- c += 4;
-- }
-- else if (!g_ascii_strncasecmp(c + 1, "span", 4))
-- {
-- /* Bi-directional text support using CSS properties in span tags */
-- c += 5;
--
-- while (*c != '\0' && *c != '>')
-- {
-- while (*c == ' ')
-- c++;
-- if (!g_ascii_strncasecmp(c, "dir=\"rtl\"", 9))
-- {
-- c += 9;
-- direction = '1';
-- }
-- else if (!g_ascii_strncasecmp(c, "style=\"", 7))
-- {
-- /* Parse inline CSS attributes */
-- char *attributes;
-- int attr_len = 0;
-- c += 7;
-- while (*(c + attr_len) != '\0' && *(c + attr_len) != '"')
-- attr_len++;
-- if (*(c + attr_len) == '"')
-- {
-- char *attr_dir;
-- attributes = g_strndup(c, attr_len);
-- attr_dir = purple_markup_get_css_property(attributes, "direction");
-- if (attr_dir && (!g_ascii_strncasecmp(attr_dir, "RTL", 3)))
-- direction = '1';
-- g_free(attr_dir);
-- g_free(attributes);
-- }
--
-- }
-- else
-- {
-- c++;
-- }
-- }
-- if (*c == '>')
-- c++;
-- }
-- else if (!g_ascii_strncasecmp(c + 1, "font", 4))
-- {
-- c += 5;
--
-- while ((*c != '\0') && !g_ascii_strncasecmp(c, " ", 1))
-- c++;
--
-- if (!g_ascii_strncasecmp(c, "color=\"#", 7))
-- {
-- c += 8;
--
-- fontcolor[0] = *(c + 4);
-- fontcolor[1] = *(c + 5);
-- fontcolor[2] = *(c + 2);
-- fontcolor[3] = *(c + 3);
-- fontcolor[4] = *c;
-- fontcolor[5] = *(c + 1);
--
-- c += 8;
-- }
-- else if (!g_ascii_strncasecmp(c, "face=\"", 6))
-- {
-- const char *end = NULL;
-- const char *comma = NULL;
-- unsigned int namelen = 0;
--
-- c += 6;
-- end = strchr(c, '\"');
-- comma = strchr(c, ',');
--
-- if (comma == NULL || comma > end)
-- namelen = (unsigned int)(end - c);
-- else
-- namelen = (unsigned int)(comma - c);
--
-- fontface = g_strndup(c, namelen);
-- c = end + 2;
-- }
-- else
-- {
-- /* Drop all unrecognized/misparsed font tags */
-- while ((*c != '\0') && g_ascii_strncasecmp(c, "\">", 2))
-- c++;
--
-- if (*c != '\0')
-- c += 2;
-- }
-- }
-- else
-- {
-- while ((*c != '\0') && (*c != '>'))
-- c++;
-- if (*c != '\0')
-- c++;
-- }
-- }
-- else if (*c == '&')
-- {
-- if (!g_ascii_strncasecmp(c, "&lt;", 4))
-- {
-- msg[retcount++] = '<';
-- c += 4;
-- }
-- else if (!g_ascii_strncasecmp(c, "&gt;", 4))
-- {
-- msg[retcount++] = '>';
-- c += 4;
-- }
-- else if (!g_ascii_strncasecmp(c, "&nbsp;", 6))
-- {
-- msg[retcount++] = ' ';
-- c += 6;
-- }
-- else if (!g_ascii_strncasecmp(c, "&quot;", 6))
-- {
-- msg[retcount++] = '"';
-- c += 6;
-- }
-- else if (!g_ascii_strncasecmp(c, "&amp;", 5))
-- {
-- msg[retcount++] = '&';
-- c += 5;
-- }
-- else if (!g_ascii_strncasecmp(c, "&apos;", 6))
-- {
-- msg[retcount++] = '\'';
-- c += 6;
-- }
-- else
-- msg[retcount++] = *c++;
-- }
-- else
-- msg[retcount++] = *c++;
-- }
--
-- if (fontface == NULL)
-- fontface = g_strdup("Segoe UI");
--
-- msn_encode_spaces(fontface, fontface_encoded, BUF_LEN);
-- *attributes = g_strdup_printf("FN=%s; EF=%s; CO=%s; PF=0; RL=%c",
-- fontface_encoded,
-- fonteffect, fontcolor, direction);
-- *message = msg;
--
-- g_free(fontface);
--}
--
--void
--msn_parse_socket(const char *str, char **ret_host, int *ret_port)
--{
-- char *host;
-- char *c;
-- int port;
--
-- host = g_strdup(str);
--
-- if ((c = strchr(host, ':')) != NULL) {
-- *c = '\0';
-- port = atoi(c + 1);
-- } else {
-- port = 1863;
-- }
--
-- *ret_host = host;
-- *ret_port = port;
--}
--
--void
--msn_parse_user(const char *str, char **ret_user, int *ret_network)
--{
-- char **tokens;
--
-- tokens = g_strsplit(str, ":", 2);
--
-- *ret_network = atoi(tokens[0]);
-- *ret_user = tokens[1];
--
-- g_free(tokens[0]);
-- /* tokens[1] is returned */
-- g_free(tokens);
--}
--
--gboolean
--msn_email_is_valid(const char *passport)
--{
-- if (purple_email_is_valid(passport)) {
-- /* Special characters aren't allowed in domains, so only go to '@' */
-- while (*passport != '@') {
-- if (*passport == '/')
-- return FALSE;
-- else if (*passport == '?')
-- return FALSE;
-- else if (*passport == '=')
-- return FALSE;
-- /* MSN also doesn't like colons, but that's checked already */
--
-- passport++;
-- }
--
-- return TRUE;
-- }
--
-- return FALSE;
--}
--
--/***************************************************************************
-- * MSN Challenge Computing Function
-- ***************************************************************************/
--
--/*
-- * Handle MSN Challenge computation
-- * This algorithm references
-- * http://imfreedom.org/wiki/index.php/MSN:NS/Challenges
-- */
--#define BUFSIZE 256
--void
--msn_handle_chl(char *input, char *output)
--{
-- PurpleCipher *cipher;
-- PurpleCipherContext *context;
-- const guchar productKey[] = MSNP15_WLM_PRODUCT_KEY;
-- const guchar productID[] = MSNP15_WLM_PRODUCT_ID;
-- const char hexChars[] = "0123456789abcdef";
-- char buf[BUFSIZE];
-- unsigned char md5Hash[16];
-- unsigned char *newHash;
-- unsigned int *md5Parts;
-- unsigned int *chlStringParts;
-- unsigned int newHashParts[5];
--
-- long long nHigh = 0, nLow = 0;
--
-- int len;
-- int i;
--
-- /* Create the MD5 hash by using Purple MD5 algorithm */
-- cipher = purple_ciphers_find_cipher("md5");
-- context = purple_cipher_context_new(cipher, NULL);
--
-- purple_cipher_context_append(context, (guchar *)input, strlen(input));
-- purple_cipher_context_append(context, productKey, sizeof(productKey) - 1);
-- purple_cipher_context_digest(context, sizeof(md5Hash), md5Hash, NULL);
-- purple_cipher_context_destroy(context);
--
-- /* Split it into four integers */
-- md5Parts = (unsigned int *)md5Hash;
-- for (i = 0; i < 4; i++) {
-- /* adjust endianess */
-- md5Parts[i] = GUINT_TO_LE(md5Parts[i]);
--
-- /* & each integer with 0x7FFFFFFF */
-- /* and save one unmodified array for later */
-- newHashParts[i] = md5Parts[i];
-- md5Parts[i] &= 0x7FFFFFFF;
-- }
--
-- /* make a new string and pad with '0' to length that's a multiple of 8 */
-- snprintf(buf, BUFSIZE - 5, "%s%s", input, productID);
-- len = strlen(buf);
-- if ((len % 8) != 0) {
-- int fix = 8 - (len % 8);
-- memset(&buf[len], '0', fix);
-- buf[len + fix] = '\0';
-- len += fix;
-- }
--
-- /* split into integers */
-- chlStringParts = (unsigned int *)buf;
--
-- /* this is magic */
-- for (i = 0; i < (len / 4); i += 2) {
-- long long temp;
--
-- chlStringParts[i] = GUINT_TO_LE(chlStringParts[i]);
-- chlStringParts[i + 1] = GUINT_TO_LE(chlStringParts[i + 1]);
--
-- temp = (0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF;
-- temp = (md5Parts[0] * (temp + nLow) + md5Parts[1]) % 0x7FFFFFFF;
-- nHigh += temp;
--
-- temp = ((long long)chlStringParts[i + 1] + temp) % 0x7FFFFFFF;
-- nLow = (md5Parts[2] * temp + md5Parts[3]) % 0x7FFFFFFF;
-- nHigh += nLow;
-- }
-- nLow = (nLow + md5Parts[1]) % 0x7FFFFFFF;
-- nHigh = (nHigh + md5Parts[3]) % 0x7FFFFFFF;
--
-- newHashParts[0] ^= nLow;
-- newHashParts[1] ^= nHigh;
-- newHashParts[2] ^= nLow;
-- newHashParts[3] ^= nHigh;
--
-- /* adjust endianness */
-- for(i = 0; i < 4; i++)
-- newHashParts[i] = GUINT_TO_LE(newHashParts[i]);
--
-- /* make a string of the parts */
-- newHash = (unsigned char *)newHashParts;
--
-- /* convert to hexadecimal */
-- for (i = 0; i < 16; i++)
-- {
-- output[i * 2] = hexChars[(newHash[i] >> 4) & 0xF];
-- output[(i * 2) + 1] = hexChars[newHash[i] & 0xF];
-- }
--
-- output[32] = '\0';
--}
--
--guint8
--msn_read8(const char *buf)
--{
-- return (guint8)buf[0];
--}
--
--guint16
--msn_read16le(const char *buf)
--{
-- return GUINT16_FROM_LE(*(guint16 *)buf);
--}
--
--guint16
--msn_read16be(const char *buf)
--{
-- return GUINT16_FROM_BE(*(guint16 *)buf);
--}
--
--guint32
--msn_read32le(const char *buf)
--{
-- return GUINT32_FROM_LE(*(guint32 *)buf);
--}
--
--guint32
--msn_read32be(const char *buf)
--{
-- return GUINT32_FROM_BE(*(guint32 *)buf);
--}
--
--guint64
--msn_read64le(const char *buf)
--{
-- return GUINT64_FROM_LE(*(guint64 *)buf);
--}
--
--guint64
--msn_read64be(const char *buf)
--{
-- return GUINT64_FROM_BE(*(guint64 *)buf);
--}
--
--void
--msn_write8(char *buf, guint8 data)
--{
-- *(guint8 *)buf = data;
--}
--
--void
--msn_write16le(char *buf, guint16 data)
--{
-- *(guint16 *)buf = GUINT16_TO_LE(data);
--}
--
--void
--msn_write16be(char *buf, guint16 data)
--{
-- *(guint16 *)buf = GUINT16_TO_BE(data);
--}
--
--void
--msn_write32le(char *buf, guint32 data)
--{
-- *(guint32 *)buf = GUINT32_TO_LE(data);
--}
--
--void
--msn_write32be(char *buf, guint32 data)
--{
-- *(guint32 *)buf = GUINT32_TO_BE(data);
--}
--
--void
--msn_write64le(char *buf, guint64 data)
--{
-- *(guint64 *)buf = GUINT64_TO_LE(data);
--}
--
--void
--msn_write64be(char *buf, guint64 data)
--{
-- *(guint64 *)buf = GUINT64_TO_BE(data);
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/msnutils.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/msnutils.h
---- pidgin-2.10.7/libpurple/protocols/msn/msnutils.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/msnutils.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,244 +0,0 @@
--/**
-- * @file msnutils.h Utility functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_UTILS_H
--#define MSN_UTILS_H
--
--/*encode the str to RFC2047 style*/
--char *msn_encode_mime(const char *str);
--
--/**
-- * Generate the Random GUID
-- */
--char *rand_guid(void);
--
--/**
-- * Encodes the spaces in a string
-- *
-- * @param str The string to be encoded.
-- * @param buf The buffer to hold the encoded string.
-- * @param len The maximum length (including NUL) to put in @buf.
-- *
-- * @return Whether @str was able to fit in @buf.
-- */
--gboolean
--msn_encode_spaces(const char *str, char *buf, size_t len);
--
--/**
-- * Parses the MSN message formatting into a format compatible with Purple.
-- *
-- * @param mime The mime header with the formatting.
-- * @param pre_ret The returned prefix string.
-- * @param post_ret The returned postfix string.
-- *
-- * @return The new message.
-- */
--void msn_parse_format(const char *mime, char **pre_ret, char **post_ret);
--
--/**
-- * Parses the Purple message formatting (html) into the MSN format.
-- *
-- * @param html The html message to format.
-- * @param attributes The returned attributes string.
-- * @param message The returned message string.
-- *
-- * @return The new message.
-- */
--void msn_import_html(const char *html, char **attributes, char **message);
--
--/**
-- * Parses a socket string.
-- *
-- * @param str A host:port string.
-- * @param ret_host Return string value of the host.
-- * @param ret_port Return integer value of the port.
-- */
--void msn_parse_socket(const char *str, char **ret_host, int *ret_port);
--
--/**
-- * Parses a user name
-- *
-- * @param str A network:username string.
-- * @param ret_user Return of the user's passport.
-- * @param ret_network Return of the user's network.
-- */
--void msn_parse_user(const char *str, char **ret_user, int *ret_network);
--
--/**
-- * Verify if the email is a vaild passport.
-- *
-- * @param passport The email
-- *
-- * @return True if it is a valid passport, else FALSE
-- */
--gboolean msn_email_is_valid(const char *passport);
--
--/**
-- * Handle MSN Challenge Computation
-- * This algorithm references
-- * http://imfreedom.org/wiki/index.php/MSN:NS/Challenges
-- *
-- * @param input Challenge input.
-- * @param output Callenge output.
-- */
--void msn_handle_chl(char *input, char *output);
--
--/**
-- * Read a byte from a buffer
-- *
-- * @param buf Pointer to buffer.
-- *
-- * @return 8-bit byte
-- */
--guint8 msn_read8(const char *buf);
--
--/**
-- * Read a little-endian short from a buffer
-- *
-- * @param buf Pointer to buffer.
-- *
-- * @return 16-bit short
-- */
--guint16 msn_read16le(const char *buf);
--
--/**
-- * Read a big-endian short from a buffer
-- *
-- * @param buf Pointer to buffer.
-- *
-- * @return 16-bit short
-- */
--guint16 msn_read16be(const char *buf);
--
--/**
-- * Read a little-endian int from a buffer
-- *
-- * @param buf Pointer to buffer.
-- *
-- * @return 32-bit int
-- */
--guint32 msn_read32le(const char *buf);
--
--/**
-- * Read a big-endian int from a buffer
-- *
-- * @param buf Pointer to buffer.
-- *
-- * @return 32-bit int
-- */
--guint32 msn_read32be(const char *buf);
--
--/**
-- * Read a little-endian long from a buffer
-- *
-- * @param buf Pointer to buffer.
-- *
-- * @return 64-bit long
-- */
--guint64 msn_read64le(const char *buf);
--
--/**
-- * Read a big-endian long from a buffer
-- *
-- * @param buf Pointer to buffer.
-- *
-- * @return 64-bit long
-- */
--guint64 msn_read64be(const char *buf);
--
--/**
-- * Write a byte to a buffer
-- *
-- * @param buf Pointer to buffer.
-- * @param data 8-bit byte.
-- */
--void msn_write8(char *buf, guint8 data);
--
--/**
-- * Write a little-endian short to a buffer
-- *
-- * @param buf Pointer to buffer.
-- * @param data short.
-- */
--void msn_write16le(char *buf, guint16 data);
--
--/**
-- * Write a big-endian short to a buffer
-- *
-- * @param buf Pointer to buffer.
-- * @param data short.
-- */
--void msn_write16be(char *buf, guint16 data);
--
--/**
-- * Write a little-endian int to a buffer
-- *
-- * @param buf Pointer to buffer.
-- * @param data int.
-- */
--void msn_write32le(char *buf, guint32 data);
--
--/**
-- * Write a big-endian int to a buffer
-- *
-- * @param buf Pointer to buffer.
-- * @param data int.
-- */
--void msn_write32be(char *buf, guint32 data);
--
--/**
-- * Write a little-endian long to a buffer
-- *
-- * @param buf Pointer to buffer.
-- * @param data long.
-- */
--void msn_write64le(char *buf, guint64 data);
--
--/**
-- * Write a big-endian long to a buffer
-- *
-- * @param buf Pointer to buffer.
-- * @param data short
-- */
--void msn_write64be(char *buf, guint64 data);
--
--/**
-- * Same as above, but these increment the buf pointer.
-- */
--#define msn_pop8(buf) msn_read8((buf+=1)-1)
--#define msn_pop16le(buf) msn_read16le((buf+=2)-2)
--#define msn_pop16be(buf) msn_read16be((buf+=2)-2)
--#define msn_pop32le(buf) msn_read32le((buf+=4)-4)
--#define msn_pop32be(buf) msn_read32be((buf+=4)-4)
--#define msn_pop64le(buf) msn_read64le((buf+=8)-8)
--#define msn_pop64be(buf) msn_read64be((buf+=8)-8)
--#define msn_push8(buf, data) msn_write8(buf, data), buf+=1
--#define msn_push16le(buf, data) msn_write16le(buf, data), buf+=2
--#define msn_push16be(buf, data) msn_write16be(buf, data), buf+=2
--#define msn_push32le(buf, data) msn_write32le(buf, data), buf+=4
--#define msn_push32be(buf, data) msn_write32be(buf, data), buf+=4
--#define msn_push64le(buf, data) msn_write64le(buf, data), buf+=8
--#define msn_push64be(buf, data) msn_write64be(buf, data), buf+=8
--
--#endif /* MSN_UTILS_H */
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/nexus.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/nexus.c
---- pidgin-2.10.7/libpurple/protocols/msn/nexus.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/nexus.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,670 +0,0 @@
--/**
-- * @file nexus.c MSN Nexus functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "cipher.h"
--#include "debug.h"
--
--#include "msnutils.h"
--#include "soap.h"
--#include "nexus.h"
--#include "notification.h"
--
--/**************************************************************************
-- * Valid Ticket Tokens
-- **************************************************************************/
--
--#define SSO_VALID_TICKET_DOMAIN 0
--#define SSO_VALID_TICKET_POLICY 1
--static char *ticket_domains[][2] = {
-- /* http://msnpiki.msnfanatic.com/index.php/MSNP15:SSO */
-- /* {"Domain", "Policy Ref URI"}, Purpose */
-- {"messengerclear.live.com", NULL}, /* Authentication for messenger. */
-- {"messenger.msn.com", "?id=507"}, /* Authentication for receiving OIMs. */
-- {"contacts.msn.com", "MBI"}, /* Authentication for the Contact server. */
-- {"messengersecure.live.com", "MBI_SSL"}, /* Authentication for sending OIMs. */
-- {"storage.live.com", "MBI"}, /* Storage REST API */
-- {"sup.live.com", "MBI"}, /* What's New service */
--};
--
--/**************************************************************************
-- * Main
-- **************************************************************************/
--
--MsnNexus *
--msn_nexus_new(MsnSession *session)
--{
-- MsnNexus *nexus;
-- int i;
--
-- nexus = g_new0(MsnNexus, 1);
-- nexus->session = session;
--
-- nexus->token_len = sizeof(ticket_domains) / sizeof(char *[2]);
-- nexus->tokens = g_new0(MsnTicketToken, nexus->token_len);
--
-- for (i = 0; i < nexus->token_len; i++)
-- nexus->tokens[i].token = g_hash_table_new_full(g_str_hash, g_str_equal,
-- g_free, g_free);
--
-- return nexus;
--}
--
--void
--msn_nexus_destroy(MsnNexus *nexus)
--{
-- int i;
-- for (i = 0; i < nexus->token_len; i++) {
-- g_hash_table_destroy(nexus->tokens[i].token);
-- g_free(nexus->tokens[i].secret);
-- g_slist_free(nexus->tokens[i].updates);
-- }
--
-- g_free(nexus->tokens);
-- g_free(nexus->policy);
-- g_free(nexus->nonce);
-- g_free(nexus->cipher);
-- g_free(nexus->secret);
-- g_free(nexus);
--}
--
--/**************************************************************************
-- * RPS/SSO Authentication
-- **************************************************************************/
--
--static char *
--rps_create_key(const char *key, int key_len, const char *data, size_t data_len)
--{
-- const guchar magic[] = "WS-SecureConversation";
-- const int magic_len = sizeof(magic) - 1;
--
-- PurpleCipherContext *hmac;
-- guchar hash1[20], hash2[20], hash3[20], hash4[20];
-- char *result;
--
-- hmac = purple_cipher_context_new_by_name("hmac", NULL);
--
-- purple_cipher_context_set_option(hmac, "hash", "sha1");
-- purple_cipher_context_set_key_with_len(hmac, (guchar *)key, key_len);
-- purple_cipher_context_append(hmac, magic, magic_len);
-- purple_cipher_context_append(hmac, (guchar *)data, data_len);
-- purple_cipher_context_digest(hmac, sizeof(hash1), hash1, NULL);
--
-- purple_cipher_context_reset(hmac, NULL);
-- purple_cipher_context_set_option(hmac, "hash", "sha1");
-- purple_cipher_context_set_key_with_len(hmac, (guchar *)key, key_len);
-- purple_cipher_context_append(hmac, hash1, 20);
-- purple_cipher_context_append(hmac, magic, magic_len);
-- purple_cipher_context_append(hmac, (guchar *)data, data_len);
-- purple_cipher_context_digest(hmac, sizeof(hash2), hash2, NULL);
--
-- purple_cipher_context_reset(hmac, NULL);
-- purple_cipher_context_set_option(hmac, "hash", "sha1");
-- purple_cipher_context_set_key_with_len(hmac, (guchar *)key, key_len);
-- purple_cipher_context_append(hmac, hash1, 20);
-- purple_cipher_context_digest(hmac, sizeof(hash3), hash3, NULL);
--
-- purple_cipher_context_reset(hmac, NULL);
-- purple_cipher_context_set_option(hmac, "hash", "sha1");
-- purple_cipher_context_set_key_with_len(hmac, (guchar *)key, key_len);
-- purple_cipher_context_append(hmac, hash3, sizeof(hash3));
-- purple_cipher_context_append(hmac, magic, magic_len);
-- purple_cipher_context_append(hmac, (guchar *)data, data_len);
-- purple_cipher_context_digest(hmac, sizeof(hash4), hash4, NULL);
--
-- purple_cipher_context_destroy(hmac);
--
-- result = g_malloc(24);
-- memcpy(result, hash2, sizeof(hash2));
-- memcpy(result + sizeof(hash2), hash4, 4);
--
-- return result;
--}
--
--static char *
--des3_cbc(const char *key, const char *iv, const char *data, int len, gboolean decrypt)
--{
-- PurpleCipherContext *des3;
-- char *out;
-- size_t outlen;
--
-- des3 = purple_cipher_context_new_by_name("des3", NULL);
-- purple_cipher_context_set_key(des3, (guchar *)key);
-- purple_cipher_context_set_batch_mode(des3, PURPLE_CIPHER_BATCH_MODE_CBC);
-- purple_cipher_context_set_iv(des3, (guchar *)iv, 8);
--
-- out = g_malloc(len);
-- if (decrypt)
-- purple_cipher_context_decrypt(des3, (guchar *)data, len, (guchar *)out, &outlen);
-- else
-- purple_cipher_context_encrypt(des3, (guchar *)data, len, (guchar *)out, &outlen);
--
-- purple_cipher_context_destroy(des3);
--
-- return out;
--}
--
--#define MSN_USER_KEY_SIZE (7*4 + 8 + 20 + 72)
--#define CRYPT_MODE_CBC 1
--#define CIPHER_TRIPLE_DES 0x6603
--#define HASH_SHA1 0x8004
--static char *
--msn_rps_encrypt(MsnNexus *nexus)
--{
-- char usr_key_base[MSN_USER_KEY_SIZE], *usr_key;
-- const char magic1[] = "SESSION KEY HASH";
-- const char magic2[] = "SESSION KEY ENCRYPTION";
-- PurpleCipherContext *hmac;
-- size_t len;
-- guchar *hash;
-- char *key1, *key2, *key3;
-- gsize key1_len;
-- const char *iv;
-- char *nonce_fixed;
-- char *cipher;
-- char *response;
--
-- usr_key = &usr_key_base[0];
-- /* Header */
-- msn_push32le(usr_key, 28); /* Header size */
-- msn_push32le(usr_key, CRYPT_MODE_CBC); /* Crypt mode */
-- msn_push32le(usr_key, CIPHER_TRIPLE_DES); /* Cipher type */
-- msn_push32le(usr_key, HASH_SHA1); /* Hash type */
-- msn_push32le(usr_key, 8); /* IV size */
-- msn_push32le(usr_key, 20); /* Hash size */
-- msn_push32le(usr_key, 72); /* Cipher size */
-- /* Data */
-- iv = usr_key;
-- msn_push32le(usr_key, rand());
-- msn_push32le(usr_key, rand());
-- hash = (guchar *)usr_key;
-- usr_key += 20; /* Remaining is cipher data */
--
-- key1 = (char *)purple_base64_decode((const char *)nexus->tokens[MSN_AUTH_MESSENGER].secret, &key1_len);
-- key2 = rps_create_key(key1, key1_len, magic1, sizeof(magic1) - 1);
-- key3 = rps_create_key(key1, key1_len, magic2, sizeof(magic2) - 1);
--
-- len = strlen(nexus->nonce);
-- hmac = purple_cipher_context_new_by_name("hmac", NULL);
-- purple_cipher_context_set_option(hmac, "hash", "sha1");
-- purple_cipher_context_set_key_with_len(hmac, (guchar *)key2, 24);
-- purple_cipher_context_append(hmac, (guchar *)nexus->nonce, len);
-- purple_cipher_context_digest(hmac, 20, hash, NULL);
-- purple_cipher_context_destroy(hmac);
--
-- /* We need to pad this to 72 bytes, apparently */
-- nonce_fixed = g_malloc(len + 8);
-- memcpy(nonce_fixed, nexus->nonce, len);
-- memset(nonce_fixed + len, 0x08, 8);
-- cipher = des3_cbc(key3, iv, nonce_fixed, len + 8, FALSE);
-- g_free(nonce_fixed);
--
-- memcpy(usr_key, cipher, 72);
--
-- g_free(key1);
-- g_free(key2);
-- g_free(key3);
-- g_free(cipher);
--
-- response = purple_base64_encode((guchar *)usr_key_base, MSN_USER_KEY_SIZE);
--
-- return response;
--}
--
--/**************************************************************************
-- * Login
-- **************************************************************************/
--
--/* Used to specify which token to update when only doing single updates */
--typedef struct _MsnNexusUpdateData MsnNexusUpdateData;
--struct _MsnNexusUpdateData {
-- MsnNexus *nexus;
-- int id;
--};
--
--typedef struct _MsnNexusUpdateCallback MsnNexusUpdateCallback;
--struct _MsnNexusUpdateCallback {
-- GSourceFunc cb;
-- gpointer data;
--};
--
--static gboolean
--nexus_parse_token(MsnNexus *nexus, int id, xmlnode *node)
--{
-- char *token_str, *expiry_str;
-- const char *id_str;
-- char **elems, **cur, **tokens;
-- xmlnode *token = xmlnode_get_child(node, "RequestedSecurityToken/BinarySecurityToken");
-- xmlnode *secret = xmlnode_get_child(node, "RequestedProofToken/BinarySecret");
-- xmlnode *expires = xmlnode_get_child(node, "LifeTime/Expires");
--
-- if (!token)
-- return FALSE;
--
-- /* Use the ID that the server sent us */
-- if (id == -1) {
-- id_str = xmlnode_get_attrib(token, "Id");
-- if (id_str == NULL)
-- return FALSE;
--
-- id = atol(id_str + 7) - 1; /* 'Compact#' or 'PPToken#' */
-- if (id >= nexus->token_len)
-- return FALSE; /* Where did this come from? */
-- }
--
-- token_str = xmlnode_get_data(token);
-- if (token_str == NULL)
-- return FALSE;
--
-- g_hash_table_remove_all(nexus->tokens[id].token);
--
-- elems = g_strsplit(token_str, "&", 0);
--
-- for (cur = elems; *cur != NULL; cur++) {
-- tokens = g_strsplit(*cur, "=", 2);
-- g_hash_table_insert(nexus->tokens[id].token, tokens[0], tokens[1]);
-- /* Don't free each of the tokens, only the array. */
-- g_free(tokens);
-- }
-- g_strfreev(elems);
-- g_free(token_str);
--
-- if (secret)
-- nexus->tokens[id].secret = xmlnode_get_data(secret);
-- else
-- nexus->tokens[id].secret = NULL;
--
-- /* Yay for MS using ISO-8601 */
-- expiry_str = xmlnode_get_data(expires);
-- nexus->tokens[id].expiry = purple_str_to_time(expiry_str,
-- FALSE, NULL, NULL, NULL);
-- g_free(expiry_str);
--
-- purple_debug_info("msn", "Updated ticket for domain '%s', expires at %" G_GINT64_FORMAT ".\n",
-- ticket_domains[id][SSO_VALID_TICKET_DOMAIN],
-- (gint64)nexus->tokens[id].expiry);
-- return TRUE;
--}
--
--static gboolean
--nexus_parse_collection(MsnNexus *nexus, int id, xmlnode *collection)
--{
-- xmlnode *node;
-- gboolean result;
--
-- node = xmlnode_get_child(collection, "RequestSecurityTokenResponse");
--
-- if (!node)
-- return FALSE;
--
-- result = TRUE;
-- for (; node && result; node = node->next) {
-- xmlnode *endpoint = xmlnode_get_child(node, "AppliesTo/EndpointReference/Address");
-- char *address = xmlnode_get_data(endpoint);
--
-- if (g_str_equal(address, "http://Passport.NET/tb")) {
-- /* This node contains the stuff for updating tokens. */
-- char *data;
-- xmlnode *cipher = xmlnode_get_child(node, "RequestedSecurityToken/EncryptedData/CipherData/CipherValue");
-- xmlnode *secret = xmlnode_get_child(node, "RequestedProofToken/BinarySecret");
--
-- g_free(nexus->cipher);
-- nexus->cipher = xmlnode_get_data(cipher);
-- data = xmlnode_get_data(secret);
-- g_free(nexus->secret);
-- nexus->secret = (char *)purple_base64_decode(data, NULL);
-- g_free(data);
--
-- } else {
-- result = nexus_parse_token(nexus, id, node);
-- }
-- g_free(address);
-- }
--
-- return result;
--}
--
--static void
--nexus_got_response_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
--{
-- MsnNexus *nexus = data;
-- MsnSession *session = nexus->session;
-- const char *ticket;
-- char *response;
--
-- if (resp == NULL) {
-- msn_session_set_error(session, MSN_ERROR_SERVCONN, _("Windows Live ID authentication:Unable to connect"));
-- return;
-- }
--
-- if (!nexus_parse_collection(nexus, -1,
-- xmlnode_get_child(resp->xml,
-- "Body/RequestSecurityTokenResponseCollection"))) {
-- msn_session_set_error(session, MSN_ERROR_SERVCONN, _("Windows Live ID authentication:Invalid response"));
-- return;
-- }
--
-- ticket = msn_nexus_get_token_str(nexus, MSN_AUTH_MESSENGER);
-- response = msn_rps_encrypt(nexus);
-- msn_got_login_params(session, ticket, response);
-- g_free(response);
--}
--
--/*when connect, do the SOAP Style windows Live ID authentication */
--void
--msn_nexus_connect(MsnNexus *nexus)
--{
-- MsnSession *session = nexus->session;
-- const char *username;
-- const char *password;
-- char *password_xml;
-- GString *domains;
-- char *request;
-- int i;
--
-- MsnSoapMessage *soap;
--
-- purple_debug_info("msn", "Starting Windows Live ID authentication\n");
-- msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE);
--
-- username = purple_account_get_username(session->account);
-- password = purple_connection_get_password(session->account->gc);
-- if (g_utf8_strlen(password, -1) > 16) {
-- /* max byte size for 16 utf8 characters is 64 + 1 for the null */
-- gchar truncated[65];
-- g_utf8_strncpy(truncated, password, 16);
-- password_xml = g_markup_escape_text(truncated, -1);
-- } else {
-- password_xml = g_markup_escape_text(password, -1);
-- }
--
-- purple_debug_info("msn", "Logging on %s, with policy '%s', nonce '%s'\n",
-- username, nexus->policy, nexus->nonce);
--
-- domains = g_string_new(NULL);
-- for (i = 0; i < nexus->token_len; i++) {
-- g_string_append_printf(domains, MSN_SSO_RST_TEMPLATE,
-- i+1,
-- ticket_domains[i][SSO_VALID_TICKET_DOMAIN],
-- ticket_domains[i][SSO_VALID_TICKET_POLICY] != NULL ?
-- ticket_domains[i][SSO_VALID_TICKET_POLICY] :
-- nexus->policy);
-- }
--
-- request = g_strdup_printf(MSN_SSO_TEMPLATE, username, password_xml, domains->str);
-- g_free(password_xml);
-- g_string_free(domains, TRUE);
--
-- soap = msn_soap_message_new(NULL, xmlnode_from_str(request, -1));
-- g_free(request);
-- msn_soap_message_send(session, soap, MSN_SSO_SERVER, SSO_POST_URL, TRUE,
-- nexus_got_response_cb, nexus);
--}
--
--static void
--nexus_got_update_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
--{
-- MsnNexusUpdateData *ud = data;
-- MsnNexus *nexus = ud->nexus;
-- char iv[8] = {0,0,0,0,0,0,0,0};
-- xmlnode *enckey;
-- char *tmp;
-- char *nonce;
-- gsize len;
-- char *key;
-- GSList *updates;
--
--#if 0
-- char *decrypted_pp;
--#endif
-- char *decrypted_data;
--
-- if (resp == NULL)
-- return;
--
-- purple_debug_info("msn", "Got Update Response for %s.\n", ticket_domains[ud->id][SSO_VALID_TICKET_DOMAIN]);
--
-- enckey = xmlnode_get_child(resp->xml, "Header/Security/DerivedKeyToken");
-- while (enckey) {
-- if (g_str_equal(xmlnode_get_attrib(enckey, "Id"), "EncKey"))
-- break;
-- enckey = xmlnode_get_next_twin(enckey);
-- }
-- if (!enckey) {
-- purple_debug_error("msn", "Invalid response in token update.\n");
-- return;
-- }
--
-- tmp = xmlnode_get_data(xmlnode_get_child(enckey, "Nonce"));
-- nonce = (char *)purple_base64_decode(tmp, &len);
-- key = rps_create_key(nexus->secret, 24, nonce, len);
-- g_free(tmp);
-- g_free(nonce);
--
--#if 0
-- /* Don't know what this is for yet */
-- tmp = xmlnode_get_data(xmlnode_get_child(resp->xml,
-- "Header/EncryptedPP/EncryptedData/CipherData/CipherValue"));
-- if (tmp) {
-- decrypted_pp = des3_cbc(key, iv, tmp, len, TRUE);
-- g_free(tmp);
-- purple_debug_info("msn", "Got Response Header EncryptedPP: %s\n", decrypted_pp);
-- g_free(decrypted_pp);
-- }
--#endif
--
-- tmp = xmlnode_get_data(xmlnode_get_child(resp->xml,
-- "Body/EncryptedData/CipherData/CipherValue"));
-- if (tmp) {
-- char *unescaped;
-- xmlnode *rstresponse;
--
-- unescaped = (char *)purple_base64_decode(tmp, &len);
-- g_free(tmp);
--
-- decrypted_data = des3_cbc(key, iv, unescaped, len, TRUE);
-- g_free(unescaped);
-- purple_debug_info("msn", "Got Response Body EncryptedData: %s\n", decrypted_data);
--
-- rstresponse = xmlnode_from_str(decrypted_data, -1);
-- if (g_str_equal(rstresponse->name, "RequestSecurityTokenResponse"))
-- nexus_parse_token(nexus, ud->id, rstresponse);
-- else
-- nexus_parse_collection(nexus, ud->id, rstresponse);
-- g_free(decrypted_data);
-- }
--
-- updates = nexus->tokens[ud->id].updates;
-- nexus->tokens[ud->id].updates = NULL;
-- while (updates != NULL) {
-- MsnNexusUpdateCallback *update = updates->data;
-- if (update->cb)
-- purple_timeout_add(0, update->cb, update->data);
-- g_free(update);
-- updates = g_slist_delete_link(updates, updates);
-- }
--
-- g_free(ud);
-- g_free(key);
--}
--
--void
--msn_nexus_update_token(MsnNexus *nexus, int id, GSourceFunc cb, gpointer data)
--{
-- MsnSession *session = nexus->session;
-- MsnNexusUpdateData *ud;
-- MsnNexusUpdateCallback *update;
-- PurpleCipherContext *sha1;
-- PurpleCipherContext *hmac;
--
-- char *key;
--
-- guchar digest[20];
--
-- struct tm *tm;
-- time_t now;
-- char *now_str;
-- char *timestamp;
-- char *timestamp_b64;
--
-- char *domain;
-- char *domain_b64;
--
-- char *signedinfo;
-- gint32 nonce[6];
-- int i;
-- char *nonce_b64;
-- char *signature_b64;
-- guchar signature[20];
--
-- char *request;
-- MsnSoapMessage *soap;
--
-- update = g_new0(MsnNexusUpdateCallback, 1);
-- update->cb = cb;
-- update->data = data;
--
-- if (nexus->tokens[id].updates != NULL) {
-- /* Update already in progress. Just add to list and return. */
-- purple_debug_info("msn",
-- "Ticket update for user '%s' on domain '%s' in progress. Adding request to queue.\n",
-- purple_account_get_username(session->account),
-- ticket_domains[id][SSO_VALID_TICKET_DOMAIN]);
-- nexus->tokens[id].updates = g_slist_prepend(nexus->tokens[id].updates,
-- update);
-- return;
-- } else {
-- purple_debug_info("msn",
-- "Updating ticket for user '%s' on domain '%s'\n",
-- purple_account_get_username(session->account),
-- ticket_domains[id][SSO_VALID_TICKET_DOMAIN]);
-- nexus->tokens[id].updates = g_slist_prepend(nexus->tokens[id].updates,
-- update);
-- }
--
-- ud = g_new0(MsnNexusUpdateData, 1);
-- ud->nexus = nexus;
-- ud->id = id;
--
-- sha1 = purple_cipher_context_new_by_name("sha1", NULL);
--
-- domain = g_strdup_printf(MSN_SSO_RST_TEMPLATE,
-- id,
-- ticket_domains[id][SSO_VALID_TICKET_DOMAIN],
-- ticket_domains[id][SSO_VALID_TICKET_POLICY] != NULL ?
-- ticket_domains[id][SSO_VALID_TICKET_POLICY] :
-- nexus->policy);
-- purple_cipher_context_append(sha1, (guchar *)domain, strlen(domain));
-- purple_cipher_context_digest(sha1, 20, digest, NULL);
-- domain_b64 = purple_base64_encode(digest, 20);
--
-- now = time(NULL);
-- tm = gmtime(&now);
-- now_str = g_strdup(purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", tm));
-- now += 5*60;
-- tm = gmtime(&now);
-- timestamp = g_strdup_printf(MSN_SSO_TIMESTAMP_TEMPLATE,
-- now_str,
-- purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", tm));
-- purple_cipher_context_reset(sha1, NULL);
-- purple_cipher_context_append(sha1, (guchar *)timestamp, strlen(timestamp));
-- purple_cipher_context_digest(sha1, 20, digest, NULL);
-- timestamp_b64 = purple_base64_encode(digest, 20);
-- g_free(now_str);
--
-- purple_cipher_context_destroy(sha1);
--
-- signedinfo = g_strdup_printf(MSN_SSO_SIGNEDINFO_TEMPLATE,
-- id,
-- domain_b64,
-- timestamp_b64);
--
-- for (i = 0; i < 6; i++)
-- nonce[i] = rand();
-- nonce_b64 = purple_base64_encode((guchar *)&nonce, sizeof(nonce));
--
-- key = rps_create_key(nexus->secret, 24, (char *)nonce, sizeof(nonce));
-- hmac = purple_cipher_context_new_by_name("hmac", NULL);
-- purple_cipher_context_set_option(hmac, "hash", "sha1");
-- purple_cipher_context_set_key_with_len(hmac, (guchar *)key, 24);
-- purple_cipher_context_append(hmac, (guchar *)signedinfo, strlen(signedinfo));
-- purple_cipher_context_digest(hmac, 20, signature, NULL);
-- purple_cipher_context_destroy(hmac);
-- signature_b64 = purple_base64_encode(signature, 20);
--
-- request = g_strdup_printf(MSN_SSO_TOKEN_UPDATE_TEMPLATE,
-- nexus->cipher,
-- nonce_b64,
-- timestamp,
-- signedinfo,
-- signature_b64,
-- domain);
--
-- g_free(nonce_b64);
-- g_free(domain_b64);
-- g_free(timestamp_b64);
-- g_free(timestamp);
-- g_free(key);
-- g_free(signature_b64);
-- g_free(signedinfo);
-- g_free(domain);
--
-- soap = msn_soap_message_new(NULL, xmlnode_from_str(request, -1));
-- g_free(request);
-- msn_soap_message_send(session, soap, MSN_SSO_SERVER, SSO_POST_URL, TRUE,
-- nexus_got_update_cb, ud);
--}
--
--GHashTable *
--msn_nexus_get_token(MsnNexus *nexus, MsnAuthDomains id)
--{
-- g_return_val_if_fail(nexus != NULL, NULL);
-- g_return_val_if_fail(id < nexus->token_len, NULL);
--
-- return nexus->tokens[id].token;
--}
--
--const char *
--msn_nexus_get_token_str(MsnNexus *nexus, MsnAuthDomains id)
--{
-- static char buf[1024];
-- GHashTable *token = msn_nexus_get_token(nexus, id);
-- const char *msn_t;
-- const char *msn_p;
-- gint ret;
--
-- g_return_val_if_fail(token != NULL, NULL);
--
-- msn_t = g_hash_table_lookup(token, "t");
-- msn_p = g_hash_table_lookup(token, "p");
--
-- g_return_val_if_fail(msn_t != NULL, NULL);
-- g_return_val_if_fail(msn_p != NULL, NULL);
--
-- ret = g_snprintf(buf, sizeof(buf) - 1, "t=%s&p=%s", msn_t, msn_p);
-- g_return_val_if_fail(ret != -1, NULL);
--
-- return buf;
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/nexus.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/nexus.h
---- pidgin-2.10.7/libpurple/protocols/msn/nexus.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/nexus.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,219 +0,0 @@
--/**
-- * @file nexus.h MSN Nexus functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_NEXUS_H
--#define MSN_NEXUS_H
--
--#include "internal.h"
--
--typedef struct _MsnNexus MsnNexus;
--typedef struct _MsnTicketToken MsnTicketToken;
--
--/* Index into ticket_tokens in nexus.c Keep updated! */
--typedef enum
--{
-- MSN_AUTH_MESSENGER = 0,
-- MSN_AUTH_MESSENGER_WEB = 1,
-- MSN_AUTH_CONTACTS = 2,
-- MSN_AUTH_LIVE_SECURE = 3,
-- MSN_AUTH_STORAGE = 4,
-- MSN_AUTH_WHATSNEW = 5
--} MsnAuthDomains;
--
--#define MSN_SSO_SERVER "login.live.com"
--#define SSO_POST_URL "/RST.srf"
--
--#define MSN_SSO_RST_TEMPLATE \
--"<wst:RequestSecurityToken xmlns=\"http://schemas.xmlsoap.org/ws/2004/04/trust\" Id=\"RST%d\">"\
-- "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\
-- "<wsp:AppliesTo xmlns=\"http://schemas.xmlsoap.org/ws/2002/12/policy\">"\
-- "<wsa:EndpointReference xmlns=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">"\
-- "<wsa:Address>%s</wsa:Address>"\
-- "</wsa:EndpointReference>"\
-- "</wsp:AppliesTo>"\
-- "<wsse:PolicyReference xmlns=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" URI=\"%s\"></wsse:PolicyReference>"\
--"</wst:RequestSecurityToken>"
--
--#define MSN_SSO_TEMPLATE "<?xml version='1.0' encoding='utf-8'?>"\
--"<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-- " xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\""\
-- " xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\""\
-- " xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\""\
-- " xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\""\
-- " xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\""\
-- " xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\""\
-- " xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">"\
-- "<Header>"\
-- "<ps:AuthInfo"\
-- " xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\""\
-- " Id=\"PPAuthInfo\">"\
-- "<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>"\
-- "<ps:BinaryVersion>4</ps:BinaryVersion>"\
-- "<ps:UIVersion>1</ps:UIVersion>"\
-- "<ps:Cookies></ps:Cookies>"\
-- "<ps:RequestParams>AQAAAAIAAABsYwQAAAAxMDMz</ps:RequestParams>"\
-- "</ps:AuthInfo>"\
-- "<wsse:Security>"\
-- "<wsse:UsernameToken Id=\"user\">"\
-- "<wsse:Username>%s</wsse:Username>"\
-- "<wsse:Password>%s</wsse:Password>"\
-- "</wsse:UsernameToken>"\
-- "</wsse:Security>"\
-- "</Header>"\
-- "<Body>"\
-- "<ps:RequestMultipleSecurityTokens"\
-- " xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\""\
-- " Id=\"RSTS\">"\
-- "<wst:RequestSecurityToken Id=\"RST0\">"\
-- "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\
-- "<wsp:AppliesTo>"\
-- "<wsa:EndpointReference>"\
-- "<wsa:Address>http://Passport.NET/tb</wsa:Address>"\
-- "</wsa:EndpointReference>"\
-- "</wsp:AppliesTo>"\
-- "</wst:RequestSecurityToken>"\
-- "%s" /* Other RSTn tokens */\
-- "</ps:RequestMultipleSecurityTokens>"\
-- "</Body>"\
--"</Envelope>"
--
--#define MSN_SSO_AUTHINFO_TEMPLATE \
--"<ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"PPAuthInfo\">"\
-- "<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>"\
-- "<ps:BinaryVersion>4</ps:BinaryVersion>"\
-- "<ps:UIVersion>1</ps:UIVersion>"\
-- "<ps:Cookies></ps:Cookies>"\
-- "<ps:RequestParams>AQAAAAIAAABsYwQAAAA0MTA1</ps:RequestParams>"\
--"</ps:AuthInfo>"
--/* Not sure what's editable here, so I'll just hard-code the SHA1 hash */
--#define MSN_SSO_AUTHINFO_SHA1_BASE64 "d2IeTF4DAkPEa/tVETHznsivEpc="
--
--#define MSN_SSO_TIMESTAMP_TEMPLATE \
--"<wsu:Timestamp xmlns=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" Id=\"Timestamp\">"\
-- "<wsu:Created>%s</wsu:Created>"\
-- "<wsu:Expires>%s</wsu:Expires>"\
--"</wsu:Timestamp>"
--
--#define MSN_SSO_SIGNEDINFO_TEMPLATE \
--"<SignedInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\">"\
-- "<CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></CanonicalizationMethod>"\
-- "<SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#hmac-sha1\"></SignatureMethod>"\
-- "<Reference URI=\"#RST%d\">"\
-- "<Transforms>"\
-- "<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform>"\
-- "</Transforms>"\
-- "<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod>"\
-- "<DigestValue>%s</DigestValue>"\
-- "</Reference>"\
-- "<Reference URI=\"#Timestamp\">"\
-- "<Transforms>"\
-- "<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform>"\
-- "</Transforms>"\
-- "<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod>"\
-- "<DigestValue>%s</DigestValue>"\
-- "</Reference>"\
-- "<Reference URI=\"#PPAuthInfo\">"\
-- "<Transforms>"\
-- "<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform>"\
-- "</Transforms>"\
-- "<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod>"\
-- "<DigestValue>" MSN_SSO_AUTHINFO_SHA1_BASE64 "</DigestValue>"\
-- "</Reference>"\
--"</SignedInfo>"
--
--#define MSN_SSO_TOKEN_UPDATE_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<Envelope"\
-- " xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\""\
-- " xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\""\
-- " xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\""\
-- " xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\""\
-- " xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\""\
-- " xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\""\
-- " xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\""\
-- " xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">"\
-- "<Header>"\
-- MSN_SSO_AUTHINFO_TEMPLATE /* ps:AuthInfo */ \
-- "<wsse:Security>"\
-- "<EncryptedData xmlns=\"http://www.w3.org/2001/04/xmlenc#\" Id=\"BinaryDAToken0\" Type=\"http://www.w3.org/2001/04/xmlenc#Element\">"\
-- "<EncryptionMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#tripledes-cbc\"></EncryptionMethod>"\
-- "<ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">"\
-- "<ds:KeyName>http://Passport.NET/STS</ds:KeyName>"\
-- "</ds:KeyInfo>"\
-- "<CipherData>"\
-- "<CipherValue>%s</CipherValue>"\
-- "</CipherData>"\
-- "</EncryptedData>"\
-- "<wssc:DerivedKeyToken Id=\"SignKey\">"\
-- "<wsse:RequestedTokenReference>"\
-- "<wsse:KeyIdentifier ValueType=\"http://docs.oasis-open.org/wss/2004/XX/oasis-2004XX-wss-saml-token-profile-1.0#SAMLAssertionID\" />"\
-- "<wsse:Reference URI=\"#BinaryDAToken0\" />"\
-- "</wsse:RequestedTokenReference>"\
-- "<wssc:Nonce>%s</wssc:Nonce>"\
-- "</wssc:DerivedKeyToken>"\
-- "%s" /* wsu:Timestamp */\
-- "<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\">"\
-- "%s" /* SignedInfo */\
-- "<SignatureValue>%s</SignatureValue>"\
-- "<KeyInfo>"\
-- "<wsse:SecurityTokenReference>"\
-- "<wsse:Reference URI=\"#SignKey\" />"\
-- "</wsse:SecurityTokenReference>"\
-- "</KeyInfo>"\
-- "</Signature>"\
-- "</wsse:Security>"\
-- "</Header>"\
-- "<Body>"\
-- "%s" /* wst:RequestSecurityToken */ \
-- "</Body>"\
--"</Envelope>"
--
--struct _MsnTicketToken {
-- GHashTable *token;
-- char *secret;
-- time_t expiry;
-- GSList *updates;
--};
--
--struct _MsnNexus
--{
-- MsnSession *session;
--
-- /* From server via USR command */
-- char *policy;
-- char *nonce;
--
-- /* From server via SOAP stuff */
-- char *cipher;
-- char *secret;
-- MsnTicketToken *tokens;
-- int token_len;
--};
--
--void msn_nexus_connect(MsnNexus *nexus);
--MsnNexus *msn_nexus_new(MsnSession *session);
--void msn_nexus_destroy(MsnNexus *nexus);
--GHashTable *msn_nexus_get_token(MsnNexus *nexus, MsnAuthDomains id);
--const char *msn_nexus_get_token_str(MsnNexus *nexus, MsnAuthDomains id);
--void msn_nexus_update_token(MsnNexus *nexus, int id, GSourceFunc cb, gpointer data);
--
--#endif /* MSN_NEXUS_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/notification.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/notification.c
---- pidgin-2.10.7/libpurple/protocols/msn/notification.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/notification.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,2471 +0,0 @@
--/**
-- * @file notification.c Notification server functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "cipher.h"
--#include "core.h"
--#include "debug.h"
--
--#include "notification.h"
--
--#include "contact.h"
--#include "error.h"
--#include "msnutils.h"
--#include "state.h"
--#include "userlist.h"
--
--static MsnTable *cbs_table;
--
--/**************************************************************************
-- * Main
-- **************************************************************************/
--
--static void
--destroy_cb(MsnServConn *servconn)
--{
-- MsnNotification *notification;
--
-- notification = servconn->cmdproc->data;
-- g_return_if_fail(notification != NULL);
--
-- msn_notification_destroy(notification);
--}
--
--MsnNotification *
--msn_notification_new(MsnSession *session)
--{
-- MsnNotification *notification;
-- MsnServConn *servconn;
--
-- g_return_val_if_fail(session != NULL, NULL);
--
-- notification = g_new0(MsnNotification, 1);
--
-- notification->session = session;
-- notification->servconn = servconn = msn_servconn_new(session, MSN_SERVCONN_NS);
-- msn_servconn_set_destroy_cb(servconn, destroy_cb);
--
-- notification->cmdproc = servconn->cmdproc;
-- notification->cmdproc->data = notification;
-- notification->cmdproc->cbs_table = cbs_table;
--
-- return notification;
--}
--
--void
--msn_notification_destroy(MsnNotification *notification)
--{
-- notification->cmdproc->data = NULL;
--
-- msn_servconn_set_destroy_cb(notification->servconn, NULL);
--
-- msn_servconn_destroy(notification->servconn);
--
-- g_free(notification);
--}
--
--/**************************************************************************
-- * Connect
-- **************************************************************************/
--
--static void
--connect_cb(MsnServConn *servconn)
--{
-- MsnCmdProc *cmdproc;
-- MsnSession *session;
-- MsnTransaction *trans;
-- GString *vers;
-- const char *ver_str;
-- int i;
--
-- g_return_if_fail(servconn != NULL);
--
-- cmdproc = servconn->cmdproc;
-- session = servconn->session;
--
-- vers = g_string_new("");
--
-- for (i = WLM_MAX_PROTOCOL; i >= WLM_MIN_PROTOCOL; i--)
-- g_string_append_printf(vers, " MSNP%d", i);
--
-- g_string_append(vers, " CVR0");
--
-- if (session->login_step == MSN_LOGIN_STEP_START)
-- msn_session_set_login_step(session, MSN_LOGIN_STEP_HANDSHAKE);
-- else
-- msn_session_set_login_step(session, MSN_LOGIN_STEP_HANDSHAKE2);
--
-- /* Skip the initial space */
-- ver_str = (vers->str + 1);
-- trans = msn_transaction_new(cmdproc, "VER", "%s", ver_str);
-- msn_cmdproc_send_trans(cmdproc, trans);
--
-- g_string_free(vers, TRUE);
--}
--
--gboolean
--msn_notification_connect(MsnNotification *notification, const char *host, int port)
--{
-- MsnServConn *servconn;
--
-- g_return_val_if_fail(notification != NULL, FALSE);
--
-- servconn = notification->servconn;
--
-- msn_servconn_set_connect_cb(servconn, connect_cb);
-- notification->in_use = msn_servconn_connect(servconn, host, port, TRUE);
--
-- return notification->in_use;
--}
--
--void
--msn_notification_disconnect(MsnNotification *notification)
--{
-- g_return_if_fail(notification != NULL);
-- g_return_if_fail(notification->in_use);
--
-- msn_servconn_disconnect(notification->servconn);
--
-- notification->in_use = FALSE;
--}
--
--/**************************************************************************
-- * Login
-- **************************************************************************/
--
--void
--msn_got_login_params(MsnSession *session, const char *ticket, const char *response)
--{
-- MsnCmdProc *cmdproc;
-- MsnTransaction *trans;
--
-- cmdproc = session->notification->cmdproc;
--
-- msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_END);
--
-- trans = msn_transaction_new(cmdproc, "USR", "SSO S %s %s %s", ticket, response, session->guid);
--
-- msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--static void
--cvr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- PurpleAccount *account;
-- MsnTransaction *trans;
--
-- account = cmdproc->session->account;
--
-- trans = msn_transaction_new(cmdproc, "USR", "SSO I %s", purple_account_get_username(account));
-- msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--static void
--usr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnSession *session = cmdproc->session;
--
-- if (!g_ascii_strcasecmp(cmd->params[1], "OK"))
-- {
-- /* authenticate OK */
-- msn_session_set_login_step(session, MSN_LOGIN_STEP_SYN);
-- }
-- else if (!g_ascii_strcasecmp(cmd->params[1], "SSO"))
-- {
-- /* RPS authentication */
--
-- if (session->nexus)
-- msn_nexus_destroy(session->nexus);
--
-- session->nexus = msn_nexus_new(session);
--
-- session->nexus->policy = g_strdup(cmd->params[3]);
-- session->nexus->nonce = g_strdup(cmd->params[4]);
--
-- msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_START);
--
-- msn_nexus_connect(session->nexus);
-- }
--}
--
--static void
--usr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
--{
-- MsnErrorType msnerr = 0;
--
-- switch (error)
-- {
-- case 500:
-- case 601:
-- case 910:
-- case 921:
-- msnerr = MSN_ERROR_SERV_UNAVAILABLE;
-- break;
-- case 911:
-- msnerr = MSN_ERROR_AUTH;
-- break;
-- default:
-- return;
-- break;
-- }
--
-- msn_session_set_error(cmdproc->session, msnerr, NULL);
--}
--
--static void
--ver_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnSession *session;
-- MsnTransaction *trans;
-- PurpleAccount *account;
-- gboolean protocol_supported = FALSE;
-- int proto_ver;
-- size_t i;
--
-- session = cmdproc->session;
-- account = session->account;
--
-- session->protocol_ver = 0;
-- for (i = 1; i < cmd->param_count; i++)
-- {
-- if (sscanf(cmd->params[i], "MSNP%d", &proto_ver) == 1) {
-- if (proto_ver >= WLM_MIN_PROTOCOL
-- && proto_ver <= WLM_MAX_PROTOCOL
-- && proto_ver > session->protocol_ver) {
-- protocol_supported = TRUE;
-- session->protocol_ver = proto_ver;
-- }
-- }
-- }
--
-- if (!protocol_supported)
-- {
-- msn_session_set_error(session, MSN_ERROR_UNSUPPORTED_PROTOCOL,
-- NULL);
-- return;
-- }
--
-- purple_debug_info("msn", "Negotiated protocol version %d with the server.\n", session->protocol_ver);
--
-- /*
-- * Windows Live Messenger 8.5
-- * Notice :CVR String discriminate!
-- * reference of http://www.microsoft.com/globaldev/reference/oslocversion.mspx
-- * to see the Local ID
-- */
-- trans = msn_transaction_new(cmdproc, "CVR",
-- "0x0409 winnt 5.1 i386 MSNMSGR 8.5.1302 BC01 %s",
-- purple_account_get_username(account));
-- msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--/**************************************************************************
-- * Log out
-- **************************************************************************/
--
--static void
--out_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- if (cmd->param_count == 0)
-- msn_session_set_error(cmdproc->session, -1, NULL);
-- else if (!g_ascii_strcasecmp(cmd->params[0], "OTH"))
-- msn_session_set_error(cmdproc->session, MSN_ERROR_SIGN_OTHER,
-- NULL);
-- else if (!g_ascii_strcasecmp(cmd->params[0], "SSD"))
-- msn_session_set_error(cmdproc->session, MSN_ERROR_SERV_DOWN, NULL);
--}
--
--void
--msn_notification_close(MsnNotification *notification)
--{
-- MsnTransaction *trans;
--
-- g_return_if_fail(notification != NULL);
--
-- if (!notification->in_use)
-- return;
--
-- trans = msn_transaction_new(notification->cmdproc, "OUT", NULL);
-- msn_transaction_set_saveable(trans, FALSE);
-- msn_cmdproc_send_trans(notification->cmdproc, trans);
--
-- msn_notification_disconnect(notification);
--}
--
--/**************************************************************************
-- * Messages
-- **************************************************************************/
--
--static void
--msg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-- size_t len)
--{
-- MsnMessage *msg;
--
-- msg = msn_message_new_from_cmd(cmdproc->session, cmd);
--
-- msn_message_parse_payload(msg, payload, len, MSG_LINE_DEM, MSG_BODY_DEM);
-- if (purple_debug_is_verbose())
-- msn_message_show_readable(msg, "Notification", TRUE);
--
-- msn_cmdproc_process_msg(cmdproc, msg);
--
-- msn_message_unref(msg);
--}
--
--static void
--msg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- purple_debug_info("msn", "Processing MSG... \n");
--
-- /* NOTE: cmd is not always cmdproc->last_cmd, sometimes cmd is a queued
-- * command and we are processing it */
-- if (cmd->payload == NULL) {
-- cmdproc->last_cmd->payload_cb = msg_cmd_post;
-- cmd->payload_len = atoi(cmd->params[2]);
-- } else {
-- g_return_if_fail(cmd->payload_cb != NULL);
--
--#if 0 /* glib on win32 doesn't correctly support precision modifiers for a string */
-- purple_debug_info("msn", "MSG payload:{%.*s}\n", (guint)cmd->payload_len, cmd->payload);
--#endif
-- cmd->payload_cb(cmdproc, cmd, cmd->payload, cmd->payload_len);
-- }
--}
--
--/*send Message to Yahoo Messenger*/
--void
--msn_notification_send_uum(MsnSession *session, MsnMessage *msg)
--{
-- MsnCmdProc *cmdproc;
-- MsnTransaction *trans;
-- char *payload;
-- gsize payload_len;
-- int type;
-- MsnUser *user;
-- int network;
--
-- g_return_if_fail(msg != NULL);
--
-- cmdproc = session->notification->cmdproc;
--
-- payload = msn_message_gen_payload(msg, &payload_len);
-- type = msg->type;
-- user = msn_userlist_find_user(session->userlist, msg->remote_user);
-- if (user)
-- network = msn_user_get_network(user);
-- else
-- network = MSN_NETWORK_PASSPORT;
--
-- purple_debug_info("msn",
-- "send UUM, payload{%s}, strlen:%" G_GSIZE_FORMAT ", len:%" G_GSIZE_FORMAT "\n",
-- payload, strlen(payload), payload_len);
--
-- trans = msn_transaction_new(cmdproc, "UUM", "%s %d %d %" G_GSIZE_FORMAT,
-- msg->remote_user, network, type, payload_len);
-- msn_transaction_set_payload(trans, payload, strlen(payload));
-- msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--/*Yahoo msg process*/
--static void
--ubm_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- purple_debug_info("msn", "Processing UBM... \n");
--
-- /* NOTE: cmd is not always cmdproc->last_cmd, sometimes cmd is a queued
-- * command and we are processing it */
-- if (cmd->payload == NULL) {
-- cmdproc->last_cmd->payload_cb = msg_cmd_post;
-- cmd->payload_len = atoi(cmd->params[5]);
-- } else {
-- g_return_if_fail(cmd->payload_cb != NULL);
--
-- purple_debug_info("msn", "UBM payload:{%.*s}\n", (guint)(cmd->payload_len), cmd->payload);
-- msg_cmd_post(cmdproc, cmd, cmd->payload, cmd->payload_len);
-- }
--}
--
--/**************************************************************************
-- * Challenges
-- * we use MD5 to caculate the Challenges
-- **************************************************************************/
--static void
--chl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnTransaction *trans;
-- char buf[33];
--
-- msn_handle_chl(cmd->params[1], buf);
-- trans = msn_transaction_new(cmdproc, "QRY", "%s 32", MSNP15_WLM_PRODUCT_ID);
--
-- msn_transaction_set_payload(trans, buf, 32);
--
-- msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--/**************************************************************************
-- * Buddy Lists
-- **************************************************************************/
--
--typedef struct MsnFqyCbData {
-- MsnFqyCb cb;
-- gpointer data;
--} MsnFqyCbData;
--
--/* add contact to xmlnode */
--static void
--msn_add_contact_xml(xmlnode *mlNode, const char *passport, MsnListOp list_op, MsnNetwork networkId)
--{
-- xmlnode *d_node,*c_node;
-- char **tokens;
-- const char *email,*domain;
-- char fmt_str[3];
--
-- g_return_if_fail(passport != NULL);
--
-- purple_debug_info("msn", "Passport: %s, type: %d\n", passport, networkId);
-- tokens = g_strsplit(passport, "@", 2);
-- email = tokens[0];
-- domain = tokens[1];
--
-- if (email == NULL || domain == NULL) {
-- purple_debug_error("msn", "Invalid passport (%s) specified to add to contact xml.\n", passport);
-- g_strfreev(tokens);
-- g_return_if_reached();
-- }
--
-- /*find a domain Node*/
-- for (d_node = xmlnode_get_child(mlNode, "d"); d_node;
-- d_node = xmlnode_get_next_twin(d_node)) {
-- const char *attr = xmlnode_get_attrib(d_node,"n");
-- if (attr == NULL)
-- continue;
-- if (!strcmp(attr, domain))
-- break;
-- }
--
-- if (d_node == NULL) {
-- /*domain not found, create a new domain Node*/
-- purple_debug_info("msn", "Didn't find existing domain node, adding one.\n");
-- d_node = xmlnode_new("d");
-- xmlnode_set_attrib(d_node, "n", domain);
-- xmlnode_insert_child(mlNode, d_node);
-- }
--
-- /*create contact node*/
-- c_node = xmlnode_new("c");
-- xmlnode_set_attrib(c_node, "n", email);
--
-- if (list_op != 0) {
-- purple_debug_info("msn", "list_op: %d\n", list_op);
-- g_snprintf(fmt_str, sizeof(fmt_str), "%d", list_op);
-- xmlnode_set_attrib(c_node, "l", fmt_str);
-- }
--
-- if (networkId != MSN_NETWORK_UNKNOWN) {
-- g_snprintf(fmt_str, sizeof(fmt_str), "%d", networkId);
-- /*mobile*/
-- /*type_str = g_strdup_printf("4");*/
-- xmlnode_set_attrib(c_node, "t", fmt_str);
-- }
--
-- xmlnode_insert_child(d_node, c_node);
--
-- g_strfreev(tokens);
--}
--
--static void
--msn_notification_post_adl(MsnCmdProc *cmdproc, const char *payload, int payload_len)
--{
-- MsnTransaction *trans;
-- purple_debug_info("msn", "Sending ADL with payload: %s\n", payload);
-- trans = msn_transaction_new(cmdproc, "ADL", "%i", payload_len);
-- msn_transaction_set_payload(trans, payload, payload_len);
-- msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--static void
--msn_notification_post_rml(MsnCmdProc *cmdproc, const char *payload, int payload_len)
--{
-- MsnTransaction *trans;
-- purple_debug_info("msn", "Sending RML with payload: %s\n", payload);
-- trans = msn_transaction_new(cmdproc, "RML", "%i", payload_len);
-- msn_transaction_set_payload(trans, payload, payload_len);
-- msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--void
--msn_notification_send_fqy(MsnSession *session,
-- const char *payload, int payload_len,
-- MsnFqyCb cb,
-- gpointer cb_data)
--{
-- MsnTransaction *trans;
-- MsnCmdProc *cmdproc;
-- MsnFqyCbData *data;
--
-- cmdproc = session->notification->cmdproc;
--
-- data = g_new(MsnFqyCbData, 1);
-- data->cb = cb;
-- data->data = cb_data;
--
-- trans = msn_transaction_new(cmdproc, "FQY", "%d", payload_len);
-- msn_transaction_set_payload(trans, payload, payload_len);
-- msn_transaction_set_data(trans, data);
-- msn_transaction_set_data_free(trans, g_free);
-- msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--static void
--update_contact_network(MsnSession *session, const char *passport, MsnNetwork network, gpointer unused)
--{
-- MsnUser *user;
--
-- if (network == MSN_NETWORK_UNKNOWN)
-- {
-- purple_debug_warning("msn",
-- "Ignoring user %s about which server knows nothing.\n",
-- passport);
-- /* Decrement the count for unknown results so that we'll continue login.
-- Also, need to finish the login process here as well, because ADL OK
-- will not be called. */
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "ADL/FQY count is %d\n", session->adl_fqy);
-- if (--session->adl_fqy == 0)
-- msn_session_finish_login(session);
-- return;
-- }
--
-- /* TODO: Also figure out how to update membership lists */
-- user = msn_userlist_find_user(session->userlist, passport);
-- if (user) {
-- xmlnode *adl_node;
-- char *payload;
-- int payload_len;
--
-- msn_user_set_network(user, network);
--
-- adl_node = xmlnode_new("ml");
-- xmlnode_set_attrib(adl_node, "l", "1");
-- msn_add_contact_xml(adl_node, passport,
-- user->list_op & MSN_LIST_OP_MASK, network);
-- payload = xmlnode_to_str(adl_node, &payload_len);
-- msn_notification_post_adl(session->notification->cmdproc, payload, payload_len);
-- g_free(payload);
-- xmlnode_free(adl_node);
-- } else {
-- purple_debug_error("msn",
-- "Got FQY update for unknown user %s on network %d.\n",
-- passport, network);
-- }
--}
--
--/*dump contact info to NS*/
--void
--msn_notification_dump_contact(MsnSession *session)
--{
-- MsnUser *user;
-- GList *l;
-- xmlnode *adl_node;
-- xmlnode *fqy_node;
-- char *payload;
-- int payload_len;
-- int adl_count = 0;
-- int fqy_count = 0;
-- PurpleConnection *pc;
-- const char *display_name;
--
-- adl_node = xmlnode_new("ml");
-- adl_node->child = NULL;
-- xmlnode_set_attrib(adl_node, "l", "1");
-- fqy_node = xmlnode_new("ml");
--
-- /*get the userlist*/
-- for (l = session->userlist->users; l != NULL; l = l->next) {
-- user = l->data;
--
-- /* skip RL & PL during initial dump */
-- if (!(user->list_op & MSN_LIST_OP_MASK))
-- continue;
--
-- if (user->passport && !strcmp(user->passport, "messenger@microsoft.com"))
-- continue;
--
-- if ((user->list_op & MSN_LIST_OP_MASK & ~MSN_LIST_FL_OP)
-- == (MSN_LIST_AL_OP | MSN_LIST_BL_OP)) {
-- /* The server will complain if we send it a user on both the
-- Allow and Block lists. So assume they're on the Block list
-- and remove them from the Allow list in the membership lists to
-- stop this from happening again. */
-- purple_debug_warning("msn",
-- "User %s is on both Allow and Block list; "
-- "removing from Allow list.\n",
-- user->passport);
-- msn_user_unset_op(user, MSN_LIST_AL_OP);
-- }
--
-- if (user->networkid != MSN_NETWORK_UNKNOWN) {
-- msn_add_contact_xml(adl_node, user->passport,
-- user->list_op & MSN_LIST_OP_MASK,
-- user->networkid);
--
-- /* each ADL command may contain up to 150 contacts */
-- if (++adl_count % 150 == 0) {
-- payload = xmlnode_to_str(adl_node, &payload_len);
--
-- /* ADL's are returned all-together */
-- session->adl_fqy++;
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "Posting ADL, count is %d\n",
-- session->adl_fqy);
--
-- msn_notification_post_adl(session->notification->cmdproc,
-- payload, payload_len);
--
-- g_free(payload);
-- xmlnode_free(adl_node);
--
-- adl_node = xmlnode_new("ml");
-- adl_node->child = NULL;
-- xmlnode_set_attrib(adl_node, "l", "1");
-- }
-- } else {
-- /* FQY's are returned one-at-a-time */
-- session->adl_fqy++;
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "Adding FQY address, count is %d\n",
-- session->adl_fqy);
--
-- msn_add_contact_xml(fqy_node, user->passport, 0, user->networkid);
--
-- /* each FQY command may contain up to 150 contacts, probably */
-- if (++fqy_count % 150 == 0) {
-- payload = xmlnode_to_str(fqy_node, &payload_len);
--
-- msn_notification_send_fqy(session, payload, payload_len,
-- update_contact_network, NULL);
--
-- g_free(payload);
-- xmlnode_free(fqy_node);
-- fqy_node = xmlnode_new("ml");
-- }
-- }
-- }
--
-- /* Send the rest, or just an empty one to let the server set us online */
-- if (adl_count == 0 || adl_count % 150 != 0) {
-- payload = xmlnode_to_str(adl_node, &payload_len);
--
-- /* ADL's are returned all-together */
-- session->adl_fqy++;
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "Posting ADL, count is %d\n",
-- session->adl_fqy);
--
-- msn_notification_post_adl(session->notification->cmdproc, payload, payload_len);
--
-- g_free(payload);
-- }
--
-- if (fqy_count % 150 != 0) {
-- payload = xmlnode_to_str(fqy_node, &payload_len);
--
-- msn_notification_send_fqy(session, payload, payload_len,
-- update_contact_network, NULL);
--
-- g_free(payload);
-- }
--
-- xmlnode_free(adl_node);
-- xmlnode_free(fqy_node);
--
-- msn_session_activate_login_timeout(session);
--
-- pc = purple_account_get_connection(session->account);
-- display_name = purple_connection_get_display_name(pc);
-- if (display_name
-- && strcmp(display_name,
-- purple_account_get_username(session->account))) {
-- msn_set_public_alias(pc, display_name, NULL, NULL);
-- }
--
--}
--
--static void
--blp_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
--}
--
--static void
--adl_cmd_parse(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-- size_t len)
--{
-- xmlnode *root, *domain_node;
--
-- purple_debug_misc("msn", "Parsing received ADL XML data\n");
--
-- g_return_if_fail(payload != NULL);
--
-- root = xmlnode_from_str(payload, (gssize) len);
--
-- if (root == NULL) {
-- purple_debug_info("msn", "Invalid XML in ADL!\n");
-- return;
-- }
-- for (domain_node = xmlnode_get_child(root, "d");
-- domain_node;
-- domain_node = xmlnode_get_next_twin(domain_node)) {
-- xmlnode *contact_node = NULL;
--
-- for (contact_node = xmlnode_get_child(domain_node, "c");
-- contact_node;
-- contact_node = xmlnode_get_next_twin(contact_node)) {
-- const gchar *list;
-- gint list_op = 0;
--
-- list = xmlnode_get_attrib(contact_node, "l");
-- if (list != NULL) {
-- list_op = atoi(list);
-- }
--
-- if (list_op & MSN_LIST_RL_OP) {
-- /* someone is adding us */
-- msn_get_contact_list(cmdproc->session, MSN_PS_PENDING_LIST, NULL);
-- }
-- }
-- }
--
-- xmlnode_free(root);
--}
--
--static void
--adl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnSession *session;
--
-- g_return_if_fail(cmdproc != NULL);
-- g_return_if_fail(cmdproc->session != NULL);
-- g_return_if_fail(cmdproc->last_cmd != NULL);
-- g_return_if_fail(cmd != NULL);
--
-- session = cmdproc->session;
--
-- if (!strcmp(cmd->params[1], "OK")) {
-- /* ADL ack */
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "ADL ACK, count is %d\n",
-- session->adl_fqy);
-- if (--session->adl_fqy == 0)
-- msn_session_finish_login(session);
-- } else {
-- cmdproc->last_cmd->payload_cb = adl_cmd_parse;
-- cmd->payload_len = atoi(cmd->params[1]);
-- }
--
-- return;
--}
--
--static void
--adl_error_parse(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
--{
-- MsnSession *session;
-- PurpleAccount *account;
-- PurpleConnection *gc;
-- int error = GPOINTER_TO_INT(cmd->payload_cbdata);
--
-- session = cmdproc->session;
-- account = session->account;
-- gc = purple_account_get_connection(account);
--
-- if (error == 241) {
-- /* khc: some googling suggests that error 241 means the buddy is somehow
-- in the local list, but not the server list, and that we should add
-- those buddies to the addressbook. For now I will just notify the user
-- about the raw payload, because I am lazy */
-- xmlnode *adl = xmlnode_from_str(payload, len);
-- GString *emails = g_string_new(NULL);
--
-- xmlnode *domain = xmlnode_get_child(adl, "d");
-- while (domain) {
-- const char *domain_str = xmlnode_get_attrib(domain, "n");
-- xmlnode *contact = xmlnode_get_child(domain, "c");
-- while (contact) {
-- g_string_append_printf(emails, "%s@%s\n",
-- xmlnode_get_attrib(contact, "n"), domain_str);
-- contact = xmlnode_get_next_twin(contact);
-- }
-- domain = xmlnode_get_next_twin(domain);
-- }
--
-- purple_notify_error(gc, NULL,
-- _("The following users are missing from your addressbook"),
-- emails->str);
-- g_string_free(emails, TRUE);
-- xmlnode_free(adl);
-- }
-- else
-- {
-- char *adl = g_strndup(payload, len);
-- char *reason = g_strdup_printf(_("Unknown error (%d): %s"),
-- error, adl);
-- g_free(adl);
--
-- purple_notify_error(gc, NULL, _("Unable to add user"), reason);
-- g_free(reason);
-- }
--}
--
--static void
--adl_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
--{
-- MsnSession *session;
-- PurpleAccount *account;
-- PurpleConnection *gc;
-- MsnCommand *cmd = cmdproc->last_cmd;
--
-- session = cmdproc->session;
-- account = session->account;
-- gc = purple_account_get_connection(account);
--
-- purple_debug_error("msn", "ADL error\n");
-- if (cmd->param_count > 1) {
-- cmd->payload_cb = adl_error_parse;
-- cmd->payload_len = atoi(cmd->params[1]);
-- cmd->payload_cbdata = GINT_TO_POINTER(error);
-- } else {
-- char *reason = g_strdup_printf(_("Unknown error (%d)"), error);
-- purple_notify_error(gc, NULL, _("Unable to add user"), reason);
-- g_free(reason);
-- }
--}
--
--static void
--rml_error_parse(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
--{
-- MsnSession *session;
-- PurpleAccount *account;
-- PurpleConnection *gc;
-- char *adl, *reason;
-- int error = GPOINTER_TO_INT(cmd->payload_cbdata);
--
-- session = cmdproc->session;
-- account = session->account;
-- gc = purple_account_get_connection(account);
--
-- adl = g_strndup(payload, len);
-- reason = g_strdup_printf(_("Unknown error (%d): %s"),
-- error, adl);
-- g_free(adl);
--
-- purple_notify_error(gc, NULL, _("Unable to remove user"), reason);
-- g_free(reason);
--}
--
--static void
--rml_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
--{
-- MsnSession *session;
-- PurpleAccount *account;
-- PurpleConnection *gc;
-- MsnCommand *cmd = cmdproc->last_cmd;
--
-- session = cmdproc->session;
-- account = session->account;
-- gc = purple_account_get_connection(account);
--
-- purple_debug_error("msn", "RML error\n");
-- if (cmd->param_count > 1) {
-- cmd->payload_cb = rml_error_parse;
-- cmd->payload_len = atoi(cmd->params[1]);
-- cmd->payload_cbdata = GINT_TO_POINTER(error);
-- } else {
-- char *reason = g_strdup_printf(_("Unknown error (%d)"), error);
-- purple_notify_error(gc, NULL, _("Unable to remove user"), reason);
-- g_free(reason);
-- }
--}
--
--static void
--fqy_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-- size_t len)
--{
-- MsnSession *session;
-- xmlnode *ml, *d, *c;
-- const char *domain;
-- const char *local;
-- const char *type;
-- char *passport;
-- MsnNetwork network = MSN_NETWORK_PASSPORT;
--
-- session = cmdproc->session;
--
-- /* FQY response:
-- <ml><d n="domain.com"><c n="local-node" t="network" /></d></ml> */
-- ml = xmlnode_from_str(payload, len);
-- for (d = xmlnode_get_child(ml, "d");
-- d != NULL;
-- d = xmlnode_get_next_twin(d)) {
-- domain = xmlnode_get_attrib(d, "n");
-- for (c = xmlnode_get_child(d, "c");
-- c != NULL;
-- c = xmlnode_get_next_twin(c)) {
-- local = xmlnode_get_attrib(c, "n");
-- type = xmlnode_get_attrib(c, "t");
--
-- passport = g_strdup_printf("%s@%s", local, domain);
--
-- if (g_ascii_isdigit(cmd->command[0]))
-- network = MSN_NETWORK_UNKNOWN;
-- else if (type != NULL)
-- network = (MsnNetwork)strtoul(type, NULL, 10);
--
-- purple_debug_info("msn", "FQY response says %s is from network %d\n",
-- passport, network);
-- if (cmd->trans->data) {
-- MsnFqyCbData *fqy_data = cmd->trans->data;
-- fqy_data->cb(session, passport, network, fqy_data->data);
-- /* Don't free fqy_data yet since the server responds to FQY multiple times.
-- It will be freed when cmd->trans is freed. */
-- }
--
-- g_free(passport);
-- }
-- }
--
-- xmlnode_free(ml);
--}
--
--static void
--fqy_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
--{
-- MsnCommand *cmd = cmdproc->last_cmd;
--
-- purple_debug_warning("msn", "FQY error %d\n", error);
-- if (cmd->param_count > 1) {
-- cmd->payload_cb = fqy_cmd_post;
-- cmd->payload_len = atoi(cmd->params[1]);
-- cmd->payload_cbdata = GINT_TO_POINTER(error);
-- }
--#if 0
-- /* If the server didn't send us a corresponding email address for this
-- FQY error, it's probably going to disconnect us. So it isn't necessary
-- to tell the handler about it. */
-- else if (trans->data)
-- ((MsnFqyCb)trans->data)(session, NULL, MSN_NETWORK_UNKNOWN, NULL);
--#endif
--}
--
--static void
--fqy_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- purple_debug_info("msn", "Process FQY\n");
-- cmdproc->last_cmd->payload_cb = fqy_cmd_post;
-- cmd->payload_len = atoi(cmd->params[1]);
--}
--
--static void
--rml_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-- size_t len)
--{
-- if (payload != NULL)
-- purple_debug_info("msn", "Received RML:\n%s\n", payload);
--}
--
--static void
--rml_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- purple_debug_info("msn", "Process RML\n");
-- cmd->payload_len = atoi(cmd->params[1]);
-- cmdproc->last_cmd->payload_cb = rml_cmd_post;
--}
--
--static void
--qng_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- /* TODO: Call PNG after the timeout specified. */
--}
--
--
--static void
--fln_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnUser *user;
-- char *passport;
-- int networkid;
--
-- /* Tell libpurple that the user has signed off */
-- msn_parse_user(cmd->params[0], &passport, &networkid);
-- user = msn_userlist_find_user(cmdproc->session->userlist, passport);
-- msn_user_set_state(user, NULL);
-- msn_user_update(user);
--
-- g_free(passport);
--}
--
--static void
--iln_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnSession *session;
-- MsnUser *user;
-- MsnObject *msnobj = NULL;
-- unsigned long clientid, extcaps;
-- char *extcap_str;
-- int networkid = 0;
-- const char *state, *passport;
-- char *friendly;
--
-- session = cmdproc->session;
--
-- state = cmd->params[1];
-- passport = cmd->params[2];
--
-- user = msn_userlist_find_user(session->userlist, passport);
-- if (user == NULL)
-- /* Where'd this come from? */
-- return;
--
-- if (cmd->param_count == 8) {
-- /* Yahoo! Buddy, looks like */
-- networkid = atoi(cmd->params[3]);
-- friendly = g_strdup(purple_url_decode(cmd->params[4]));
-- clientid = strtoul(cmd->params[5], &extcap_str, 10);
-- if (extcap_str && *extcap_str)
-- extcaps = strtoul(extcap_str+1, NULL, 10);
-- else
-- extcaps = 0;
--
-- /* cmd->params[7] seems to be a URL to a Yahoo! icon:
-- https://sec.yimg.com/i/us/nt/b/purpley.1.0.png
-- ... and it's purple, HAH!
-- */
-- } else if (cmd->param_count == 7) {
-- /* MSNP14+ with Display Picture object */
-- networkid = atoi(cmd->params[3]);
-- friendly = g_strdup(purple_url_decode(cmd->params[4]));
-- clientid = strtoul(cmd->params[5], &extcap_str, 10);
-- if (extcap_str && *extcap_str)
-- extcaps = strtoul(extcap_str+1, NULL, 10);
-- else
-- extcaps = 0;
-- msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[6]));
-- } else if (cmd->param_count == 6) {
-- /* Yes, this is 5. The friendly name could start with a number,
-- but the display picture object can't... */
-- if (isdigit(cmd->params[5][0])) {
-- /* MSNP14 without Display Picture object */
-- networkid = atoi(cmd->params[3]);
-- friendly = g_strdup(purple_url_decode(cmd->params[4]));
-- clientid = strtoul(cmd->params[5], &extcap_str, 10);
-- if (extcap_str && *extcap_str)
-- extcaps = strtoul(extcap_str+1, NULL, 10);
-- else
-- extcaps = 0;
-- } else {
-- /* MSNP8+ with Display Picture object */
-- friendly = g_strdup(purple_url_decode(cmd->params[3]));
-- clientid = strtoul(cmd->params[4], &extcap_str, 10);
-- if (extcap_str && *extcap_str)
-- extcaps = strtoul(extcap_str+1, NULL, 10);
-- else
-- extcaps = 0;
-- msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[5]));
-- }
-- } else if (cmd->param_count == 5) {
-- /* MSNP8+ without Display Picture object */
-- friendly = g_strdup(purple_url_decode(cmd->params[3]));
-- clientid = strtoul(cmd->params[4], &extcap_str, 10);
-- if (extcap_str && *extcap_str)
-- extcaps = strtoul(extcap_str+1, NULL, 10);
-- else
-- extcaps = 0;
-- } else {
-- purple_debug_warning("msn", "Received ILN with unknown number of parameters.\n");
-- return;
-- }
--
-- if (msn_user_set_friendly_name(user, friendly)) {
-- msn_update_contact(session, passport, MSN_UPDATE_DISPLAY, friendly);
-- }
-- g_free(friendly);
--
-- msn_user_set_object(user, msnobj);
--
-- user->mobile = (clientid & MSN_CAP_MOBILE_ON) || (user->extinfo && user->extinfo->phone_mobile && user->extinfo->phone_mobile[0] == '+');
-- msn_user_set_clientid(user, clientid);
-- msn_user_set_extcaps(user, extcaps);
-- msn_user_set_network(user, networkid);
--
-- msn_user_set_state(user, state);
-- msn_user_update(user);
--}
--
--static void
--ipg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
--{
-- PurpleConnection *gc;
-- MsnUserList *userlist;
-- const char *who = NULL;
-- char *text = NULL;
-- const char *id = NULL;
-- xmlnode *payloadNode, *from, *msg, *textNode;
--
-- purple_debug_misc("msn", "Incoming Page: {%s}\n", payload);
--
-- userlist = cmdproc->session->userlist;
-- gc = purple_account_get_connection(cmdproc->session->account);
--
-- /* payload looks like this:
-- <?xml version="1.0"?>
-- <NOTIFICATION id="0" siteid="111100400" siteurl="http://mobile.msn.com/">
-- <TO name="passport@example.com">
-- <VIA agent="mobile"/>
-- </TO>
-- <FROM name="tel:+XXXXXXXXXXX"/>
-- <MSG pri="1" id="1">
-- <CAT Id="110110001"/>
-- <ACTION url="2wayIM.asp"/>
-- <SUBSCR url="2wayIM.asp"/>
-- <BODY lcid="1033">
-- <TEXT>Message was here</TEXT>
-- </BODY>
-- </MSG>
-- </NOTIFICATION>
-- */
--
-- /* This is the payload if your message was too long:
-- <NOTIFICATION id="TrID" siteid="111100400" siteurl="http://mobile.msn.com/">
-- <TO name="passport@example.com">
-- <VIA agent="mobile"/>
-- </TO>
-- <FROM name="tel:+XXXXXXXXXXX"/>
-- <MSG pri="1" id="407">
-- <CAT Id="110110001"/>
-- <ACTION url="2wayIM.asp"/>
-- <SUBSCR url="2wayIM.asp"/>
-- <BODY lcid="1033">
-- <TEXT></TEXT>
-- </BODY>
-- </MSG>
-- </NOTIFICATION>
-- */
--
-- payloadNode = xmlnode_from_str(payload, len);
-- if (!payloadNode)
-- return;
--
-- if (!(from = xmlnode_get_child(payloadNode, "FROM")) ||
-- !(msg = xmlnode_get_child(payloadNode, "MSG")) ||
-- !(textNode = xmlnode_get_child(msg, "BODY/TEXT"))) {
-- xmlnode_free(payloadNode);
-- return;
-- }
--
-- who = xmlnode_get_attrib(from, "name");
-- if (!who) return;
--
-- text = xmlnode_get_data(textNode);
--
-- /* Match number to user's mobile number, FROM is a phone number if the
-- other side page you using your phone number */
-- if (!strncmp(who, "tel:+", 5)) {
-- MsnUser *user =
-- msn_userlist_find_user_with_mobile_phone(userlist, who + 4);
--
-- if (user && user->passport)
-- who = user->passport;
-- }
--
-- id = xmlnode_get_attrib(msg, "id");
--
-- if (id && strcmp(id, "1")) {
-- PurpleConversation *conv
-- = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,
-- who, gc->account);
-- if (conv != NULL) {
-- const char *error;
-- if (!strcmp(id, "407"))
-- error = _("Mobile message was not sent because it was too long.");
-- else
-- error = _("Mobile message was not sent because an unknown error occurred.");
--
-- purple_conversation_write(conv, NULL, error,
-- PURPLE_MESSAGE_ERROR, time(NULL));
--
-- if ((id = xmlnode_get_attrib(payloadNode, "id")) != NULL) {
-- unsigned int trId = atol(id);
-- MsnTransaction *trans;
--
-- trans = msn_history_find(cmdproc->history, trId);
-- if (trans) {
-- MsnMessage *msg = (MsnMessage *)trans->data;
--
-- if (msg) {
-- char *body_str = msn_message_to_string(msg);
-- char *body_enc = g_markup_escape_text(body_str, -1);
--
-- purple_conversation_write(conv, NULL, body_enc,
-- PURPLE_MESSAGE_RAW, time(NULL));
--
-- g_free(body_str);
-- g_free(body_enc);
-- msn_message_unref(msg);
-- trans->data = NULL;
-- }
-- }
-- }
-- }
-- } else {
-- serv_got_im(gc, who, text, 0, time(NULL));
-- }
--
-- g_free(text);
-- xmlnode_free(payloadNode);
--}
--
--static void
--ipg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- cmd->payload_len = atoi(cmd->params[0]);
-- cmdproc->last_cmd->payload_cb = ipg_cmd_post;
--}
--
--static void
--nln_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnSession *session;
-- MsnUser *user;
-- MsnObject *msnobj;
-- unsigned long clientid, extcaps;
-- char *extcap_str;
-- char *passport;
-- int networkid;
-- const char *state, *friendly;
--
-- session = cmdproc->session;
--
-- state = cmd->params[0];
-- msn_parse_user(cmd->params[1], &passport, &networkid);
-- friendly = purple_url_decode(cmd->params[2]);
--
-- user = msn_userlist_find_user(session->userlist, passport);
-- if (user == NULL) return;
--
-- if (msn_user_set_friendly_name(user, friendly) && user != session->user)
-- {
-- msn_update_contact(session, passport, MSN_UPDATE_DISPLAY, friendly);
-- }
--
-- if (cmd->param_count == 5)
-- {
-- msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[4]));
-- msn_user_set_object(user, msnobj);
-- }
-- else
-- {
-- msn_user_set_object(user, NULL);
-- }
--
-- clientid = strtoul(cmd->params[3], &extcap_str, 10);
-- if (extcap_str && *extcap_str)
-- extcaps = strtoul(extcap_str+1, NULL, 10);
-- else
-- extcaps = 0;
--
-- user->mobile = (clientid & MSN_CAP_MOBILE_ON) || (user->extinfo && user->extinfo->phone_mobile && user->extinfo->phone_mobile[0] == '+');
--
-- msn_user_set_clientid(user, clientid);
-- msn_user_set_extcaps(user, extcaps);
-- msn_user_set_network(user, networkid);
--
-- msn_user_set_state(user, state);
-- msn_user_update(user);
--
-- g_free(passport);
--}
--
--#if 0
--static void
--chg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- char *state = cmd->params[1];
-- int state_id = 0;
--
-- if (!strcmp(state, "NLN"))
-- state_id = MSN_ONLINE;
-- else if (!strcmp(state, "BSY"))
-- state_id = MSN_BUSY;
-- else if (!strcmp(state, "IDL"))
-- state_id = MSN_IDLE;
-- else if (!strcmp(state, "BRB"))
-- state_id = MSN_BRB;
-- else if (!strcmp(state, "AWY"))
-- state_id = MSN_AWAY;
-- else if (!strcmp(state, "PHN"))
-- state_id = MSN_PHONE;
-- else if (!strcmp(state, "LUN"))
-- state_id = MSN_LUNCH;
-- else if (!strcmp(state, "HDN"))
-- state_id = MSN_HIDDEN;
--
-- cmdproc->session->state = state_id;
--}
--#endif
--
--
--static void
--not_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
--{
--#if 0
-- MSN_SET_PARAMS("NOT %d\r\n%s", cmdproc->servconn->payload, payload);
-- purple_debug_misc("msn", "Notification: {%s}\n", payload);
--#endif
--}
--
--static void
--not_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- cmd->payload_len = atoi(cmd->params[0]);
-- cmdproc->last_cmd->payload_cb = not_cmd_post;
--}
--
--static void
--prp_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnSession *session = cmdproc->session;
-- const char *type, *value;
--
-- g_return_if_fail(cmd->param_count >= 3);
--
-- type = cmd->params[2];
--
-- if (cmd->param_count == 4)
-- {
-- value = cmd->params[3];
-- if (!strcmp(type, "PHH"))
-- msn_user_set_home_phone(session->user, purple_url_decode(value));
-- else if (!strcmp(type, "PHW"))
-- msn_user_set_work_phone(session->user, purple_url_decode(value));
-- else if (!strcmp(type, "PHM"))
-- msn_user_set_mobile_phone(session->user, purple_url_decode(value));
-- }
-- else
-- {
-- if (!strcmp(type, "PHH"))
-- msn_user_set_home_phone(session->user, NULL);
-- else if (!strcmp(type, "PHW"))
-- msn_user_set_work_phone(session->user, NULL);
-- else if (!strcmp(type, "PHM"))
-- msn_user_set_mobile_phone(session->user, NULL);
-- }
--}
--
--/**************************************************************************
-- * Misc commands
-- **************************************************************************/
--
--static void
--url_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnSession *session;
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- const char *rru;
-- const char *url;
-- PurpleCipherContext *cipher;
-- gchar creds[33];
-- char *buf;
--
-- gulong tmp_timestamp;
--
-- session = cmdproc->session;
-- account = session->account;
-- gc = account->gc;
--
-- rru = cmd->params[1];
-- url = cmd->params[2];
--
-- session->passport_info.mail_timestamp = time(NULL);
-- tmp_timestamp = session->passport_info.mail_timestamp - session->passport_info.sl;
--
-- buf = g_strdup_printf("%s%lu%s",
-- session->passport_info.mspauth ? session->passport_info.mspauth : "BOGUS",
-- tmp_timestamp,
-- purple_connection_get_password(gc));
--
-- cipher = purple_cipher_context_new_by_name("md5", NULL);
-- purple_cipher_context_append(cipher, (const guchar *)buf, strlen(buf));
-- purple_cipher_context_digest_to_str(cipher, sizeof(creds), creds, NULL);
-- purple_cipher_context_destroy(cipher);
-- g_free(buf);
--
-- g_free(session->passport_info.mail_url);
-- session->passport_info.mail_url =
-- g_strdup_printf("%s&auth=%s&creds=%s&sl=%ld&username=%s&mode=ttl&sid=%s&id=2&rru=%s&svc=mail&js=yes",
-- url,
-- session->passport_info.mspauth ? purple_url_encode(session->passport_info.mspauth) : "BOGUS",
-- creds,
-- tmp_timestamp,
-- msn_user_get_passport(session->user),
-- session->passport_info.sid,
-- rru);
--
-- /* The user wants to check his or her email */
-- if (cmd->trans && cmd->trans->data)
-- purple_notify_uri(purple_account_get_connection(account), session->passport_info.mail_url);
--}
--/**************************************************************************
-- * Switchboards
-- **************************************************************************/
--
--static void
--rng_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnSession *session;
-- MsnSwitchBoard *swboard;
-- const char *session_id;
-- char *host;
-- int port;
--
-- session = cmdproc->session;
-- session_id = cmd->params[0];
--
-- msn_parse_socket(cmd->params[1], &host, &port);
--
-- if (session->http_method)
-- port = 80;
--
-- swboard = msn_switchboard_new(session);
--
-- msn_switchboard_set_invited(swboard, TRUE);
-- msn_switchboard_set_session_id(swboard, session_id);
-- msn_switchboard_set_auth_key(swboard, cmd->params[3]);
-- swboard->im_user = g_strdup(cmd->params[4]);
-- /* msn_switchboard_add_user(swboard, cmd->params[4]); */
--
-- if (!msn_switchboard_connect(swboard, host, port))
-- msn_switchboard_destroy(swboard);
--
-- g_free(host);
--}
--
--static void
--xfr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- char *host;
-- int port;
--
-- if (strcmp(cmd->params[1], "SB") && strcmp(cmd->params[1], "NS"))
-- {
-- /* Maybe we can have a generic bad command error. */
-- purple_debug_error("msn", "Bad XFR command (%s)\n", cmd->params[1]);
-- return;
-- }
--
-- msn_parse_socket(cmd->params[2], &host, &port);
--
-- if (!strcmp(cmd->params[1], "SB"))
-- {
-- purple_debug_error("msn", "This shouldn't be handled here.\n");
-- }
-- else if (!strcmp(cmd->params[1], "NS"))
-- {
-- MsnSession *session;
--
-- session = cmdproc->session;
--
-- msn_session_set_login_step(session, MSN_LOGIN_STEP_TRANSFER);
--
-- msn_notification_connect(session->notification, host, port);
-- }
--
-- g_free(host);
--}
--
--static void
--gcf_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-- size_t len)
--{
--/* QuLogic: Disabled until confirmed correct. */
--#if 0
-- xmlnode *root;
-- xmlnode *policy;
--
-- g_return_if_fail(cmd->payload != NULL);
--
-- if ( (root = xmlnode_from_str(cmd->payload, cmd->payload_len)) == NULL)
-- {
-- purple_debug_error("msn", "Unable to parse GCF payload into a XML tree\n");
-- return;
-- }
--
--
-- g_free(cmdproc->session->blocked_text);
-- cmdproc->session->blocked_text = NULL;
--
-- /* We need a get_child with attrib... */
-- policy = xmlnode_get_child(root, "Policy");
-- while (policy) {
-- if (g_str_equal(xmlnode_get_attrib(policy, "type"), "SHIELDS"))
-- break;
-- policy = xmlnode_get_next_twin(policy);
-- }
--
-- if (policy) {
-- GString *blocked = g_string_new(NULL);
-- xmlnode *imtext = xmlnode_get_child(policy,
-- "config/block/regexp/imtext");
-- while (imtext) {
-- const char *value = xmlnode_get_attrib(imtext, "value");
-- g_string_append_printf(blocked, "%s<br/>\n",
-- purple_base64_decode(value, NULL));
-- imtext = xmlnode_get_next_twin(imtext);
-- }
--
-- cmdproc->session->blocked_text = g_string_free(blocked, FALSE);
-- }
--
-- xmlnode_free(root);
--#endif
--}
--
--static void
--gcf_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- purple_debug_info("msn", "Processing GCF command\n");
--
-- cmdproc->last_cmd->payload_cb = gcf_cmd_post;
-- cmd->payload_len = atoi(cmd->params[1]);
--}
--
--static void
--sbs_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- purple_debug_info("msn", "Processing SBS... \n");
-- /*get the payload content*/
--}
--
--static void
--parse_user_endpoints(MsnUser *user, xmlnode *payloadNode)
--{
-- MsnSession *session;
-- xmlnode *epNode, *capsNode;
-- MsnUserEndpoint data;
-- const char *id;
-- char *caps, *tmp;
-- gboolean is_me;
--
-- purple_debug_info("msn", "Get EndpointData\n");
--
-- session = user->userlist->session;
-- is_me = (user == session->user);
--
-- msn_user_clear_endpoints(user);
-- for (epNode = xmlnode_get_child(payloadNode, "EndpointData");
-- epNode;
-- epNode = xmlnode_get_next_twin(epNode)) {
-- id = xmlnode_get_attrib(epNode, "id");
-- capsNode = xmlnode_get_child(epNode, "Capabilities");
--
-- /* Disconnect others, if MPOP is disabled */
-- if (is_me
-- && !session->enable_mpop
-- && strncasecmp(id + 1, session->guid, 36) != 0) {
-- purple_debug_info("msn", "Disconnecting Endpoint %s\n", id);
--
-- tmp = g_strdup_printf("%s;%s", user->passport, id);
-- msn_notification_send_uun(session, tmp, MSN_UNIFIED_NOTIFICATION_MPOP, "goawyplzthxbye");
-- g_free(tmp);
-- } else {
-- if (capsNode != NULL) {
-- caps = xmlnode_get_data(capsNode);
--
-- data.clientid = strtoul(caps, &tmp, 10);
-- if (tmp && *tmp)
-- data.extcaps = strtoul(tmp + 1, NULL, 10);
-- else
-- data.extcaps = 0;
--
-- g_free(caps);
-- } else {
-- data.clientid = 0;
-- data.extcaps = 0;
-- }
--
-- msn_user_set_endpoint_data(user, id, &data);
-- }
-- }
--
-- if (is_me && session->enable_mpop) {
-- for (epNode = xmlnode_get_child(payloadNode, "PrivateEndpointData");
-- epNode;
-- epNode = xmlnode_get_next_twin(epNode)) {
-- MsnUserEndpoint *ep;
-- xmlnode *nameNode, *clientNode;
--
-- /* <PrivateEndpointData id='{GUID}'>
-- <EpName>Endpoint Name</EpName>
-- <Idle>true/false</Idle>
-- <ClientType>1</ClientType>
-- <State>NLN</State>
-- </PrivateEndpointData>
-- */
-- id = xmlnode_get_attrib(epNode, "id");
-- ep = msn_user_get_endpoint_data(user, id);
--
-- if (ep != NULL) {
-- nameNode = xmlnode_get_child(epNode, "EpName");
-- if (nameNode != NULL) {
-- g_free(ep->name);
-- ep->name = xmlnode_get_data(nameNode);
-- }
--
-- clientNode = xmlnode_get_child(epNode, "ClientType");
-- if (clientNode != NULL) {
-- tmp = xmlnode_get_data(clientNode);
-- ep->type = strtoul(tmp, NULL, 10);
-- g_free(tmp);
-- }
-- }
-- }
-- }
--}
--
--static void parse_currentmedia(MsnUser *user, const char *cmedia)
--{
-- char **cmedia_array;
-- int strings = 0;
--
-- if (!cmedia || cmedia[0] == '\0') {
-- purple_debug_info("msn", "No currentmedia string\n");
-- return;
-- }
--
-- purple_debug_info("msn", "Parsing currentmedia string: \"%s\"\n", cmedia);
--
-- cmedia_array = g_strsplit(cmedia, "\\0", 0);
--
-- /*
-- * 0: Application
-- * 1: 'Music'/'Games'/'Office'
-- * 2: '1' if enabled, '0' if not
-- * 3: Format (eg. {0} by {1})
-- * 4: Title
-- * If 'Music':
-- * 5: Artist
-- * 6: Album
-- * 7: ?
-- */
-- strings = g_strv_length(cmedia_array);
--
-- if (strings >= 4 && !strcmp(cmedia_array[2], "1")) {
-- if (user->extinfo == NULL)
-- user->extinfo = g_new0(MsnUserExtendedInfo, 1);
-- else {
-- g_free(user->extinfo->media_album);
-- g_free(user->extinfo->media_artist);
-- g_free(user->extinfo->media_title);
-- }
--
-- if (!strcmp(cmedia_array[1], "Music"))
-- user->extinfo->media_type = CURRENT_MEDIA_MUSIC;
-- else if (!strcmp(cmedia_array[1], "Games"))
-- user->extinfo->media_type = CURRENT_MEDIA_GAMES;
-- else if (!strcmp(cmedia_array[1], "Office"))
-- user->extinfo->media_type = CURRENT_MEDIA_OFFICE;
-- else
-- user->extinfo->media_type = CURRENT_MEDIA_UNKNOWN;
--
-- user->extinfo->media_title = g_strdup(cmedia_array[strings == 4 ? 3 : 4]);
-- user->extinfo->media_artist = strings > 5 ? g_strdup(cmedia_array[5]) : NULL;
-- user->extinfo->media_album = strings > 6 ? g_strdup(cmedia_array[6]) : NULL;
-- }
--
-- g_strfreev(cmedia_array);
--}
--
--/*
-- * Get the UBX's PSM info
-- * Post it to the User status
-- * Thanks for Chris <ukdrizzle@yahoo.co.uk>'s code
-- */
--static void
--ubx_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-- size_t len)
--{
-- MsnSession *session;
-- MsnUser *user;
-- char *passport;
-- int network;
-- xmlnode *payloadNode;
-- char *psm_str, *str;
--
-- session = cmdproc->session;
--
-- msn_parse_user(cmd->params[0], &passport, &network);
-- user = msn_userlist_find_user(session->userlist, passport);
--
-- if (user == NULL) {
-- str = g_strndup(payload, len);
-- purple_debug_info("msn", "unknown user %s, payload is %s\n",
-- passport, str);
-- g_free(passport);
-- g_free(str);
-- return;
-- }
--
-- g_free(passport);
--
-- /* Free any existing media info for this user */
-- if (user->extinfo) {
-- g_free(user->extinfo->media_album);
-- g_free(user->extinfo->media_artist);
-- g_free(user->extinfo->media_title);
-- user->extinfo->media_album = NULL;
-- user->extinfo->media_artist = NULL;
-- user->extinfo->media_title = NULL;
-- user->extinfo->media_type = CURRENT_MEDIA_UNKNOWN;
-- }
--
-- if (len != 0) {
-- payloadNode = xmlnode_from_str(payload, len);
-- if (!payloadNode) {
-- purple_debug_error("msn", "UBX XML parse Error!\n");
--
-- msn_user_set_statusline(user, NULL);
--
-- msn_user_update(user);
-- return;
-- }
--
-- psm_str = msn_get_psm(payloadNode);
-- msn_user_set_statusline(user, psm_str);
-- g_free(psm_str);
--
-- str = msn_get_currentmedia(payloadNode);
-- parse_currentmedia(user, str);
-- g_free(str);
--
-- parse_user_endpoints(user, payloadNode);
--
-- xmlnode_free(payloadNode);
--
-- } else {
-- msn_user_set_statusline(user, NULL);
-- }
--
-- msn_user_update(user);
--}
--
--static void
--ubx_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- purple_debug_misc("msn", "UBX received.\n");
-- cmdproc->last_cmd->payload_cb = ubx_cmd_post;
-- cmd->payload_len = atoi(cmd->params[1]);
--}
--
--static void
--uux_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-- size_t len)
--{
-- /* Do Nothing, right now. */
-- if (payload != NULL)
-- purple_debug_info("msn", "UUX payload:\n%s\n", payload);
--}
--
--static void
--uux_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- purple_debug_misc("msn", "UUX received.\n");
-- cmdproc->last_cmd->payload_cb = uux_cmd_post;
-- cmd->payload_len = atoi(cmd->params[1]);
--}
--
--void
--msn_notification_send_uux(MsnSession *session, const char *payload)
--{
-- MsnTransaction *trans;
-- MsnCmdProc *cmdproc;
-- size_t len = strlen(payload);
--
-- cmdproc = session->notification->cmdproc;
-- purple_debug_misc("msn", "Sending UUX command with payload: %s\n", payload);
-- trans = msn_transaction_new(cmdproc, "UUX", "%" G_GSIZE_FORMAT, len);
-- msn_transaction_set_payload(trans, payload, len);
-- msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--void msn_notification_send_uux_endpointdata(MsnSession *session)
--{
-- xmlnode *epDataNode;
-- xmlnode *capNode;
-- char *caps;
-- char *payload;
-- int length;
--
-- epDataNode = xmlnode_new("EndpointData");
--
-- capNode = xmlnode_new_child(epDataNode, "Capabilities");
-- caps = g_strdup_printf("%d:%02d", MSN_CLIENT_ID_CAPABILITIES, MSN_CLIENT_ID_EXT_CAPS);
-- xmlnode_insert_data(capNode, caps, -1);
-- g_free(caps);
--
-- payload = xmlnode_to_str(epDataNode, &length);
--
-- msn_notification_send_uux(session, payload);
--
-- xmlnode_free(epDataNode);
-- g_free(payload);
--}
--
--void msn_notification_send_uux_private_endpointdata(MsnSession *session)
--{
-- xmlnode *private;
-- const char *name;
-- xmlnode *epname;
-- xmlnode *idle;
-- GHashTable *ui_info;
-- const gchar *ui_type;
-- xmlnode *client_type;
-- xmlnode *state;
-- char *payload;
-- int length;
--
-- private = xmlnode_new("PrivateEndpointData");
--
-- name = purple_account_get_string(session->account, "endpoint-name", NULL);
-- epname = xmlnode_new_child(private, "EpName");
-- xmlnode_insert_data(epname, name, -1);
--
-- idle = xmlnode_new_child(private, "Idle");
-- xmlnode_insert_data(idle, "false", -1);
--
-- /* ClientType info (from amsn guys):
-- 0: None
-- 1: Computer
-- 2: Website
-- 3: Mobile / none
-- 4: Xbox / phone /mobile
-- 9: MsnGroup
-- 32: Email member, currently Yahoo!
-- */
-- client_type = xmlnode_new_child(private, "ClientType");
-- ui_info = purple_core_get_ui_info();
-- ui_type = ui_info ? g_hash_table_lookup(ui_info, "client_type") : NULL;
-- if (ui_type) {
-- if (strcmp(ui_type, "pc") == 0)
-- xmlnode_insert_data(client_type, "1", -1);
-- else if (strcmp(ui_type, "web") == 0)
-- xmlnode_insert_data(client_type, "2", -1);
-- else if (strcmp(ui_type, "phone") == 0)
-- xmlnode_insert_data(client_type, "3", -1);
-- else if (strcmp(ui_type, "handheld") == 0)
-- xmlnode_insert_data(client_type, "3", -1);
-- else
-- xmlnode_insert_data(client_type, "1", -1);
-- }
-- else
-- xmlnode_insert_data(client_type, "1", -1);
--
-- state = xmlnode_new_child(private, "State");
-- xmlnode_insert_data(state, msn_state_get_text(msn_state_from_account(session->account)), -1);
--
-- payload = xmlnode_to_str(private, &length);
--
-- msn_notification_send_uux(session, payload);
--
-- xmlnode_free(private);
-- g_free(payload);
--}
--
--static void
--ubn_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-- size_t len)
--{
-- /* Do Nothing, right now. */
-- if (payload != NULL)
-- purple_debug_info("msn", "UBN payload:\n%s\n", payload);
--}
--
--static void
--ubn_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- purple_debug_misc("msn", "UBN received from %s.\n", cmd->params[0]);
-- cmdproc->last_cmd->payload_cb = ubn_cmd_post;
-- cmd->payload_len = atoi(cmd->params[2]);
--}
--
--static void
--uun_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
-- size_t len)
--{
-- /* Do Nothing, right now. */
-- if (payload != NULL)
-- purple_debug_info("msn", "UUN payload:\n%s\n", payload);
--}
--
--static void
--uun_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- if (strcmp(cmd->params[1], "OK") != 0) {
-- purple_debug_misc("msn", "UUN received.\n");
-- cmdproc->last_cmd->payload_cb = uun_cmd_post;
-- cmd->payload_len = atoi(cmd->params[1]);
-- }
-- else
-- purple_debug_misc("msn", "UUN OK received.\n");
--}
--
--void
--msn_notification_send_uun(MsnSession *session, const char *user,
-- MsnUnifiedNotificationType type, const char *payload)
--{
-- MsnTransaction *trans;
-- MsnCmdProc *cmdproc;
-- size_t len = strlen(payload);
--
-- cmdproc = session->notification->cmdproc;
-- purple_debug_misc("msn", "Sending UUN command %d to %s with payload: %s\n",
-- type, user, payload);
-- trans = msn_transaction_new(cmdproc, "UUN", "%s %d %" G_GSIZE_FORMAT,
-- user, type, len);
-- msn_transaction_set_payload(trans, payload, len);
-- msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--void
--msn_notification_send_circle_auth(MsnSession *session, const char *ticket)
--{
-- MsnTransaction *trans;
-- MsnCmdProc *cmdproc;
-- char *encoded;
--
-- cmdproc = session->notification->cmdproc;
--
-- encoded = purple_base64_encode((guchar *)ticket, strlen(ticket));
-- trans = msn_transaction_new(cmdproc, "USR", "SHA A %s", encoded);
-- msn_cmdproc_send_trans(cmdproc, trans);
--
-- g_free(encoded);
--}
--
--/**************************************************************************
-- * Message Types
-- **************************************************************************/
--
--static void
--profile_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
--{
-- MsnSession *session;
-- const char *value;
--#ifdef MSN_PARTIAL_LISTS
-- const char *clLastChange;
--#endif
--
-- session = cmdproc->session;
--
-- if (strcmp(msg->remote_user, "Hotmail"))
-- /* This isn't an official message. */
-- return;
--
-- if ((value = msn_message_get_header_value(msg, "sid")) != NULL)
-- {
-- g_free(session->passport_info.sid);
-- session->passport_info.sid = g_strdup(value);
-- }
--
-- if ((value = msn_message_get_header_value(msg, "MSPAuth")) != NULL)
-- {
-- g_free(session->passport_info.mspauth);
-- session->passport_info.mspauth = g_strdup(value);
-- }
--
-- if ((value = msn_message_get_header_value(msg, "ClientIP")) != NULL)
-- {
-- g_free(session->passport_info.client_ip);
-- session->passport_info.client_ip = g_strdup(value);
-- }
--
-- if ((value = msn_message_get_header_value(msg, "ClientPort")) != NULL)
-- {
-- session->passport_info.client_port = ntohs(atoi(value));
-- }
--
-- if ((value = msn_message_get_header_value(msg, "LoginTime")) != NULL)
-- session->passport_info.sl = atol(value);
--
-- if ((value = msn_message_get_header_value(msg, "EmailEnabled")) != NULL)
-- session->passport_info.email_enabled = (gboolean)atol(value);
--
--#ifdef MSN_PARTIAL_LISTS
-- /*starting retrieve the contact list*/
-- clLastChange = purple_account_get_string(session->account, "CLLastChange", NULL);
-- /* msn_userlist_load defeats all attempts at trying to detect blist sync issues */
-- msn_userlist_load(session);
-- msn_get_contact_list(session, MSN_PS_INITIAL, clLastChange);
--#else
-- /* always get the full list? */
-- msn_get_contact_list(session, MSN_PS_INITIAL, NULL);
--#endif
--}
--
--static void
--initial_email_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
--{
-- MsnSession *session;
-- PurpleConnection *gc;
-- GHashTable *table;
-- const char *unread;
--
-- session = cmdproc->session;
-- gc = session->account->gc;
--
-- if (strcmp(msg->remote_user, "Hotmail"))
-- /* This isn't an official message. */
-- return;
--
-- if (session->passport_info.mail_url == NULL)
-- {
-- MsnTransaction *trans;
-- trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
-- msn_transaction_queue_cmd(trans, msg->cmd);
--
-- msn_cmdproc_send_trans(cmdproc, trans);
--
-- return;
-- }
--
-- if (!purple_account_get_check_mail(session->account))
-- return;
--
-- table = msn_message_get_hashtable_from_body(msg);
--
-- unread = g_hash_table_lookup(table, "Inbox-Unread");
--
-- if (unread != NULL)
-- {
-- int count = atoi(unread);
--
-- if (count > 0)
-- {
-- const char *passports[2] = { msn_user_get_passport(session->user) };
-- const char *urls[2] = { session->passport_info.mail_url };
--
-- purple_notify_emails(gc, count, FALSE, NULL, NULL,
-- passports, urls, NULL, NULL);
-- }
-- }
--
-- g_hash_table_destroy(table);
--}
--
--/*offline Message notification process*/
--static void
--initial_mdata_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
--{
-- MsnSession *session;
-- PurpleConnection *gc;
-- GHashTable *table;
-- const char *mdata, *unread;
--
-- session = cmdproc->session;
-- gc = session->account->gc;
--
-- if (strcmp(msg->remote_user, "Hotmail"))
-- /* This isn't an official message. */
-- return;
--
-- table = msn_message_get_hashtable_from_body(msg);
--
-- mdata = g_hash_table_lookup(table, "Mail-Data");
--
-- if (mdata != NULL)
-- msn_parse_oim_msg(session->oim, mdata);
--
-- if (g_hash_table_lookup(table, "Inbox-URL") == NULL)
-- {
-- g_hash_table_destroy(table);
-- return;
-- }
--
-- if (session->passport_info.mail_url == NULL)
-- {
-- MsnTransaction *trans;
-- trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
-- msn_transaction_queue_cmd(trans, msg->cmd);
--
-- msn_cmdproc_send_trans(cmdproc, trans);
--
-- g_hash_table_destroy(table);
-- return;
-- }
--
-- if (!purple_account_get_check_mail(session->account))
-- {
-- g_hash_table_destroy(table);
-- return;
-- }
--
-- unread = g_hash_table_lookup(table, "Inbox-Unread");
--
-- if (unread != NULL)
-- {
-- int count = atoi(unread);
--
-- if (count > 0)
-- {
-- const char *passports[2] = { msn_user_get_passport(session->user) };
-- const char *urls[2] = { session->passport_info.mail_url };
--
-- purple_notify_emails(gc, count, FALSE, NULL, NULL,
-- passports, urls, NULL, NULL);
-- }
-- }
--
-- g_hash_table_destroy(table);
--}
--
--/*offline Message Notification*/
--static void
--delete_oim_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
--{
-- purple_debug_misc("msn", "Delete OIM message.\n");
--}
--
--static void
--email_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
--{
-- MsnSession *session;
-- PurpleConnection *gc;
-- GHashTable *table;
-- char *from, *subject, *tmp;
--
-- session = cmdproc->session;
-- gc = session->account->gc;
--
-- if (strcmp(msg->remote_user, "Hotmail"))
-- /* This isn't an official message. */
-- return;
--
-- if (session->passport_info.mail_url == NULL)
-- {
-- MsnTransaction *trans;
-- trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
-- msn_transaction_queue_cmd(trans, msg->cmd);
--
-- msn_cmdproc_send_trans(cmdproc, trans);
--
-- return;
-- }
--
-- if (!purple_account_get_check_mail(session->account))
-- return;
--
-- table = msn_message_get_hashtable_from_body(msg);
--
-- from = subject = NULL;
--
-- tmp = g_hash_table_lookup(table, "From");
-- if (tmp != NULL)
-- from = purple_mime_decode_field(tmp);
--
-- tmp = g_hash_table_lookup(table, "Subject");
-- if (tmp != NULL)
-- subject = purple_mime_decode_field(tmp);
--
-- purple_notify_email(gc,
-- (subject != NULL ? subject : ""),
-- (from != NULL ? from : ""),
-- msn_user_get_passport(session->user),
-- session->passport_info.mail_url, NULL, NULL);
--
-- g_free(from);
-- g_free(subject);
--
-- g_hash_table_destroy(table);
--}
--
--static void
--system_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
--{
-- GHashTable *table;
-- const char *type_s;
--
-- if (strcmp(msg->remote_user, "Hotmail"))
-- /* This isn't an official message. */
-- return;
--
-- table = msn_message_get_hashtable_from_body(msg);
--
-- if ((type_s = g_hash_table_lookup(table, "Type")) != NULL)
-- {
-- int type = atoi(type_s);
-- char buf[MSN_BUF_LEN] = "";
-- int minutes;
--
-- switch (type)
-- {
-- case 1:
-- minutes = atoi(g_hash_table_lookup(table, "Arg1"));
-- g_snprintf(buf, sizeof(buf), dngettext(PACKAGE,
-- "The MSN server will shut down for maintenance "
-- "in %d minute. You will automatically be "
-- "signed out at that time. Please finish any "
-- "conversations in progress.\n\nAfter the "
-- "maintenance has been completed, you will be "
-- "able to successfully sign in.",
-- "The MSN server will shut down for maintenance "
-- "in %d minutes. You will automatically be "
-- "signed out at that time. Please finish any "
-- "conversations in progress.\n\nAfter the "
-- "maintenance has been completed, you will be "
-- "able to successfully sign in.", minutes),
-- minutes);
-- default:
-- break;
-- }
--
-- if (*buf != '\0')
-- purple_notify_info(cmdproc->session->account->gc, NULL, buf, NULL);
-- }
--
-- g_hash_table_destroy(table);
--}
--
--/**************************************************************************
-- * Dispatch server list management
-- **************************************************************************/
--typedef struct MsnAddRemoveListData {
-- MsnCmdProc *cmdproc;
-- MsnUser *user;
-- MsnListOp list_op;
-- gboolean add;
--} MsnAddRemoveListData;
--
--static void
--modify_unknown_buddy_on_list(MsnSession *session, const char *passport,
-- MsnNetwork network, gpointer data)
--{
-- MsnAddRemoveListData *addrem = data;
-- MsnCmdProc *cmdproc;
-- xmlnode *node;
-- char *payload;
-- int payload_len;
--
-- cmdproc = addrem->cmdproc;
--
-- /* Update user first */
-- msn_user_set_network(addrem->user, network);
--
-- node = xmlnode_new("ml");
-- node->child = NULL;
--
-- msn_add_contact_xml(node, passport, addrem->list_op, network);
--
-- payload = xmlnode_to_str(node, &payload_len);
-- xmlnode_free(node);
--
-- if (addrem->add)
-- msn_notification_post_adl(cmdproc, payload, payload_len);
-- else
-- msn_notification_post_rml(cmdproc, payload, payload_len);
--
-- g_free(payload);
-- g_free(addrem);
--}
--
--void
--msn_notification_add_buddy_to_list(MsnNotification *notification, MsnListId list_id,
-- MsnUser *user)
--{
-- MsnAddRemoveListData *addrem;
-- MsnCmdProc *cmdproc;
-- MsnListOp list_op = 1 << list_id;
-- xmlnode *adl_node;
-- char *payload;
-- int payload_len;
--
-- cmdproc = notification->servconn->cmdproc;
--
-- adl_node = xmlnode_new("ml");
-- adl_node->child = NULL;
--
-- msn_add_contact_xml(adl_node, user->passport, list_op, user->networkid);
--
-- payload = xmlnode_to_str(adl_node, &payload_len);
-- xmlnode_free(adl_node);
--
-- if (user->networkid != MSN_NETWORK_UNKNOWN) {
-- msn_notification_post_adl(cmdproc, payload, payload_len);
--
-- } else {
-- addrem = g_new(MsnAddRemoveListData, 1);
-- addrem->cmdproc = cmdproc;
-- addrem->user = user;
-- addrem->list_op = list_op;
-- addrem->add = TRUE;
--
-- msn_notification_send_fqy(notification->session, payload, payload_len,
-- modify_unknown_buddy_on_list, addrem);
-- }
--
-- g_free(payload);
--}
--
--void
--msn_notification_rem_buddy_from_list(MsnNotification *notification, MsnListId list_id,
-- MsnUser *user)
--{
-- MsnAddRemoveListData *addrem;
-- MsnCmdProc *cmdproc;
-- MsnListOp list_op = 1 << list_id;
-- xmlnode *rml_node;
-- char *payload;
-- int payload_len;
--
-- cmdproc = notification->servconn->cmdproc;
--
-- rml_node = xmlnode_new("ml");
-- rml_node->child = NULL;
--
-- msn_add_contact_xml(rml_node, user->passport, list_op, user->networkid);
--
-- payload = xmlnode_to_str(rml_node, &payload_len);
-- xmlnode_free(rml_node);
--
-- if (user->networkid != MSN_NETWORK_UNKNOWN) {
-- msn_notification_post_rml(cmdproc, payload, payload_len);
--
-- } else {
-- addrem = g_new(MsnAddRemoveListData, 1);
-- addrem->cmdproc = cmdproc;
-- addrem->user = user;
-- addrem->list_op = list_op;
-- addrem->add = FALSE;
--
-- msn_notification_send_fqy(notification->session, payload, payload_len,
-- modify_unknown_buddy_on_list, addrem);
-- }
--
-- g_free(payload);
--}
--
--/**************************************************************************
-- * Init
-- **************************************************************************/
--void
--msn_notification_init(void)
--{
-- cbs_table = msn_table_new();
--
-- /* Synchronous */
-- msn_table_add_cmd(cbs_table, "CHG", "CHG", NULL);
-- msn_table_add_cmd(cbs_table, "CHG", "ILN", iln_cmd);
-- msn_table_add_cmd(cbs_table, "ADL", "ILN", iln_cmd);
-- msn_table_add_cmd(cbs_table, "USR", "USR", usr_cmd);
-- msn_table_add_cmd(cbs_table, "USR", "XFR", xfr_cmd);
-- msn_table_add_cmd(cbs_table, "USR", "GCF", gcf_cmd);
-- msn_table_add_cmd(cbs_table, "CVR", "CVR", cvr_cmd);
-- msn_table_add_cmd(cbs_table, "VER", "VER", ver_cmd);
-- msn_table_add_cmd(cbs_table, "PRP", "PRP", prp_cmd);
-- msn_table_add_cmd(cbs_table, "BLP", "BLP", blp_cmd);
-- msn_table_add_cmd(cbs_table, "XFR", "XFR", xfr_cmd);
--
-- /* Asynchronous */
-- msn_table_add_cmd(cbs_table, NULL, "IPG", ipg_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "MSG", msg_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "UBM", ubm_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "GCF", gcf_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "SBS", sbs_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "NOT", not_cmd);
--
-- msn_table_add_cmd(cbs_table, NULL, "CHL", chl_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "RML", rml_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "ADL", adl_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "FQY", fqy_cmd);
--
-- msn_table_add_cmd(cbs_table, NULL, "QRY", NULL);
-- msn_table_add_cmd(cbs_table, NULL, "QNG", qng_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "FLN", fln_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "NLN", nln_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "ILN", iln_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "OUT", out_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "RNG", rng_cmd);
--
-- msn_table_add_cmd(cbs_table, NULL, "UBX", ubx_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "UUX", uux_cmd);
--
-- msn_table_add_cmd(cbs_table, NULL, "UBN", ubn_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "UUN", uun_cmd);
--
-- msn_table_add_cmd(cbs_table, NULL, "URL", url_cmd);
--
-- msn_table_add_cmd(cbs_table, "fallback", "XFR", xfr_cmd);
--
-- msn_table_add_error(cbs_table, "ADL", adl_error);
-- msn_table_add_error(cbs_table, "RML", rml_error);
-- msn_table_add_error(cbs_table, "FQY", fqy_error);
-- msn_table_add_error(cbs_table, "USR", usr_error);
--
-- msn_table_add_msg_type(cbs_table,
-- "text/x-msmsgsprofile",
-- profile_msg);
-- /*initial OIM notification*/
-- msn_table_add_msg_type(cbs_table,
-- "text/x-msmsgsinitialmdatanotification",
-- initial_mdata_msg);
-- /*OIM notification when user online*/
-- msn_table_add_msg_type(cbs_table,
-- "text/x-msmsgsoimnotification",
-- initial_mdata_msg);
-- msn_table_add_msg_type(cbs_table,
-- "text/x-msmsgsinitialemailnotification",
-- initial_email_msg);
-- msn_table_add_msg_type(cbs_table,
-- "text/x-msmsgsemailnotification",
-- email_msg);
-- /*delete an offline Message notification*/
-- msn_table_add_msg_type(cbs_table,
-- "text/x-msmsgsactivemailnotification",
-- delete_oim_msg);
-- msn_table_add_msg_type(cbs_table,
-- "application/x-msmsgssystemmessage",
-- system_msg);
-- /* generic message handlers */
-- msn_table_add_msg_type(cbs_table, "text/plain",
-- msn_plain_msg);
-- msn_table_add_msg_type(cbs_table, "text/x-msmsgscontrol",
-- msn_control_msg);
-- msn_table_add_msg_type(cbs_table, "text/x-msnmsgr-datacast",
-- msn_datacast_msg);
--}
--
--void
--msn_notification_end(void)
--{
-- msn_table_destroy(cbs_table);
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/notification.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/notification.h
---- pidgin-2.10.7/libpurple/protocols/msn/notification.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/notification.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,124 +0,0 @@
--/**
-- * @file notification.h Notification server functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_NOTIFICATION_H
--#define MSN_NOTIFICATION_H
--
--typedef struct _MsnNotification MsnNotification;
--
--/* MSN protocol challenge info */
--
--/* MSNP18 challenge: WLM Version 2009 (Build 14.0.8089.726) */
--#define MSNP18_WLM_PRODUCT_KEY "C1BX{V4W}Q3*10SM"
--#define MSNP18_WLM_PRODUCT_ID "PROD0120PW!CCV9@"
--
--/* MSNP15 challenge: WLM 8.5.1288.816 */
--#define MSNP15_WLM_PRODUCT_KEY "ILTXC!4IXB5FB*PX"
--#define MSNP15_WLM_PRODUCT_ID "PROD0119GSJUC$18"
--
--/* MSNP13 challenge */
--#define MSNP13_WLM_PRODUCT_KEY "O4BG@C7BWLYQX?5G"
--#define MSNP13_WLM_PRODUCT_ID "PROD01065C%ZFN6F"
--
--#define MSNP10_PRODUCT_KEY "VT6PX?UQTM4WM%YR"
--#define MSNP10_PRODUCT_ID "PROD0038W!61ZTF9"
--
--#include "cmdproc.h"
--#include "msg.h"
--#include "session.h"
--#include "servconn.h"
--#include "state.h"
--#include "user.h"
--#include "userlist.h"
--
--struct _MsnNotification
--{
-- MsnSession *session;
--
-- /**
-- * This is a convenience pointer that always points to
-- * servconn->cmdproc
-- */
-- MsnCmdProc *cmdproc;
-- MsnServConn *servconn;
--
-- gboolean in_use;
--};
--
--typedef void (*MsnFqyCb)(MsnSession *session, const char *passport, MsnNetwork network, gpointer data);
--
--/* Type used for msn_notification_send_uun */
--typedef enum {
-- MSN_UNIFIED_NOTIFICATION_SHARED_FOLDERS = 1,
-- MSN_UNIFIED_NOTIFICATION_UNKNOWN1 = 2,
-- MSN_UNIFIED_NOTIFICATION_P2P = 3,
-- MSN_UNIFIED_NOTIFICATION_MPOP = 4
--
--} MsnUnifiedNotificationType;
--
--void msn_notification_end(void);
--void msn_notification_init(void);
--
--void msn_notification_add_buddy_to_list(MsnNotification *notification,
-- MsnListId list_id, MsnUser *user);
--void msn_notification_rem_buddy_from_list(MsnNotification *notification,
-- MsnListId list_id, MsnUser *user);
--
--void msn_notification_send_fqy(MsnSession *session,
-- const char *payload, int payload_len,
-- MsnFqyCb cb, gpointer cb_data);
--
--MsnNotification *msn_notification_new(MsnSession *session);
--void msn_notification_destroy(MsnNotification *notification);
--gboolean msn_notification_connect(MsnNotification *notification,
-- const char *host, int port);
--void msn_notification_disconnect(MsnNotification *notification);
--void msn_notification_dump_contact(MsnSession *session);
--
--void msn_notification_send_uum(MsnSession *session, MsnMessage *msg);
--
--void msn_notification_send_uux(MsnSession *session, const char *payload);
--
--void msn_notification_send_uux_endpointdata(MsnSession *session);
--
--void msn_notification_send_uux_private_endpointdata(MsnSession *session);
--
--void msn_notification_send_uun(MsnSession *session,
-- const char *user,
-- MsnUnifiedNotificationType type,
-- const char *payload);
--
--void msn_notification_send_circle_auth(MsnSession *session, const char *ticket);
--
--/**
-- * Closes a notification.
-- *
-- * It's first closed, and then disconnected.
-- *
-- * @param notification The notification object to close.
-- */
--void msn_notification_close(MsnNotification *notification);
--
--void msn_got_login_params(MsnSession *session, const char *ticket, const char *response);
--
--#endif /* MSN_NOTIFICATION_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/object.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/object.c
---- pidgin-2.10.7/libpurple/protocols/msn/object.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/object.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,459 +0,0 @@
--/**
-- * @file object.c MSNObject API
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "msn.h"
--#include "object.h"
--#include "debug.h"
--/* Sha1 stuff */
--#include "cipher.h"
--/* Base64 stuff */
--#include "util.h"
--
--#define GET_STRING_TAG(field, id) \
-- if ((tag = strstr(str, id "=\"")) != NULL) \
-- { \
-- tag += strlen(id "=\""); \
-- c = strchr(tag, '"'); \
-- if (c != NULL) \
-- { \
-- if (obj->field != NULL) \
-- g_free(obj->field); \
-- obj->field = g_strndup(tag, c - tag); \
-- } \
-- }
--
--#define GET_INT_TAG(field, id) \
-- if ((tag = strstr(str, id "=\"")) != NULL) \
-- { \
-- char buf[16]; \
-- size_t offset; \
-- tag += strlen(id "=\""); \
-- c = strchr(tag, '"'); \
-- if (c != NULL) \
-- { \
-- memset(buf, 0, sizeof(buf)); \
-- offset = c - tag; \
-- if (offset >= sizeof(buf)) \
-- offset = sizeof(buf) - 1; \
-- strncpy(buf, tag, offset); \
-- obj->field = atoi(buf); \
-- } \
-- }
--
--static GList *local_objs;
--
--MsnObject *
--msn_object_new(void)
--{
-- MsnObject *obj;
--
-- obj = g_new0(MsnObject, 1);
--
-- msn_object_set_type(obj, MSN_OBJECT_UNKNOWN);
-- msn_object_set_friendly(obj, "AAA=");
--
-- return obj;
--}
--
--MsnObject *
--msn_object_new_from_string(const char *str)
--{
-- MsnObject *obj;
-- char *tag, *c;
--
-- g_return_val_if_fail(str != NULL, NULL);
--
-- if (strncmp(str, "<msnobj ", 8))
-- return NULL;
--
-- obj = msn_object_new();
--
-- GET_STRING_TAG(creator, "Creator");
-- GET_INT_TAG(size, "Size");
-- GET_INT_TAG(type, "Type");
-- GET_STRING_TAG(location, "Location");
-- GET_STRING_TAG(friendly, "Friendly");
-- GET_STRING_TAG(sha1d, "SHA1D");
-- GET_STRING_TAG(sha1c, "SHA1C");
-- GET_STRING_TAG(url, "Url");
-- GET_STRING_TAG(url1, "Url1");
--
-- /* If we are missing any of the required elements then discard the object */
-- if (obj->creator == NULL || obj->size == 0 || obj->type == 0
-- || obj->sha1d == NULL) {
-- purple_debug_error("msn", "Discarding invalid msnobj: '%s'\n", str);
-- msn_object_destroy(obj);
-- return NULL;
-- }
--
-- if (obj->location == NULL || obj->friendly == NULL) {
-- /* Location/friendly are required for non-buddyicon objects */
-- if (obj->type != MSN_OBJECT_USERTILE) {
-- purple_debug_error("msn", "Discarding invalid msnobj: '%s'\n", str);
-- msn_object_destroy(obj);
-- return NULL;
-- /* Buddy icon object can contain Url/Url1 instead */
-- } else if (obj->url == NULL || obj->url1 == NULL) {
-- purple_debug_error("msn", "Discarding invalid msnobj: '%s'\n", str);
-- msn_object_destroy(obj);
-- return NULL;
-- }
-- }
--
-- return obj;
--}
--
--MsnObject*
--msn_object_new_from_image(PurpleStoredImage *img, const char *location,
-- const char *creator, MsnObjectType type)
--{
-- MsnObject *msnobj;
--
-- PurpleCipherContext *ctx;
-- char *buf;
-- gconstpointer data;
-- size_t size;
-- char *base64;
-- unsigned char digest[20];
--
-- msnobj = NULL;
--
-- if (img == NULL)
-- return msnobj;
--
-- size = purple_imgstore_get_size(img);
-- data = purple_imgstore_get_data(img);
--
-- /* New object */
-- msnobj = msn_object_new();
-- msn_object_set_local(msnobj);
-- msn_object_set_type(msnobj, type);
-- msn_object_set_location(msnobj, location);
-- msn_object_set_creator(msnobj, creator);
--
-- msn_object_set_image(msnobj, img);
--
-- /* Compute the SHA1D field. */
-- memset(digest, 0, sizeof(digest));
--
-- ctx = purple_cipher_context_new_by_name("sha1", NULL);
-- purple_cipher_context_append(ctx, data, size);
-- purple_cipher_context_digest(ctx, sizeof(digest), digest, NULL);
--
-- base64 = purple_base64_encode(digest, sizeof(digest));
-- msn_object_set_sha1d(msnobj, base64);
-- g_free(base64);
--
-- msn_object_set_size(msnobj, size);
--
-- /* Compute the SHA1C field. */
-- buf = g_strdup_printf(
-- "Creator%sSize%dType%dLocation%sFriendly%sSHA1D%s",
-- msn_object_get_creator(msnobj),
-- msn_object_get_size(msnobj),
-- msn_object_get_type(msnobj),
-- msn_object_get_location(msnobj),
-- msn_object_get_friendly(msnobj),
-- msn_object_get_sha1d(msnobj));
--
-- memset(digest, 0, sizeof(digest));
--
-- purple_cipher_context_reset(ctx, NULL);
-- purple_cipher_context_append(ctx, (const guchar *)buf, strlen(buf));
-- purple_cipher_context_digest(ctx, sizeof(digest), digest, NULL);
-- purple_cipher_context_destroy(ctx);
-- g_free(buf);
--
-- base64 = purple_base64_encode(digest, sizeof(digest));
-- msn_object_set_sha1c(msnobj, base64);
-- g_free(base64);
--
-- return msnobj;
--}
--
--void
--msn_object_destroy(MsnObject *obj)
--{
-- g_return_if_fail(obj != NULL);
--
-- g_free(obj->creator);
-- g_free(obj->location);
-- g_free(obj->friendly);
-- g_free(obj->sha1d);
-- g_free(obj->sha1c);
-- g_free(obj->url);
-- g_free(obj->url1);
--
-- purple_imgstore_unref(obj->img);
--
-- if (obj->local)
-- local_objs = g_list_remove(local_objs, obj);
--
-- g_free(obj);
--}
--
--char *
--msn_object_to_string(const MsnObject *obj)
--{
-- char *str;
-- const char *sha1c;
--
-- g_return_val_if_fail(obj != NULL, NULL);
--
-- sha1c = msn_object_get_sha1c(obj);
--
-- str = g_strdup_printf("<msnobj Creator=\"%s\" Size=\"%d\" Type=\"%d\" "
-- "Location=\"%s\" Friendly=\"%s\" SHA1D=\"%s\""
-- "%s%s%s/>",
-- msn_object_get_creator(obj),
-- msn_object_get_size(obj),
-- msn_object_get_type(obj),
-- msn_object_get_location(obj),
-- msn_object_get_friendly(obj),
-- msn_object_get_sha1d(obj),
-- sha1c ? " SHA1C=\"" : "",
-- sha1c ? sha1c : "",
-- sha1c ? "\"" : "");
--
-- return str;
--}
--
--void
--msn_object_set_creator(MsnObject *obj, const char *creator)
--{
-- g_return_if_fail(obj != NULL);
--
-- g_free(obj->creator);
-- obj->creator = g_strdup(creator);
--}
--
--void
--msn_object_set_size(MsnObject *obj, int size)
--{
-- g_return_if_fail(obj != NULL);
--
-- obj->size = size;
--}
--
--void
--msn_object_set_type(MsnObject *obj, MsnObjectType type)
--{
-- g_return_if_fail(obj != NULL);
--
-- obj->type = type;
--}
--
--void
--msn_object_set_location(MsnObject *obj, const char *location)
--{
-- g_return_if_fail(obj != NULL);
--
-- g_free(obj->location);
-- obj->location = g_strdup(location);
--}
--
--void
--msn_object_set_friendly(MsnObject *obj, const char *friendly)
--{
-- g_return_if_fail(obj != NULL);
--
-- g_free(obj->friendly);
-- obj->friendly = g_strdup(friendly);
--}
--
--void
--msn_object_set_sha1d(MsnObject *obj, const char *sha1d)
--{
-- g_return_if_fail(obj != NULL);
--
-- g_free(obj->sha1d);
-- obj->sha1d = g_strdup(sha1d);
--}
--
--void
--msn_object_set_sha1c(MsnObject *obj, const char *sha1c)
--{
-- g_return_if_fail(obj != NULL);
--
-- g_free(obj->sha1c);
-- obj->sha1c = g_strdup(sha1c);
--}
--
--void
--msn_object_set_url(MsnObject *obj, const char *url)
--{
-- g_return_if_fail(obj != NULL);
--
-- g_free(obj->url);
-- obj->url = g_strdup(url);
--}
--
--void
--msn_object_set_url1(MsnObject *obj, const char *url)
--{
-- g_return_if_fail(obj != NULL);
--
-- g_free(obj->url1);
-- obj->url1 = g_strdup(url);
--}
--
--const char *
--msn_object_get_creator(const MsnObject *obj)
--{
-- g_return_val_if_fail(obj != NULL, NULL);
--
-- return obj->creator;
--}
--
--int
--msn_object_get_size(const MsnObject *obj)
--{
-- g_return_val_if_fail(obj != NULL, 0);
--
-- return obj->size;
--}
--
--MsnObjectType
--msn_object_get_type(const MsnObject *obj)
--{
-- g_return_val_if_fail(obj != NULL, MSN_OBJECT_UNKNOWN);
--
-- return obj->type;
--}
--
--const char *
--msn_object_get_location(const MsnObject *obj)
--{
-- g_return_val_if_fail(obj != NULL, NULL);
--
-- return obj->location;
--}
--
--const char *
--msn_object_get_friendly(const MsnObject *obj)
--{
-- g_return_val_if_fail(obj != NULL, NULL);
--
-- return obj->friendly;
--}
--
--const char *
--msn_object_get_sha1d(const MsnObject *obj)
--{
-- g_return_val_if_fail(obj != NULL, NULL);
--
-- return obj->sha1d;
--}
--
--const char *
--msn_object_get_sha1c(const MsnObject *obj)
--{
-- g_return_val_if_fail(obj != NULL, NULL);
--
-- return obj->sha1c;
--}
--
--const char *
--msn_object_get_sha1(const MsnObject *obj)
--{
-- g_return_val_if_fail(obj != NULL, NULL);
--
-- if(obj->sha1c != NULL) {
-- return obj->sha1c;
-- } else {
-- return obj->sha1d;
-- }
--}
--
--const char *
--msn_object_get_url(const MsnObject *obj)
--{
-- g_return_val_if_fail(obj != NULL, NULL);
--
-- return obj->url;
--}
--
--const char *
--msn_object_get_url1(const MsnObject *obj)
--{
-- g_return_val_if_fail(obj != NULL, NULL);
--
-- return obj->url1;
--}
--
--MsnObject *
--msn_object_find_local(const char *sha1)
--{
-- GList *l;
--
-- g_return_val_if_fail(sha1 != NULL, NULL);
--
-- for (l = local_objs; l != NULL; l = l->next)
-- {
-- MsnObject *local_obj = l->data;
--
-- if (!strcmp(msn_object_get_sha1(local_obj), sha1))
-- return local_obj;
-- }
--
-- return NULL;
--
--}
--
--void
--msn_object_set_local(MsnObject *obj)
--{
-- g_return_if_fail(obj != NULL);
--
-- obj->local = TRUE;
--
-- local_objs = g_list_append(local_objs, obj);
--}
--
--void
--msn_object_set_image(MsnObject *obj, PurpleStoredImage *img)
--{
-- g_return_if_fail(obj != NULL);
-- g_return_if_fail(img != NULL);
--
-- /* obj->local = TRUE; */
--
-- purple_imgstore_unref(obj->img);
-- obj->img = purple_imgstore_ref(img);
--}
--
--PurpleStoredImage *
--msn_object_get_image(const MsnObject *obj)
--{
-- MsnObject *local_obj;
--
-- g_return_val_if_fail(obj != NULL, NULL);
--
-- local_obj = msn_object_find_local(msn_object_get_sha1(obj));
--
-- if (local_obj != NULL)
-- return local_obj->img;
--
-- return NULL;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/object.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/object.h
---- pidgin-2.10.7/libpurple/protocols/msn/object.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/object.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,276 +0,0 @@
--/**
-- * @file object.h MSNObject API
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_OBJECT_H
--#define MSN_OBJECT_H
--
--typedef enum
--{
-- MSN_OBJECT_UNKNOWN = -1, /**< Unknown object */
-- MSN_OBJECT_RESERVED1 = 1, /**< Reserved */
-- MSN_OBJECT_EMOTICON = 2, /**< Custom Emoticon */
-- MSN_OBJECT_USERTILE = 3, /**< UserTile (buddy icon) */
-- MSN_OBJECT_RESERVED2 = 4, /**< Reserved */
-- MSN_OBJECT_BACKGROUND = 5 /**< Background */
--} MsnObjectType;
--
--#include "internal.h"
--
--#include "imgstore.h"
--
--typedef struct
--{
-- gboolean local;
--
-- char *creator;
-- int size;
-- MsnObjectType type;
-- PurpleStoredImage *img;
-- char *location;
-- char *friendly;
-- char *sha1d;
-- char *sha1c;
-- char *url;
-- char *url1;
--} MsnObject;
--
--/**
-- * Creates a MsnObject structure.
-- *
-- * @return A new MsnObject structure.
-- */
--MsnObject *msn_object_new(void);
--
--/**
-- * Creates a MsnObject structure from a string.
-- *
-- * @param str The string.
-- *
-- * @return The new MsnObject structure.
-- */
--MsnObject *msn_object_new_from_string(const char *str);
--
--/**
-- * Creates a MsnObject structure from a stored image
-- *
-- * @param img The image associated to object
-- * @param location The object location as stored in MsnObject
-- * @param creator The creator of the object
-- * @param type The type of the object
-- *
-- * @return A new MsnObject structure
-- */
--MsnObject *msn_object_new_from_image(PurpleStoredImage *img,
-- const char *location, const char *creator, MsnObjectType type);
--
--/**
-- * Destroys an MsnObject structure.
-- *
-- * @param obj The object structure.
-- */
--void msn_object_destroy(MsnObject *obj);
--
--/**
-- * Outputs a string representation of an MsnObject.
-- *
-- * @param obj The object.
-- *
-- * @return The string representation. This must be freed.
-- */
--char *msn_object_to_string(const MsnObject *obj);
--
--/**
-- * Sets the creator field in a MsnObject.
-- *
-- * @param creator The creator value.
-- */
--void msn_object_set_creator(MsnObject *obj, const char *creator);
--
--/**
-- * Sets the size field in a MsnObject.
-- *
-- * @param size The size value.
-- */
--void msn_object_set_size(MsnObject *obj, int size);
--
--/**
-- * Sets the type field in a MsnObject.
-- *
-- * @param type The type value.
-- */
--void msn_object_set_type(MsnObject *obj, MsnObjectType type);
--
--/**
-- * Sets the location field in a MsnObject.
-- *
-- * @param location The location value.
-- */
--void msn_object_set_location(MsnObject *obj, const char *location);
--
--/**
-- * Sets the friendly name field in a MsnObject.
-- *
-- * @param friendly The friendly name value.
-- */
--void msn_object_set_friendly(MsnObject *obj, const char *friendly);
--
--/**
-- * Sets the SHA1D field in a MsnObject.
-- *
-- * @param sha1d The sha1d value.
-- */
--void msn_object_set_sha1d(MsnObject *obj, const char *sha1d);
--
--/**
-- * Sets the SHA1C field in a MsnObject.
-- *
-- * @param sha1c The sha1c value.
-- */
--void msn_object_set_sha1c(MsnObject *obj, const char *sha1c);
--
--/**
-- * Associates an image with a MsnObject.
-- *
-- * @param obj The object.
-- * @param img The image to associate.
-- */
--void msn_object_set_image(MsnObject *obj, PurpleStoredImage *img);
--
--/**
-- * Sets the url field in a MsnObject.
-- *
-- * @param url The url value.
-- */
--void msn_object_set_url(MsnObject *obj, const char *url);
--
--/**
-- * Sets the url1 field in a MsnObject.
-- *
-- * @param url1 The url1 value.
-- */
--void msn_object_set_url1(MsnObject *obj, const char *url);
--
--/**
-- * Returns a MsnObject's creator value.
-- *
-- * @param obj The object.
-- *
-- * @return The creator value.
-- */
--const char *msn_object_get_creator(const MsnObject *obj);
--
--/**
-- * Returns a MsnObject's size value.
-- *
-- * @param obj The object.
-- *
-- * @return The size value.
-- */
--int msn_object_get_size(const MsnObject *obj);
--
--/**
-- * Returns a MsnObject's type.
-- *
-- * @param obj The object.
-- *
-- * @return The object type.
-- */
--MsnObjectType msn_object_get_type(const MsnObject *obj);
--
--/**
-- * Returns a MsnObject's location value.
-- *
-- * @param obj The object.
-- *
-- * @return The location value.
-- */
--const char *msn_object_get_location(const MsnObject *obj);
--
--/**
-- * Returns a MsnObject's friendly name value.
-- *
-- * @param obj The object.
-- *
-- * @return The friendly name value.
-- */
--const char *msn_object_get_friendly(const MsnObject *obj);
--
--/**
-- * Returns a MsnObject's SHA1D value.
-- *
-- * @param obj The object.
-- *
-- * @return The SHA1D value.
-- */
--const char *msn_object_get_sha1d(const MsnObject *obj);
--
--/**
-- * Returns a MsnObject's SHA1C value.
-- *
-- * @param obj The object.
-- *
-- * @return The SHA1C value.
-- */
--const char *msn_object_get_sha1c(const MsnObject *obj);
--
--/**
-- * Returns a MsnObject's SHA1C value if it exists, otherwise SHA1D.
-- *
-- * @param obj The object.
-- *
-- * @return The SHA1C value.
-- */
--const char *msn_object_get_sha1(const MsnObject *obj);
--
--/**
-- * Returns the image associated with the MsnObject.
-- *
-- * @param obj The object.
-- *
-- * @return The associated image.
-- */
--PurpleStoredImage *msn_object_get_image(const MsnObject *obj);
--
--/**
-- * Returns a MsnObject's url value.
-- *
-- * @param obj The object.
-- *
-- * @return The url value.
-- */
--const char *msn_object_get_url(const MsnObject *obj);
--
--/**
-- * Returns a MsnObject's url1 value.
-- *
-- * @param obj The object.
-- *
-- * @return The url1 value.
-- */
--const char *msn_object_get_url1(const MsnObject *obj);
--
--MsnObject * msn_object_find_local(const char *sha1);
--
--void msn_object_set_local(MsnObject *obj);
--
--#endif /* MSN_OBJECT_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/oim.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/oim.c
---- pidgin-2.10.7/libpurple/protocols/msn/oim.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/oim.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,885 +0,0 @@
--/**
-- * @file oim.c
-- * get and send MSN offline Instant Message via SOAP request
-- * Author
-- * MaYuan<mayuan2006@gmail.com>
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "soap.h"
--#include "oim.h"
--#include "msnutils.h"
--
--typedef struct _MsnOimSendReq {
-- char *from_member;
-- char *friendname;
-- char *to_member;
-- char *oim_msg;
--} MsnOimSendReq;
--
--typedef struct {
-- MsnOim *oim;
-- char *msg_id;
--} MsnOimRecvData;
--
--/*Local Function Prototype*/
--static void msn_parse_oim_xml(MsnOim *oim, xmlnode *node);
--static void msn_oim_free_send_req(MsnOimSendReq *req);
--static void msn_oim_recv_data_free(MsnOimRecvData *data);
--static void msn_oim_post_single_get_msg(MsnOim *oim, MsnOimRecvData *data);
--
--/*new a OIM object*/
--MsnOim *
--msn_oim_new(MsnSession *session)
--{
-- MsnOim *oim;
--
-- oim = g_new0(MsnOim, 1);
-- oim->session = session;
-- oim->oim_list = NULL;
-- oim->run_id = rand_guid();
-- oim->challenge = NULL;
-- oim->send_queue = g_queue_new();
-- oim->send_seq = 1;
-- return oim;
--}
--
--/*destroy the oim object*/
--void
--msn_oim_destroy(MsnOim *oim)
--{
-- MsnOimSendReq *request;
--
-- purple_debug_info("msn", "destroy the OIM %p\n", oim);
-- g_free(oim->run_id);
-- g_free(oim->challenge);
--
-- while ((request = g_queue_pop_head(oim->send_queue)) != NULL)
-- msn_oim_free_send_req(request);
-- g_queue_free(oim->send_queue);
--
-- while (oim->oim_list != NULL)
-- msn_oim_recv_data_free((MsnOimRecvData *)oim->oim_list->data);
--
-- g_free(oim);
--}
--
--static MsnOimSendReq *
--msn_oim_new_send_req(const char *from_member, const char*friendname,
-- const char* to_member, const char *msg)
--{
-- MsnOimSendReq *request;
--
-- request = g_new0(MsnOimSendReq, 1);
-- request->from_member = g_strdup(from_member);
-- request->friendname = g_strdup(friendname);
-- request->to_member = g_strdup(to_member);
-- request->oim_msg = g_strdup(msg);
-- return request;
--}
--
--static void
--msn_oim_free_send_req(MsnOimSendReq *req)
--{
-- g_return_if_fail(req != NULL);
--
-- g_free(req->from_member);
-- g_free(req->friendname);
-- g_free(req->to_member);
-- g_free(req->oim_msg);
--
-- g_free(req);
--}
--
--static MsnOimRecvData *
--msn_oim_recv_data_new(MsnOim *oim, char *msg_id)
--{
-- MsnOimRecvData *data;
--
-- data = g_new0(MsnOimRecvData, 1);
-- data->oim = oim;
-- data->msg_id = msg_id;
--
-- oim->oim_list = g_list_append(oim->oim_list, data);
--
-- return data;
--}
--
--/* Probably only good for g_list_find_custom */
--static gint
--msn_recv_data_equal(MsnOimRecvData *a, const char *msg_id)
--{
-- return strcmp(a->msg_id, msg_id);
--}
--
--static void
--msn_oim_recv_data_free(MsnOimRecvData *data)
--{
-- data->oim->oim_list = g_list_remove(data->oim->oim_list, data);
-- g_free(data->msg_id);
--
-- g_free(data);
--}
--
--/****************************************
-- * Manage OIM Tokens
-- ****************************************/
--typedef struct _MsnOimRequestData {
-- MsnOim *oim;
-- gboolean send;
-- const char *action;
-- const char *host;
-- const char *url;
-- xmlnode *body;
-- MsnSoapCallback cb;
-- gpointer cb_data;
--} MsnOimRequestData;
--
--static gboolean msn_oim_request_helper(MsnOimRequestData *data);
--
--static void
--msn_oim_request_cb(MsnSoapMessage *request, MsnSoapMessage *response,
-- gpointer req_data)
--{
-- MsnOimRequestData *data = (MsnOimRequestData *)req_data;
-- xmlnode *fault = NULL;
-- xmlnode *faultcode = NULL;
--
-- if (response != NULL)
-- fault = xmlnode_get_child(response->xml, "Body/Fault");
--
-- if (fault && (faultcode = xmlnode_get_child(fault, "faultcode"))) {
-- gchar *faultcode_str = xmlnode_get_data(faultcode);
-- gboolean need_token_update = FALSE;
--
-- if (faultcode_str) {
-- if (g_str_equal(faultcode_str, "q0:BadContextToken") ||
-- g_str_equal(faultcode_str, "AuthenticationFailed") ||
-- g_str_equal(faultcode_str, "s:AuthenticationFailed"))
-- need_token_update = TRUE;
-- else if (g_str_equal(faultcode_str, "q0:AuthenticationFailed") &&
-- xmlnode_get_child(fault, "detail/RequiredAuthPolicy") != NULL)
-- need_token_update = TRUE;
-- }
--
-- if (need_token_update) {
-- purple_debug_warning("msn", "OIM Request Error, Updating token now.\n");
-- msn_nexus_update_token(data->oim->session->nexus,
-- data->send ? MSN_AUTH_LIVE_SECURE : MSN_AUTH_MESSENGER_WEB,
-- (GSourceFunc)msn_oim_request_helper, data);
-- g_free(faultcode_str);
-- return;
--
-- }
--
-- g_free(faultcode_str);
-- }
--
-- if (data->cb)
-- data->cb(request, response, data->cb_data);
-- xmlnode_free(data->body);
-- g_free(data);
--}
--
--static gboolean
--msn_oim_request_helper(MsnOimRequestData *data)
--{
-- MsnSession *session = data->oim->session;
--
-- if (data->send) {
-- /* The Sending of OIM's uses a different token for some reason. */
-- xmlnode *ticket;
-- ticket = xmlnode_get_child(data->body, "Header/Ticket");
-- xmlnode_set_attrib(ticket, "passport",
-- msn_nexus_get_token_str(session->nexus, MSN_AUTH_LIVE_SECURE));
-- }
-- else
-- {
-- xmlnode *passport;
-- xmlnode *xml_t;
-- xmlnode *xml_p;
-- GHashTable *token;
-- const char *msn_t;
-- const char *msn_p;
--
-- token = msn_nexus_get_token(session->nexus, MSN_AUTH_MESSENGER_WEB);
-- g_return_val_if_fail(token != NULL, FALSE);
--
-- msn_t = g_hash_table_lookup(token, "t");
-- msn_p = g_hash_table_lookup(token, "p");
--
-- g_return_val_if_fail(msn_t != NULL, FALSE);
-- g_return_val_if_fail(msn_p != NULL, FALSE);
--
-- passport = xmlnode_get_child(data->body, "Header/PassportCookie");
-- xml_t = xmlnode_get_child(passport, "t");
-- xml_p = xmlnode_get_child(passport, "p");
--
-- /* frees old token text, or the 'EMPTY' text if first time */
-- xmlnode_free(xml_t->child);
-- xmlnode_free(xml_p->child);
--
-- xmlnode_insert_data(xml_t, msn_t, -1);
-- xmlnode_insert_data(xml_p, msn_p, -1);
-- }
--
-- msn_soap_message_send(session,
-- msn_soap_message_new(data->action, xmlnode_copy(data->body)),
-- data->host, data->url, FALSE,
-- msn_oim_request_cb, data);
--
-- return FALSE;
--}
--
--
--static void
--msn_oim_make_request(MsnOim *oim, gboolean send, const char *action,
-- const char *host, const char *url, xmlnode *body, MsnSoapCallback cb,
-- gpointer cb_data)
--{
-- MsnOimRequestData *data = g_new0(MsnOimRequestData, 1);
-- data->oim = oim;
-- data->send = send;
-- data->action = action;
-- data->host = host;
-- data->url = url;
-- data->body = body;
-- data->cb = cb;
-- data->cb_data = cb_data;
--
-- msn_oim_request_helper(data);
--}
--
--/****************************************
-- * OIM GetMetadata request
-- * **************************************/
--static void
--msn_oim_get_metadata_cb(MsnSoapMessage *request, MsnSoapMessage *response,
-- gpointer data)
--{
-- MsnOim *oim = data;
--
-- if (response) {
-- msn_parse_oim_xml(oim,
-- xmlnode_get_child(response->xml, "Body/GetMetadataResponse/MD"));
-- }
--}
--
--/* Post to get the OIM Metadata */
--static void
--msn_oim_get_metadata(MsnOim *oim)
--{
-- msn_oim_make_request(oim, FALSE, MSN_OIM_GET_METADATA_ACTION,
-- MSN_OIM_RETRIEVE_HOST, MSN_OIM_RETRIEVE_URL,
-- xmlnode_from_str(MSN_OIM_GET_METADATA_TEMPLATE, -1),
-- msn_oim_get_metadata_cb, oim);
--}
--
--/****************************************
-- * OIM send SOAP request
-- * **************************************/
--/*encode the message to OIM Message Format*/
--static gchar *
--msn_oim_msg_to_str(MsnOim *oim, const char *body)
--{
-- GString *oim_body;
-- char *oim_base64;
-- char *c;
-- int len;
-- size_t base64_len;
--
-- purple_debug_info("msn", "Encoding OIM Message...\n");
-- len = strlen(body);
-- c = oim_base64 = purple_base64_encode((const guchar *)body, len);
-- base64_len = strlen(oim_base64);
-- purple_debug_info("msn", "Encoded base64 body:{%s}\n", oim_base64);
--
-- oim_body = g_string_new(NULL);
-- g_string_printf(oim_body, MSN_OIM_MSG_TEMPLATE,
-- oim->run_id, oim->send_seq);
--
--#define OIM_LINE_LEN 76
-- while (base64_len > OIM_LINE_LEN) {
-- g_string_append_len(oim_body, c, OIM_LINE_LEN);
-- g_string_append_c(oim_body, '\n');
-- c += OIM_LINE_LEN;
-- base64_len -= OIM_LINE_LEN;
-- }
--#undef OIM_LINE_LEN
--
-- g_string_append(oim_body, c);
--
-- g_free(oim_base64);
--
-- return g_string_free(oim_body, FALSE);
--}
--
--/*
-- * Process the send return SOAP string
-- * If got SOAP Fault,get the lock key,and resend it.
-- */
--static void
--msn_oim_send_read_cb(MsnSoapMessage *request, MsnSoapMessage *response,
-- gpointer data)
--{
-- MsnOim *oim = data;
-- MsnOimSendReq *msg = g_queue_pop_head(oim->send_queue);
--
-- g_return_if_fail(msg != NULL);
--
-- if (response == NULL) {
-- purple_debug_info("msn", "cannot send OIM: %s\n", msg->oim_msg);
-- } else {
-- xmlnode *faultNode = xmlnode_get_child(response->xml, "Body/Fault");
--
-- if (faultNode == NULL) {
-- /*Send OK! return*/
-- purple_debug_info("msn", "sent OIM: %s\n", msg->oim_msg);
-- } else {
-- xmlnode *faultcode = xmlnode_get_child(faultNode, "faultcode");
--
-- if (faultcode) {
-- char *faultcode_str = xmlnode_get_data(faultcode);
--
-- if (g_str_equal(faultcode_str, "q0:AuthenticationFailed")) {
-- xmlnode *challengeNode = xmlnode_get_child(faultNode,
-- "detail/LockKeyChallenge");
--
-- if (challengeNode == NULL) {
-- if (oim->challenge) {
-- g_free(oim->challenge);
-- oim->challenge = NULL;
--
-- purple_debug_info("msn", "Resending OIM: %s\n",
-- msg->oim_msg);
-- g_queue_push_head(oim->send_queue, msg);
-- msn_oim_send_msg(oim);
-- msg = NULL;
-- } else {
-- purple_debug_info("msn",
-- "Can't find lock key for OIM: %s\n",
-- msg->oim_msg);
-- }
-- } else {
-- char buf[33];
--
-- char *challenge = xmlnode_get_data(challengeNode);
-- msn_handle_chl(challenge, buf);
--
-- g_free(oim->challenge);
-- oim->challenge = g_strndup(buf, sizeof(buf));
-- g_free(challenge);
-- purple_debug_info("msn", "Found lockkey:{%s}\n", oim->challenge);
--
-- /*repost the send*/
-- purple_debug_info("msn", "Resending OIM: %s\n", msg->oim_msg);
-- g_queue_push_head(oim->send_queue, msg);
-- msn_oim_send_msg(oim);
-- msg = NULL;
-- }
-- } else {
-- /* Report the error */
-- const char *str_reason;
--
-- if (g_str_equal(faultcode_str, "q0:SystemUnavailable")) {
-- str_reason = _("Message was not sent because the system is "
-- "unavailable. This normally happens when the "
-- "user is blocked or does not exist.");
--
-- } else if (g_str_equal(faultcode_str, "q0:SenderThrottleLimitExceeded")) {
-- str_reason = _("Message was not sent because messages "
-- "are being sent too quickly.");
--
-- } else if (g_str_equal(faultcode_str, "q0:InvalidContent")) {
-- str_reason = _("Message was not sent because an unknown "
-- "encoding error occurred.");
--
-- } else {
-- str_reason = _("Message was not sent because an unknown "
-- "error occurred.");
-- }
--
-- msn_session_report_user(oim->session, msg->to_member,
-- str_reason, PURPLE_MESSAGE_ERROR);
-- msn_session_report_user(oim->session, msg->to_member,
-- msg->oim_msg, PURPLE_MESSAGE_RAW);
-- }
--
-- g_free(faultcode_str);
-- }
-- }
-- }
--
-- if (msg)
-- msn_oim_free_send_req(msg);
--}
--
--void
--msn_oim_prep_send_msg_info(MsnOim *oim, const char *membername,
-- const char* friendname, const char *tomember,
-- const char * msg)
--{
-- g_return_if_fail(oim != NULL);
--
-- g_queue_push_tail(oim->send_queue,
-- msn_oim_new_send_req(membername, friendname, tomember, msg));
--}
--
--/*post send single message request to oim server*/
--void
--msn_oim_send_msg(MsnOim *oim)
--{
-- MsnOimSendReq *oim_request;
-- char *soap_body;
-- char *msg_body;
--
-- g_return_if_fail(oim != NULL);
-- oim_request = g_queue_peek_head(oim->send_queue);
-- g_return_if_fail(oim_request != NULL);
--
-- purple_debug_info("msn", "Sending OIM: %s\n", oim_request->oim_msg);
--
-- /* if we got the challenge lock key, we compute it
-- * else we go for the SOAP fault and resend it.
-- */
-- if (oim->challenge == NULL){
-- purple_debug_info("msn", "No lock key challenge, waiting for SOAP Fault and Resend\n");
-- }
--
-- msg_body = msn_oim_msg_to_str(oim, oim_request->oim_msg);
-- soap_body = g_strdup_printf(MSN_OIM_SEND_TEMPLATE,
-- oim_request->from_member,
-- oim_request->friendname,
-- oim_request->to_member,
-- MSNP15_WLM_PRODUCT_ID,
-- oim->challenge ? oim->challenge : "",
-- oim->send_seq,
-- msg_body);
--
-- msn_oim_make_request(oim, TRUE, MSN_OIM_SEND_SOAP_ACTION, MSN_OIM_SEND_HOST,
-- MSN_OIM_SEND_URL, xmlnode_from_str(soap_body, -1), msn_oim_send_read_cb,
-- oim);
--
-- /*increase the offline Sequence control*/
-- if (oim->challenge != NULL) {
-- oim->send_seq++;
-- }
--
-- g_free(msg_body);
-- g_free(soap_body);
--}
--
--/****************************************
-- * OIM delete SOAP request
-- * **************************************/
--static void
--msn_oim_delete_read_cb(MsnSoapMessage *request, MsnSoapMessage *response,
-- gpointer data)
--{
-- MsnOimRecvData *rdata = data;
--
-- if (response && xmlnode_get_child(response->xml, "Body/Fault") == NULL)
-- purple_debug_info("msn", "Delete OIM success\n");
-- else
-- purple_debug_info("msn", "Delete OIM failed\n");
--
-- msn_oim_recv_data_free(rdata);
--}
--
--/*Post to get the Offline Instant Message*/
--static void
--msn_oim_post_delete_msg(MsnOimRecvData *rdata)
--{
-- MsnOim *oim = rdata->oim;
-- char *msgid = rdata->msg_id;
-- char *soap_body;
--
-- purple_debug_info("msn", "Delete single OIM Message {%s}\n",msgid);
--
-- soap_body = g_strdup_printf(MSN_OIM_DEL_TEMPLATE, msgid);
--
-- msn_oim_make_request(oim, FALSE, MSN_OIM_DEL_SOAP_ACTION, MSN_OIM_RETRIEVE_HOST,
-- MSN_OIM_RETRIEVE_URL, xmlnode_from_str(soap_body, -1), msn_oim_delete_read_cb, rdata);
--
-- g_free(soap_body);
--}
--
--/****************************************
-- * OIM get SOAP request
-- * **************************************/
--/* like purple_str_to_time, but different. The format of the timestamp
-- * is like this: 5 Sep 2007 21:42:12 -0700 */
--static time_t
--msn_oim_parse_timestamp(const char *timestamp)
--{
-- char month_str[4], tz_str[6];
-- char *tz_ptr = tz_str;
-- static const char *months[] = {
-- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL
-- };
-- time_t tval = 0;
-- struct tm t;
-- memset(&t, 0, sizeof(t));
--
-- time(&tval);
-- localtime_r(&tval, &t);
--
-- if (sscanf(timestamp, "%02d %03s %04d %02d:%02d:%02d %05s",
-- &t.tm_mday, month_str, &t.tm_year,
-- &t.tm_hour, &t.tm_min, &t.tm_sec, tz_str) == 7) {
-- gboolean offset_positive = TRUE;
-- int tzhrs;
-- int tzmins;
--
-- for (t.tm_mon = 0;
-- months[t.tm_mon] != NULL &&
-- strcmp(months[t.tm_mon], month_str) != 0; t.tm_mon++);
-- if (months[t.tm_mon] != NULL) {
-- if (*tz_str == '-') {
-- offset_positive = FALSE;
-- tz_ptr++;
-- } else if (*tz_str == '+') {
-- tz_ptr++;
-- }
--
-- if (sscanf(tz_ptr, "%02d%02d", &tzhrs, &tzmins) == 2) {
-- time_t tzoff = tzhrs * 60 * 60 + tzmins * 60;
--#ifdef _WIN32
-- long sys_tzoff;
--#endif
--
-- if (offset_positive)
-- tzoff *= -1;
--
-- t.tm_year -= 1900;
--
--#ifdef _WIN32
-- if ((sys_tzoff = wpurple_get_tz_offset()) != -1)
-- tzoff += sys_tzoff;
--#else
--#ifdef HAVE_TM_GMTOFF
-- tzoff += t.tm_gmtoff;
--#else
--# ifdef HAVE_TIMEZONE
-- tzset(); /* making sure */
-- tzoff -= timezone;
--# endif
--#endif
--#endif /* _WIN32 */
--
-- return mktime(&t) + tzoff;
-- }
-- }
-- }
--
-- purple_debug_info("msn", "Can't parse timestamp %s\n", timestamp);
-- return tval;
--}
--
--/*Post the Offline Instant Message to User Conversation*/
--static void
--msn_oim_report_to_user(MsnOimRecvData *rdata, const char *msg_str)
--{
-- MsnMessage *message;
-- const char *date;
-- const char *from;
-- const char *boundary;
-- char *decode_msg = NULL, *clean_msg = NULL;
-- gsize body_len;
-- char **tokens;
-- char *passport = NULL;
-- time_t stamp;
-- const char *charset = NULL;
--
-- message = msn_message_new(MSN_MSG_UNKNOWN);
--
-- msn_message_parse_payload(message, msg_str, strlen(msg_str),
-- MSG_OIM_LINE_DEM, MSG_OIM_BODY_DEM);
-- purple_debug_info("msn", "oim body:{%s}\n", message->body);
--
-- boundary = msn_message_get_header_value(message, "boundary");
--
-- if (boundary != NULL) {
-- char *bounds;
-- char **part;
--
-- bounds = g_strdup_printf("--%s" MSG_OIM_LINE_DEM, boundary);
-- tokens = g_strsplit(message->body, bounds, 0);
--
-- /* tokens+1 to skip the "This is a multipart message..." text */
-- for (part = tokens+1; *part != NULL; part++) {
-- MsnMessage *multipart;
-- const char *type;
-- multipart = msn_message_new(MSN_MSG_UNKNOWN);
-- msn_message_parse_payload(multipart, *part, strlen(*part),
-- MSG_OIM_LINE_DEM, MSG_OIM_BODY_DEM);
--
-- type = msn_message_get_content_type(multipart);
-- if (type && !strcmp(type, "text/plain")) {
-- decode_msg = (char *)purple_base64_decode(multipart->body, &body_len);
-- charset = msn_message_get_charset(multipart);
--
-- msn_message_unref(multipart);
-- break;
-- }
-- msn_message_unref(multipart);
-- }
--
-- g_strfreev(tokens);
-- g_free(bounds);
--
-- if (decode_msg == NULL) {
-- purple_debug_error("msn", "Couldn't find text/plain OIM message.\n");
-- msn_message_unref(message);
-- return;
-- }
-- } else {
-- decode_msg = (char *)purple_base64_decode(message->body, &body_len);
-- charset = msn_message_get_charset(message);
-- }
--
-- if (charset && !((g_ascii_strncasecmp(charset, "UTF-8", 5) == 0) || (g_ascii_strncasecmp(charset, "UTF8", 4) == 0))) {
-- clean_msg = g_convert(decode_msg, body_len, "UTF-8", charset, NULL, NULL, NULL);
--
-- if (!clean_msg) {
-- char *clean = purple_utf8_salvage(decode_msg);
--
-- purple_debug_error("msn", "Failed to convert charset from %s to UTF-8 for OIM message: %s\n", charset, clean);
--
-- clean_msg = g_strdup_printf(_("%s (There was an error receiving this message. "
-- "Converting the encoding from %s to UTF-8 failed.)"),
-- clean, charset);
-- g_free(clean);
-- }
--
-- g_free(decode_msg);
--
-- } else if (!g_utf8_validate(decode_msg, body_len, NULL)) {
-- char *clean = purple_utf8_salvage(decode_msg);
--
-- purple_debug_error("msn", "Received an OIM message that is not UTF-8,"
-- " and no encoding specified: %s\n", clean);
--
-- if (charset) {
-- clean_msg = g_strdup_printf(_("%s (There was an error receiving this message."
-- " The charset was %s, but it was not valid UTF-8.)"),
-- clean, charset);
-- } else {
-- clean_msg = g_strdup_printf(_("%s (There was an error receiving this message."
-- " The charset was missing, but it was not valid UTF-8.)"),
-- clean);
-- }
--
-- g_free(clean);
-- g_free(decode_msg);
--
-- } else {
-- clean_msg = decode_msg;
-- }
--
-- from = msn_message_get_header_value(message, "X-OIM-originatingSource");
--
-- /* Match number to user's mobile number, FROM is a phone number
-- if the other side pages you using your phone number */
-- if (from && !strncmp(from, "tel:+", 5)) {
-- MsnUser *user = msn_userlist_find_user_with_mobile_phone(
-- rdata->oim->session->userlist, from + 4);
--
-- if (user && user->passport)
-- passport = g_strdup(user->passport);
-- }
--
-- if (passport == NULL) {
-- char *start, *end;
--
-- from = msn_message_get_header_value(message, "From");
--
-- tokens = g_strsplit(from, " ", 2);
-- if (tokens[1] != NULL)
-- from = (const char *)tokens[1];
--
-- start = strchr(from, '<');
-- if (start != NULL) {
-- start++;
-- end = strchr(from, '>');
-- if (end != NULL)
-- passport = g_strndup(start, end - start);
-- }
-- if (passport == NULL)
-- passport = g_strdup(_("Unknown"));
--
-- g_strfreev(tokens);
-- }
--
-- date = msn_message_get_header_value(message, "Date");
-- stamp = msn_oim_parse_timestamp(date);
-- purple_debug_info("msn", "oim Date:{%s},passport{%s}\n",
-- date, passport);
--
-- serv_got_im(purple_account_get_connection(rdata->oim->session->account), passport, clean_msg, 0,
-- stamp);
--
-- /*Now get the oim message ID from the oim_list.
-- * and append to read list to prepare for deleting the Offline Message when sign out
-- */
-- msn_oim_post_delete_msg(rdata);
--
-- g_free(passport);
-- g_free(clean_msg);
-- msn_message_unref(message);
--}
--
--/* Parse the XML data,
-- * prepare to report the OIM to user
-- */
--static void
--msn_oim_get_read_cb(MsnSoapMessage *request, MsnSoapMessage *response,
-- gpointer data)
--{
-- MsnOimRecvData *rdata = data;
--
-- if (response != NULL) {
-- xmlnode *msg_node = xmlnode_get_child(response->xml,
-- "Body/GetMessageResponse/GetMessageResult");
--
-- if (msg_node) {
-- char *msg_str = xmlnode_get_data(msg_node);
-- msn_oim_report_to_user(rdata, msg_str);
-- g_free(msg_str);
-- } else {
-- char *str = xmlnode_to_str(response->xml, NULL);
-- purple_debug_info("msn", "Unknown OIM response: %s\n", str);
-- g_free(str);
-- msn_oim_recv_data_free(rdata);
-- }
-- } else {
-- purple_debug_info("msn", "Failed to get OIM\n");
-- msn_oim_recv_data_free(rdata);
-- }
--
--}
--
--/* parse the oim XML data
-- * and post it to the soap server to get the Offline Message
-- * */
--void
--msn_parse_oim_msg(MsnOim *oim,const char *xmlmsg)
--{
-- xmlnode *node;
--
-- purple_debug_info("msn", "%s\n", xmlmsg);
--
-- if (!strcmp(xmlmsg, "too-large")) {
-- /* Too many OIM's to send via NS, so we need to request them via SOAP. */
-- msn_oim_get_metadata(oim);
-- } else {
-- node = xmlnode_from_str(xmlmsg, -1);
-- msn_parse_oim_xml(oim, node);
-- xmlnode_free(node);
-- }
--}
--
--static void
--msn_parse_oim_xml(MsnOim *oim, xmlnode *node)
--{
-- xmlnode *mNode;
-- xmlnode *iu_node;
-- MsnSession *session = oim->session;
--
-- g_return_if_fail(node != NULL);
--
-- if (strcmp(node->name, "MD") != 0) {
-- char *xmlmsg = xmlnode_to_str(node, NULL);
-- purple_debug_info("msn", "WTF is this? %s\n", xmlmsg);
-- g_free(xmlmsg);
-- return;
-- }
--
-- iu_node = xmlnode_get_child(node, "E/IU");
--
-- if (iu_node != NULL && purple_account_get_check_mail(session->account))
-- {
-- char *unread = xmlnode_get_data(iu_node);
-- const char *passports[2] = { msn_user_get_passport(session->user) };
-- const char *urls[2] = { session->passport_info.mail_url };
-- int count = atoi(unread);
--
-- /* XXX/khc: pretty sure this is wrong */
-- if (count > 0)
-- purple_notify_emails(session->account->gc, count, FALSE, NULL,
-- NULL, passports, urls, NULL, NULL);
-- g_free(unread);
-- }
--
-- for(mNode = xmlnode_get_child(node, "M"); mNode;
-- mNode = xmlnode_get_next_twin(mNode)){
-- char *passport, *msgid, *nickname, *rtime = NULL;
-- xmlnode *e_node, *i_node, *n_node, *rt_node;
--
-- e_node = xmlnode_get_child(mNode, "E");
-- passport = xmlnode_get_data(e_node);
--
-- i_node = xmlnode_get_child(mNode, "I");
-- msgid = xmlnode_get_data(i_node);
--
-- n_node = xmlnode_get_child(mNode, "N");
-- nickname = xmlnode_get_data(n_node);
--
-- rt_node = xmlnode_get_child(mNode, "RT");
-- if (rt_node != NULL) {
-- rtime = xmlnode_get_data(rt_node);
-- }
--/* purple_debug_info("msn", "E:{%s},I:{%s},rTime:{%s}\n",passport,msgid,rTime); */
--
-- if (!g_list_find_custom(oim->oim_list, msgid, (GCompareFunc)msn_recv_data_equal)) {
-- MsnOimRecvData *data = msn_oim_recv_data_new(oim, msgid);
-- msn_oim_post_single_get_msg(oim, data);
-- msgid = NULL;
-- }
--
-- g_free(passport);
-- g_free(msgid);
-- g_free(rtime);
-- g_free(nickname);
-- }
--}
--
--/*Post to get the Offline Instant Message*/
--static void
--msn_oim_post_single_get_msg(MsnOim *oim, MsnOimRecvData *data)
--{
-- char *soap_body;
--
-- purple_debug_info("msn", "Get single OIM Message\n");
--
-- soap_body = g_strdup_printf(MSN_OIM_GET_TEMPLATE, data->msg_id);
--
-- msn_oim_make_request(oim, FALSE, MSN_OIM_GET_SOAP_ACTION, MSN_OIM_RETRIEVE_HOST,
-- MSN_OIM_RETRIEVE_URL, xmlnode_from_str(soap_body, -1), msn_oim_get_read_cb,
-- data);
--
-- g_free(soap_body);
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/oim.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/oim.h
---- pidgin-2.10.7/libpurple/protocols/msn/oim.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/oim.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,163 +0,0 @@
--/**
-- * @file oim.h Header file for oim.c
-- * Author
-- * MaYuan<mayuan2006@gmail.com>
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-- */
--#ifndef MSN_OIM_H
--#define MSN_OIM_H
--
--typedef struct _MsnOim MsnOim;
--
--/* OIM Retrieval Info */
--#define MSN_OIM_RETRIEVE_HOST "rsi.hotmail.com"
--#define MSN_OIM_RETRIEVE_URL "/rsi/rsi.asmx"
--
--/* OIM GetMetadata SOAP Template */
--#define MSN_OIM_GET_METADATA_ACTION "http://www.hotmail.msn.com/ws/2004/09/oim/rsi/GetMetadata"
--
--#define MSN_OIM_GET_METADATA_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope"\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
-- "<soap:Header>"\
-- "<PassportCookie xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
-- "<t>EMPTY</t>"\
-- "<p>EMPTY</p>"\
-- "</PassportCookie>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<GetMetadata xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\" />"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--/*OIM GetMessage SOAP Template*/
--#define MSN_OIM_GET_SOAP_ACTION "http://www.hotmail.msn.com/ws/2004/09/oim/rsi/GetMessage"
--
--#define MSN_OIM_GET_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope"\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
-- "<soap:Header>"\
-- "<PassportCookie xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
-- "<t>EMPTY</t>"\
-- "<p>EMPTY</p>"\
-- "</PassportCookie>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<GetMessage xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
-- "<messageId>%s</messageId>"\
-- "<alsoMarkAsRead>false</alsoMarkAsRead>"\
-- "</GetMessage>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--/*OIM DeleteMessages SOAP Template*/
--#define MSN_OIM_DEL_SOAP_ACTION "http://www.hotmail.msn.com/ws/2004/09/oim/rsi/DeleteMessages"
--
--#define MSN_OIM_DEL_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope"\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
-- "<soap:Header>"\
-- "<PassportCookie xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
-- "<t>EMPTY</t>"\
-- "<p>EMPTY</p>"\
-- "</PassportCookie>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<DeleteMessages xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
-- "<messageIds>"\
-- "<messageId>%s</messageId>"\
-- "</messageIds>"\
-- "</DeleteMessages>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--/*OIM Send SOAP Template*/
--#define MSN_OIM_MSG_TEMPLATE "MIME-Version: 1.0\n"\
-- "Content-Type: text/plain; charset=UTF-8\n"\
-- "Content-Transfer-Encoding: base64\n"\
-- "X-OIM-Message-Type: OfflineMessage\n"\
-- "X-OIM-Run-Id: {%s}\n"\
-- "X-OIM-Sequence-Num: %d\n\n"
--
--#define MSN_OIM_SEND_HOST "ows.messenger.msn.com"
--#define MSN_OIM_SEND_URL "/OimWS/oim.asmx"
--#define MSN_OIM_SEND_SOAP_ACTION "http://messenger.live.com/ws/2006/09/oim/Store2"
--#define MSN_OIM_SEND_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
--"<soap:Envelope"\
-- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
-- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
-- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
-- "<soap:Header>"\
-- "<From"\
-- " memberName=\"%s\""\
-- " friendlyName=\"%s\""\
-- " xml:lang=\"en-US\""\
-- " proxy=\"MSNMSGR\""\
-- " xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\""\
-- " msnpVer=\"MSNP15\""\
-- " buildVer=\"8.5.1288\"/>"\
-- "<To memberName=\"%s\" xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\"/>"\
-- "<Ticket passport=\"EMPTY\" appid=\"%s\" lockkey=\"%s\" xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\"/>"\
-- "<Sequence xmlns=\"http://schemas.xmlsoap.org/ws/2003/03/rm\">"\
-- "<Identifier xmlns=\"http://schemas.xmlsoap.org/ws/2002/07/utility\">http://messenger.msn.com</Identifier>"\
-- "<MessageNumber>%d</MessageNumber>"\
-- "</Sequence>"\
-- "</soap:Header>"\
-- "<soap:Body>"\
-- "<MessageType xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\">text</MessageType>"\
-- "<Content xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\">%s</Content>"\
-- "</soap:Body>"\
--"</soap:Envelope>"
--
--struct _MsnOim
--{
-- MsnSession *session;
--
-- GList * oim_list;
--
-- char *challenge;
-- char *run_id;
-- gint send_seq;
-- GQueue *send_queue;
--};
--
--/****************************************************
-- * function prototype
-- * **************************************************/
--MsnOim * msn_oim_new(MsnSession *session);
--void msn_oim_destroy(MsnOim *oim);
--
--void msn_parse_oim_msg(MsnOim *oim,const char *xmlmsg);
--
--/*Send OIM Message*/
--void msn_oim_prep_send_msg_info(MsnOim *oim, const char *membername,
-- const char *friendname, const char *tomember,
-- const char * msg);
--
--void msn_oim_send_msg(MsnOim *oim);
--
--#endif/* MSN_OIM_H*/
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/p2p.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/p2p.c
---- pidgin-2.10.7/libpurple/protocols/msn/p2p.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/p2p.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,870 +0,0 @@
--/**
-- * @file p2p.c MSN P2P functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "p2p.h"
--#include "tlv.h"
--#include "msnutils.h"
--
--MsnP2PInfo *
--msn_p2p_info_new(MsnP2PVersion version)
--{
-- MsnP2PInfo *info = g_new0(MsnP2PInfo, 1);
-- info->version = version;
--
-- switch (version) {
-- case MSN_P2P_VERSION_ONE:
-- case MSN_P2P_VERSION_TWO:
-- /* Nothing to do */
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", version);
-- g_free(info);
-- info = NULL;
-- }
--
-- return info;
--}
--
--MsnP2PInfo *
--msn_p2p_info_dup(MsnP2PInfo *info)
--{
-- MsnP2PInfo *new_info = g_new0(MsnP2PInfo, 1);
--
-- new_info->version = info->version;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- *new_info = *info;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- *new_info = *info;
-- new_info->header.v2.header_tlv = msn_tlvlist_copy(info->header.v2.header_tlv);
-- new_info->header.v2.data_tlv = msn_tlvlist_copy(info->header.v2.data_tlv);
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- g_free(new_info);
-- new_info = NULL;
-- }
--
-- return new_info;
--}
--
--void
--msn_p2p_info_free(MsnP2PInfo *info)
--{
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- /* Nothing to do! */
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- msn_tlvlist_free(info->header.v2.header_tlv);
-- msn_tlvlist_free(info->header.v2.data_tlv);
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- g_free(info);
--}
--
--size_t
--msn_p2p_header_from_wire(MsnP2PInfo *info, const char *wire, size_t max_len)
--{
-- size_t len = 0;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE: {
-- MsnP2PHeader *header = &info->header.v1;
--
-- if (max_len < P2P_PACKET_HEADER_SIZE) {
-- /* Invalid packet length */
-- len = 0;
-- break;
-- }
--
-- header->session_id = msn_pop32le(wire);
-- header->id = msn_pop32le(wire);
-- header->offset = msn_pop64le(wire);
-- header->total_size = msn_pop64le(wire);
-- header->length = msn_pop32le(wire);
-- header->flags = msn_pop32le(wire);
-- header->ack_id = msn_pop32le(wire);
-- header->ack_sub_id = msn_pop32le(wire);
-- header->ack_size = msn_pop64le(wire);
--
-- len = P2P_PACKET_HEADER_SIZE;
-- break;
-- }
--
-- case MSN_P2P_VERSION_TWO: {
-- MsnP2Pv2Header *header = &info->header.v2;
--
-- header->header_len = msn_pop8(wire);
-- header->opcode = msn_pop8(wire);
-- header->message_len = msn_pop16be(wire);
-- header->base_id = msn_pop32be(wire);
-- if (header->header_len + header->message_len + P2P_PACKET_FOOTER_SIZE > max_len) {
-- /* Invalid header and data length */
-- len = 0;
-- break;
-- }
--
-- if (header->header_len > 8) {
-- header->header_tlv = msn_tlvlist_read(wire, header->header_len - 8);
-- wire += header->header_len - 8;
-- }
--
-- if (header->message_len > 0) {
-- /* Parse Data packet */
--
-- header->data_header_len = msn_pop8(wire);
-- if (header->data_header_len > header->message_len) {
-- /* Invalid data header length */
-- len = 0;
-- break;
-- }
-- header->data_tf = msn_pop8(wire);
-- header->package_number = msn_pop16be(wire);
-- header->session_id = msn_pop32be(wire);
--
-- if (header->data_header_len > 8) {
-- header->data_tlv = msn_tlvlist_read(wire, header->data_header_len - 8);
-- wire += header->data_header_len - 8;
-- }
-- }
--
-- len = header->header_len + header->message_len;
--
-- break;
-- }
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- return len;
--}
--
--char *
--msn_p2p_header_to_wire(MsnP2PInfo *info, size_t *len)
--{
-- char *wire = NULL;
-- char *tmp;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE: {
-- MsnP2PHeader *header = &info->header.v1;
-- tmp = wire = g_new(char, P2P_PACKET_HEADER_SIZE);
--
-- msn_push32le(tmp, header->session_id);
-- msn_push32le(tmp, header->id);
-- msn_push64le(tmp, header->offset);
-- msn_push64le(tmp, header->total_size);
-- msn_push32le(tmp, header->length);
-- msn_push32le(tmp, header->flags);
-- msn_push32le(tmp, header->ack_id);
-- msn_push32le(tmp, header->ack_sub_id);
-- msn_push64le(tmp, header->ack_size);
--
-- if (len)
-- *len = P2P_PACKET_HEADER_SIZE;
--
-- break;
-- }
--
-- case MSN_P2P_VERSION_TWO: {
-- MsnP2Pv2Header *header = &info->header.v2;
-- char *header_wire = NULL;
-- char *data_header_wire = NULL;
--
-- if (header->header_tlv != NULL)
-- header_wire = msn_tlvlist_write(header->header_tlv, (size_t *)&header->header_len);
-- else
-- header->header_len = 0;
--
-- if (header->data_tlv != NULL)
-- data_header_wire = msn_tlvlist_write(header->data_tlv, (size_t *)&header->data_header_len);
-- else
-- header->data_header_len = 0;
--
-- tmp = wire = g_new(char, 16 + header->header_len + header->data_header_len);
--
-- msn_push8(tmp, header->header_len + 8);
-- msn_push8(tmp, header->opcode);
-- msn_push16be(tmp, header->data_header_len + 8 + header->message_len);
-- msn_push32be(tmp, header->base_id);
--
-- if (header_wire != NULL) {
-- memcpy(tmp, header_wire, header->header_len);
-- tmp += header->header_len;
-- }
--
-- msn_push8(tmp, header->data_header_len + 8);
-- msn_push8(tmp, header->data_tf);
-- msn_push16be(tmp, header->package_number);
-- msn_push32be(tmp, header->session_id);
--
-- if (data_header_wire != NULL) {
-- memcpy(tmp, data_header_wire, header->data_header_len);
-- tmp += header->data_header_len;
-- }
--
-- if (len)
-- *len = header->header_len + header->data_header_len + 16;
--
-- break;
-- }
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- return wire;
--}
--
--size_t
--msn_p2p_footer_from_wire(MsnP2PInfo *info, const char *wire)
--{
-- MsnP2PFooter *footer;
--
-- footer = &info->footer;
--
-- footer->value = msn_pop32be(wire);
--
-- return P2P_PACKET_FOOTER_SIZE;
--}
--
--char *
--msn_p2p_footer_to_wire(MsnP2PInfo *info, size_t *len)
--{
-- MsnP2PFooter *footer;
-- char *wire;
-- char *tmp;
--
-- footer = &info->footer;
-- tmp = wire = g_new(char, P2P_PACKET_FOOTER_SIZE);
--
-- msn_push32be(tmp, footer->value);
--
-- if (len)
-- *len = P2P_PACKET_FOOTER_SIZE;
--
-- return wire;
--}
--
--void
--msn_p2p_info_to_string(MsnP2PInfo *info, GString *str)
--{
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE: {
-- MsnP2PHeader *header = &info->header.v1;
-- g_string_append_printf(str, "Session ID: %u\r\n", header->session_id);
-- g_string_append_printf(str, "ID: %u\r\n", header->id);
-- g_string_append_printf(str, "Offset: %" G_GUINT64_FORMAT "\r\n", header->offset);
-- g_string_append_printf(str, "Total size: %" G_GUINT64_FORMAT "\r\n", header->total_size);
-- g_string_append_printf(str, "Length: %u\r\n", header->length);
-- g_string_append_printf(str, "Flags: 0x%x\r\n", header->flags);
-- g_string_append_printf(str, "ACK ID: %u\r\n", header->ack_id);
-- g_string_append_printf(str, "SUB ID: %u\r\n", header->ack_sub_id);
-- g_string_append_printf(str, "ACK Size: %" G_GUINT64_FORMAT "\r\n", header->ack_size);
--
-- break;
-- }
--
-- case MSN_P2P_VERSION_TWO:
-- /* Nothing to do! */
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- g_string_append_printf(str, "Footer: 0x%08X\r\n", info->footer.value);
--}
--
--gboolean
--msn_p2p_msg_is_data(const MsnP2PInfo *info)
--{
-- gboolean data = FALSE;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE: {
-- guint32 flags = info->header.v1.flags;
-- data = (flags == P2P_MSN_OBJ_DATA ||
-- flags == (P2P_WLM2009_COMP | P2P_MSN_OBJ_DATA) ||
-- flags == P2P_FILE_DATA);
-- break;
-- }
--
-- case MSN_P2P_VERSION_TWO:
-- data = info->header.v2.message_len > 0;
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- return data;
--}
--
--gboolean
--msn_p2p_info_is_valid(MsnP2PInfo *info)
--{
-- gboolean valid = FALSE;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- valid = info->header.v1.total_size >= info->header.v1.length;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- /* Nothing to do! */
-- valid = TRUE;
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- return valid;
--}
--
--gboolean
--msn_p2p_info_is_first(MsnP2PInfo *info)
--{
-- gboolean first = FALSE;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- first = info->header.v1.offset == 0;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- /* Nothing to do! */
-- first = info->header.v2.data_tf & TF_FIRST;
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- return first;
--}
--
--gboolean
--msn_p2p_info_is_final(MsnP2PInfo *info)
--{
-- gboolean final = FALSE;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- final = info->header.v1.offset + info->header.v1.length >= info->header.v1.total_size;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- final = msn_tlv_gettlv(info->header.v2.data_tlv, P2P_DATA_TLV_REMAINING, 1) == NULL;
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- return final;
--}
--
--void
--msn_p2p_info_create_ack(MsnP2PInfo *old_info, MsnP2PInfo *new_info)
--{
-- switch (old_info->version) {
-- case MSN_P2P_VERSION_ONE: {
-- MsnP2PHeader *old = &old_info->header.v1;
-- MsnP2PHeader *new = &new_info->header.v1;
--
-- new->session_id = old->session_id;
-- new->flags = P2P_ACK;
-- new->ack_id = old->id;
-- new->ack_sub_id = old->ack_id;
-- new->ack_size = old->total_size;
-- break;
-- }
--
-- case MSN_P2P_VERSION_TWO: {
-- MsnP2Pv2Header *old = &old_info->header.v2;
-- MsnP2Pv2Header *new = &new_info->header.v2;
--
-- msn_tlvlist_add_32(&new->header_tlv, P2P_HEADER_TLV_TYPE_ACK, old->base_id + old->message_len);
-- new->opcode = P2P_OPCODE_NONE;
--
-- if (old->message_len > 0) {
-- if (!msn_tlv_gettlv(old->header_tlv, P2P_HEADER_TLV_TYPE_ACK, 1)) {
-- if (old->opcode & P2P_OPCODE_SYN) {
-- msn_tlv_t *ack_tlv;
-- new->opcode |= P2P_OPCODE_RAK;
--
-- ack_tlv = msn_tlv_gettlv(old->header_tlv, P2P_HEADER_TLV_TYPE_PEER_INFO, 1);
-- if (ack_tlv) {
-- msn_tlvlist_add_tlv(&new->header_tlv, ack_tlv);
-- new->opcode |= P2P_OPCODE_SYN;
-- }
-- }
-- }
-- }
-- break;
-- }
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", old_info->version);
-- }
--}
--
--gboolean
--msn_p2p_info_require_ack(MsnP2PInfo *info)
--{
-- gboolean ret = FALSE;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE: {
-- guint32 flags = msn_p2p_info_get_flags(info);
--
-- ret = flags == P2P_NO_FLAG || flags == P2P_WLM2009_COMP ||
-- msn_p2p_msg_is_data(info);
-- break;
-- }
--
-- case MSN_P2P_VERSION_TWO:
-- ret = (info->header.v2.opcode & P2P_OPCODE_RAK) > 0;
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- return ret;
--}
--
--gboolean
--msn_p2p_info_is_ack(MsnP2PInfo *info)
--{
-- gboolean ret = FALSE;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE: {
-- ret = msn_p2p_info_get_flags(info) == P2P_ACK;
-- break;
-- }
--
-- case MSN_P2P_VERSION_TWO:
-- ret = msn_tlv_gettlv(info->header.v2.header_tlv, P2P_HEADER_TLV_TYPE_ACK, 1) != NULL;
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- return ret;
--}
--
--void
--msn_p2p_info_init_first(MsnP2PInfo *info, MsnP2PInfo *old_info)
--{
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- info->header.v1.session_id = old_info->header.v1.session_id;
-- info->header.v1.flags = old_info->header.v1.flags;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- info->header.v2.data_tf = TF_FIRST;
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--}
--
--guint32
--msn_p2p_info_get_session_id(MsnP2PInfo *info)
--{
-- guint32 session_id = 0;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- session_id = info->header.v1.session_id;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- session_id = info->header.v2.session_id;
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- return session_id;
--}
--
--guint32
--msn_p2p_info_get_id(MsnP2PInfo *info)
--{
-- guint32 id = 0;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- id = info->header.v1.id;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- id = info->header.v2.base_id;
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- return id;
--}
--
--guint64
--msn_p2p_info_get_offset(MsnP2PInfo *info)
--{
-- guint64 offset = 0;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- offset = info->header.v1.offset;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- /* Nothing to do! */
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- return offset;
--}
--
--guint64
--msn_p2p_info_get_total_size(MsnP2PInfo *info)
--{
-- guint64 total_size = 0;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- total_size = info->header.v1.total_size;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- /* Nothing to do! */
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- return total_size;
--}
--
--guint32
--msn_p2p_info_get_length(MsnP2PInfo *info)
--{
-- guint32 length = 0;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- length = info->header.v1.length;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- /* Nothing to do! */
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- return length;
--}
--
--guint32
--msn_p2p_info_get_flags(MsnP2PInfo *info)
--{
-- guint32 flags = 0;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- flags = info->header.v1.flags;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- flags = info->header.v2.data_tf;
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- return flags;
--}
--
--guint32
--msn_p2p_info_get_ack_id(MsnP2PInfo *info)
--{
-- guint32 ack_id = 0;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- ack_id = info->header.v1.ack_id;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- /* Nothing to do! */
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- return ack_id;
--}
--
--guint32
--msn_p2p_info_get_ack_sub_id(MsnP2PInfo *info)
--{
-- guint32 ack_sub_id = 0;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- ack_sub_id = info->header.v1.ack_sub_id;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- /* Nothing to do! */
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- return ack_sub_id;
--}
--
--guint64
--msn_p2p_info_get_ack_size(MsnP2PInfo *info)
--{
-- guint64 ack_size = 0;
--
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- ack_size = info->header.v1.ack_size;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- /* Nothing to do! */
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
-- return ack_size;
--}
--
--guint32
--msn_p2p_info_get_app_id(MsnP2PInfo *info)
--{
-- return info->footer.value;
--}
--
--void
--msn_p2p_info_set_session_id(MsnP2PInfo *info, guint32 session_id)
--{
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- info->header.v1.session_id = session_id;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- info->header.v2.session_id = session_id;
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
--}
--
--void
--msn_p2p_info_set_id(MsnP2PInfo *info, guint32 id)
--{
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- info->header.v1.id = id;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- info->header.v2.base_id = id;
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--
--}
--
--void
--msn_p2p_info_set_offset(MsnP2PInfo *info, guint64 offset)
--{
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- info->header.v1.offset = offset;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- /* Nothing to do! */
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--}
--
--void
--msn_p2p_info_set_total_size(MsnP2PInfo *info, guint64 total_size)
--{
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- info->header.v1.total_size = total_size;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- /* Nothing to do! */
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--}
--
--void
--msn_p2p_info_set_length(MsnP2PInfo *info, guint32 length)
--{
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- info->header.v1.length = length;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- /* Nothing to do! */
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--}
--
--void
--msn_p2p_info_set_flags(MsnP2PInfo *info, guint32 flags)
--{
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- info->header.v1.flags = flags;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- info->header.v2.data_tf = flags;
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--}
--
--void
--msn_p2p_info_set_ack_id(MsnP2PInfo *info, guint32 ack_id)
--{
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- info->header.v1.ack_id = ack_id;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- /* Nothing to do! */
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--}
--
--void
--msn_p2p_info_set_ack_sub_id(MsnP2PInfo *info, guint32 ack_sub_id)
--{
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- info->header.v1.ack_sub_id = ack_sub_id;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- /* Nothing to do! */
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--}
--
--void
--msn_p2p_info_set_ack_size(MsnP2PInfo *info, guint64 ack_size)
--{
-- switch (info->version) {
-- case MSN_P2P_VERSION_ONE:
-- info->header.v1.ack_size = ack_size;
-- break;
--
-- case MSN_P2P_VERSION_TWO:
-- /* Nothing to do! */
-- break;
--
-- default:
-- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
-- }
--}
--
--void
--msn_p2p_info_set_app_id(MsnP2PInfo *info, guint32 app_id)
--{
-- info->footer.value = app_id;
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/p2p.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/p2p.h
---- pidgin-2.10.7/libpurple/protocols/msn/p2p.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/p2p.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,264 +0,0 @@
--/**
-- * @file p2p.h MSN P2P functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef MSN_P2P_H
--#define MSN_P2P_H
--
--typedef struct {
-- guint32 session_id;
-- guint32 id;
-- /**
-- * In a MsnSlpMessage:
-- * For outgoing messages this is the number of bytes from buffer that
-- * have already been sent out. For incoming messages this is the
-- * number of bytes that have been written to buffer.
-- */
-- guint64 offset;
-- guint64 total_size;
-- guint32 length;
-- guint32 flags;
-- guint32 ack_id;
-- guint32 ack_sub_id;
-- guint64 ack_size;
--/* guint8 body[1]; */
--} MsnP2PHeader;
--#define P2P_PACKET_HEADER_SIZE (6 * 4 + 3 * 8)
--
--typedef struct {
-- guint8 header_len;
-- guint8 opcode;
-- guint16 message_len;
-- guint32 base_id;
-- GSList *header_tlv;
-- guint8 data_header_len;
-- guint8 data_tf;
-- guint16 package_number;
-- guint32 session_id;
-- GSList *data_tlv;
--/* guint8 body[1]; */
--} MsnP2Pv2Header;
--
--typedef struct {
-- guint16 protocol_version;
-- guint16 implementation_id;
-- guint16 version;
-- guint16 reserved;
-- guint32 caps;
--} P2PPeerInfo;
--
--typedef enum
--{
-- TF_FIRST = 0x01, /**< The first package. */
-- TF_MSNOBJ = 0x04, /**< Payload contains binary data for MsnObject. */
-- TF_FILE = 0x06 /**< Payload contains binary data. */
--} TF;
--
--typedef enum
--{
-- P2P_HEADER_TLV_TYPE_PEER_INFO = 0x01, /**< Client peer info */
-- P2P_HEADER_TLV_TYPE_ACK = 0x02, /**< ACK */
-- P2P_HEADER_TLV_TYPE_NAK = 0x03 /**< NAK */
--} P2PHeaderTLVType;
--
--typedef enum
--{
-- P2P_DATA_TLV_REMAINING = 0x01, /**< Indicates the remaining data to transfer.*/
--} P2PDataTLVType;
--
--typedef enum
--{
-- P2P_PI_PVER = 0x0200,
-- P2P_PI_IMP_ID = 0,
-- P2P_PI_VER = 0x0e00,
-- P2P_PI_RES = 0,
-- P2P_PI_CAPS = 0x0000010f
--} P2PPeerInfoVal;
--
--typedef struct
--{
-- guint32 value;
--} MsnP2PFooter;
--#define P2P_PACKET_FOOTER_SIZE (1 * 4)
--
--typedef enum
--{
-- MSN_P2P_VERSION_ONE = 0,
-- MSN_P2P_VERSION_TWO = 1,
--} MsnP2PVersion;
--
--typedef struct {
-- MsnP2PVersion version;
-- union {
-- MsnP2PHeader v1;
-- MsnP2Pv2Header v2;
-- } header;
-- MsnP2PFooter footer;
--} MsnP2PInfo;
--
--typedef enum
--{
-- P2P_NO_FLAG = 0x0, /**< No flags specified */
-- P2P_OUT_OF_ORDER = 0x1, /**< Chunk out-of-order */
-- P2P_ACK = 0x2, /**< Acknowledgement */
-- P2P_PENDING_INVITE = 0x4, /**< There is a pending invite */
-- P2P_BINARY_ERROR = 0x8, /**< Error on the binary level */
-- P2P_FILE = 0x10, /**< File */
-- P2P_MSN_OBJ_DATA = 0x20, /**< MsnObject data */
-- P2P_CLOSE = 0x40, /**< Close session */
-- P2P_TLP_ERROR = 0x80, /**< Error at transport layer protocol */
-- P2P_DC_HANDSHAKE = 0x100, /**< Direct Handshake */
-- P2P_WLM2009_COMP = 0x1000000, /**< Compatibility with WLM 2009 */
-- P2P_FILE_DATA = 0x1000030 /**< File transfer data */
--} MsnP2PHeaderFlag;
--/* Info From:
-- * http://msnpiki.msnfanatic.com/index.php/MSNC:P2Pv1_Headers#Flags
-- * http://trac.kmess.org/changeset/ba04d0c825769d23370511031c47f6be75fe9b86
-- * #7180
-- */
--
--typedef enum
--{
-- P2P_APPID_SESSION = 0x0, /**< Negotiating session */
-- P2P_APPID_OBJ = 0x1, /**< MsnObject (Display or Emoticon) */
-- P2P_APPID_FILE = 0x2, /**< File transfer */
-- P2P_APPID_EMOTE = 0xB, /**< CustomEmoticon */
-- P2P_APPID_DISPLAY = 0xC /**< Display Image */
--} MsnP2PAppId;
--
--typedef enum
--{
-- P2P_OPCODE_NONE = 0x00,
-- P2P_OPCODE_SYN = 0x01,
-- P2P_OPCODE_RAK = 0x02
--} MsnP2Pv2OpCode;
--
--MsnP2PInfo *
--msn_p2p_info_new(MsnP2PVersion version);
--
--MsnP2PInfo *
--msn_p2p_info_dup(MsnP2PInfo *info);
--
--void
--msn_p2p_info_free(MsnP2PInfo *info);
--
--size_t
--msn_p2p_header_from_wire(MsnP2PInfo *info, const char *wire, size_t max_len);
--
--char *
--msn_p2p_header_to_wire(MsnP2PInfo *info, size_t *len);
--
--size_t
--msn_p2p_footer_from_wire(MsnP2PInfo *info, const char *wire);
--
--char *
--msn_p2p_footer_to_wire(MsnP2PInfo *info, size_t *len);
--
--void
--msn_p2p_info_to_string(MsnP2PInfo *info, GString *str);
--
--gboolean
--msn_p2p_msg_is_data(const MsnP2PInfo *info);
--
--gboolean
--msn_p2p_info_is_valid(MsnP2PInfo *info);
--
--gboolean
--msn_p2p_info_is_first(MsnP2PInfo *info);
--
--gboolean
--msn_p2p_info_is_final(MsnP2PInfo *info);
--
--void
--msn_p2p_info_create_ack(MsnP2PInfo *old_info, MsnP2PInfo *new_info);
--
--gboolean
--msn_p2p_info_require_ack(MsnP2PInfo *info);
--
--gboolean
--msn_p2p_info_is_ack(MsnP2PInfo *info);
--
--void
--msn_p2p_info_init_first(MsnP2PInfo *new_info, MsnP2PInfo *old_info);
--
--guint32
--msn_p2p_info_get_session_id(MsnP2PInfo *info);
--
--guint32
--msn_p2p_info_get_id(MsnP2PInfo *info);
--
--guint64
--msn_p2p_info_get_offset(MsnP2PInfo *info);
--
--guint64
--msn_p2p_info_get_total_size(MsnP2PInfo *info);
--
--guint32
--msn_p2p_info_get_length(MsnP2PInfo *info);
--
--guint32
--msn_p2p_info_get_flags(MsnP2PInfo *info);
--
--guint32
--msn_p2p_info_get_ack_id(MsnP2PInfo *info);
--
--guint32
--msn_p2p_info_get_ack_sub_id(MsnP2PInfo *info);
--
--guint64
--msn_p2p_info_get_ack_size(MsnP2PInfo *info);
--
--guint32
--msn_p2p_info_get_app_id(MsnP2PInfo *info);
--
--void
--msn_p2p_info_set_session_id(MsnP2PInfo *info, guint32 session_id);
--
--void
--msn_p2p_info_set_id(MsnP2PInfo *info, guint32 id);
--
--void
--msn_p2p_info_set_offset(MsnP2PInfo *info, guint64 offset);
--
--void
--msn_p2p_info_set_total_size(MsnP2PInfo *info, guint64 total_size);
--
--void
--msn_p2p_info_set_length(MsnP2PInfo *info, guint32 length);
--
--void
--msn_p2p_info_set_flags(MsnP2PInfo *info, guint32 flags);
--
--void
--msn_p2p_info_set_ack_id(MsnP2PInfo *info, guint32 ack_id);
--
--void
--msn_p2p_info_set_ack_sub_id(MsnP2PInfo *info, guint32 ack_sub_id);
--
--void
--msn_p2p_info_set_ack_size(MsnP2PInfo *info, guint64 ack_size);
--
--void
--msn_p2p_info_set_app_id(MsnP2PInfo *info, guint32 app_id);
--
--#endif /* MSN_P2P_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/page.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/page.c
---- pidgin-2.10.7/libpurple/protocols/msn/page.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/page.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,85 +0,0 @@
--/**
-- * @file page.c Paging functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#include "msn.h"
--#include "page.h"
--
--MsnPage *
--msn_page_new(void)
--{
-- MsnPage *page;
--
-- page = g_new0(MsnPage, 1);
--
-- return page;
--}
--
--void
--msn_page_destroy(MsnPage *page)
--{
-- g_return_if_fail(page != NULL);
--
-- g_free(page->body);
-- g_free(page->from_location);
-- g_free(page->from_phone);
--
-- g_free(page);
--}
--
--char *
--msn_page_gen_payload(const MsnPage *page, size_t *ret_size)
--{
-- char *str;
-- char *body;
--
-- g_return_val_if_fail(page != NULL, NULL);
--
-- body = g_markup_escape_text(msn_page_get_body(page), -1);
-- str = g_strdup_printf(
-- "<TEXT xml:space=\"preserve\" enc=\"utf-8\">%s</TEXT>",
-- body);
-- g_free(body);
--
-- if (ret_size != NULL)
-- *ret_size = strlen(str);
--
-- return str;
--}
--
--void
--msn_page_set_body(MsnPage *page, const char *body)
--{
-- g_return_if_fail(page != NULL);
-- g_return_if_fail(body != NULL);
--
-- g_free(page->body);
-- page->body = g_strdup(body);
--}
--
--const char *
--msn_page_get_body(const MsnPage *page)
--{
-- g_return_val_if_fail(page != NULL, NULL);
--
-- return page->body;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/page.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/page.h
---- pidgin-2.10.7/libpurple/protocols/msn/page.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/page.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,81 +0,0 @@
--/**
-- * @file page.h Paging functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_PAGE_H
--#define MSN_PAGE_H
--
--typedef struct _MsnPage MsnPage;
--
--#include "session.h"
--
--/**
-- * A page.
-- */
--struct _MsnPage
--{
-- char *from_location;
-- char *from_phone;
--
-- char *body;
--};
--
--/**
-- * Creates a new, empty page.
-- *
-- * @return A new page.
-- */
--MsnPage *msn_page_new(void);
--
--/**
-- * Destroys a page.
-- */
--void msn_page_destroy(MsnPage *page);
--
--/**
-- * Generates the payload data of a page.
-- *
-- * @param page The page.
-- * @param ret_size The returned size of the payload.
-- *
-- * @return The payload data of a page.
-- */
--char *msn_page_gen_payload(const MsnPage *page, size_t *ret_size);
--
--/**
-- * Sets the body of a page.
-- *
-- * @param page The page.
-- * @param body The body of the page.
-- */
--void msn_page_set_body(MsnPage *page, const char *body);
--
--/**
-- * Returns the body of the page.
-- *
-- * @param page The page.
-- *
-- * @return The body of the page.
-- */
--const char *msn_page_get_body(const MsnPage *page);
--
--#endif /* MSN_PAGE_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/sbconn.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/sbconn.c
---- pidgin-2.10.7/libpurple/protocols/msn/sbconn.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/sbconn.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,174 +0,0 @@
--/**
-- * @file sbconn.c MSN Switchboard Connection
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "msg.h"
--#include "sbconn.h"
--
--void msn_sbconn_send_part(MsnSlpLink *slplink, MsnSlpMessagePart *part)
--{
-- MsnMessage *msg;
-- const char *passport;
-- char *data;
-- size_t size;
--
-- msg = msn_message_new_msnslp();
--
-- passport = purple_normalize(slplink->session->account, slplink->remote_user);
-- msn_message_set_header(msg, "P2P-Dest", passport);
--
-- msg->part = msn_slpmsgpart_ref(part);
-- data = msn_slpmsgpart_serialize(part, &size);
-- msn_message_set_bin_data(msg, data, size);
-- g_free(data);
--
-- if (slplink->swboard == NULL)
-- {
-- slplink->swboard = msn_session_get_swboard(slplink->session,
-- slplink->remote_user, MSN_SB_FLAG_FT);
--
-- g_return_if_fail(slplink->swboard != NULL);
--
-- /* If swboard is destroyed we will be too */
-- slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink);
-- }
--
-- msn_switchboard_send_msg(slplink->swboard, msg, TRUE);
-- msn_message_unref(msg);
--}
--
--/** Called when a message times out. */
--static void
--msg_timeout(MsnCmdProc *cmdproc, MsnTransaction *trans)
--{
-- MsnMessage *msg;
--
-- msg = trans->data;
--
-- msg_error_helper(cmdproc, msg, MSN_MSG_ERROR_TIMEOUT);
--}
--
--static void
--release_msg(MsnSwitchBoard *swboard, MsnMessage *msg)
--{
-- MsnCmdProc *cmdproc;
-- MsnTransaction *trans;
-- char *payload;
-- gsize payload_len;
-- char flag;
--
-- g_return_if_fail(swboard != NULL);
-- g_return_if_fail(msg != NULL);
--
-- cmdproc = swboard->cmdproc;
--
-- payload = msn_message_gen_payload(msg, &payload_len);
--
-- if (purple_debug_is_verbose()) {
-- purple_debug_info("msn", "SB length:{%" G_GSIZE_FORMAT "}\n", payload_len);
-- msn_message_show_readable(msg, "SB SEND", FALSE);
-- }
--
-- flag = msn_message_get_flag(msg);
-- trans = msn_transaction_new(cmdproc, "MSG", "%c %" G_GSIZE_FORMAT,
-- flag, payload_len);
--
-- /* Data for callbacks */
-- msn_transaction_set_data(trans, msg);
--
-- if (flag != 'U') {
-- if (msg->type == MSN_MSG_TEXT)
-- {
-- msg->ack_ref = TRUE;
-- msn_message_ref(msg);
-- swboard->ack_list = g_list_append(swboard->ack_list, msg);
-- msn_transaction_set_timeout_cb(trans, msg_timeout);
-- }
-- else if (msg->type == MSN_MSG_SLP)
-- {
-- msg->ack_ref = TRUE;
-- msn_message_ref(msg);
-- swboard->ack_list = g_list_append(swboard->ack_list, msg);
-- msn_transaction_set_timeout_cb(trans, msg_timeout);
--#if 0
-- if (msg->ack_cb != NULL)
-- {
-- msn_transaction_add_cb(trans, "ACK", msg_ack);
-- msn_transaction_add_cb(trans, "NAK", msg_nak);
-- }
--#endif
-- }
-- }
--
-- trans->payload = payload;
-- trans->payload_len = payload_len;
--
-- msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--static void
--queue_msg(MsnSwitchBoard *swboard, MsnMessage *msg)
--{
-- g_return_if_fail(swboard != NULL);
-- g_return_if_fail(msg != NULL);
--
-- purple_debug_info("msn", "Appending message to queue.\n");
--
-- g_queue_push_tail(swboard->msg_queue, msg);
--
-- msn_message_ref(msg);
--}
--
--void
--msn_sbconn_process_queue(MsnSwitchBoard *swboard)
--{
-- MsnMessage *msg;
--
-- g_return_if_fail(swboard != NULL);
--
-- purple_debug_info("msn", "Processing queue\n");
--
-- while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL)
-- {
-- purple_debug_info("msn", "Sending message\n");
-- release_msg(swboard, msg);
-- msn_message_unref(msg);
-- }
--}
--
--void
--msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg,
-- gboolean queue)
--{
-- g_return_if_fail(swboard != NULL);
-- g_return_if_fail(msg != NULL);
--
-- purple_debug_info("msn", "switchboard send msg..\n");
-- if (msn_switchboard_can_send(swboard))
-- release_msg(swboard, msg);
-- else if (queue)
-- queue_msg(swboard, msg);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/sbconn.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/sbconn.h
---- pidgin-2.10.7/libpurple/protocols/msn/sbconn.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/sbconn.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,41 +0,0 @@
--/**
-- * @file sbconn.h MSN Switchboard Connection
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef MSN_SBCONN_H
--#define MSN_SBCONN_H
--
--#include "msg.h"
--#include "slplink.h"
--
--#define MSN_SBCONN_MAX_SIZE 1202
--
--void msn_sbconn_send_part(MsnSlpLink *slplink, MsnSlpMessagePart *part);
--
--void msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg,
-- gboolean queue);
--
--void
--msn_sbconn_process_queue(MsnSwitchBoard *swboard);
--
--#endif /* MSN_SBCONN_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/servconn.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/servconn.c
---- pidgin-2.10.7/libpurple/protocols/msn/servconn.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/servconn.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,607 +0,0 @@
--/**
-- * @file servconn.c Server connection functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#include "internal.h"
--#include "debug.h"
--
--#include "servconn.h"
--#include "error.h"
--
--static void read_cb(gpointer data, gint source, PurpleInputCondition cond);
--static void servconn_timeout_renew(MsnServConn *servconn);
--
--/**************************************************************************
-- * Main
-- **************************************************************************/
--
--MsnServConn *
--msn_servconn_new(MsnSession *session, MsnServConnType type)
--{
-- MsnServConn *servconn;
--
-- g_return_val_if_fail(session != NULL, NULL);
--
-- servconn = g_new0(MsnServConn, 1);
--
-- servconn->type = type;
--
-- servconn->session = session;
-- servconn->cmdproc = msn_cmdproc_new(session);
-- servconn->cmdproc->servconn = servconn;
--
-- servconn->httpconn = msn_httpconn_new(servconn);
--
-- servconn->num = session->servconns_count++;
--
-- servconn->tx_buf = purple_circ_buffer_new(MSN_BUF_LEN);
-- servconn->tx_handler = 0;
-- servconn->timeout_sec = 0;
-- servconn->timeout_handle = 0;
--
-- servconn->fd = -1;
--
-- return servconn;
--}
--
--void
--msn_servconn_destroy(MsnServConn *servconn)
--{
-- g_return_if_fail(servconn != NULL);
--
-- if (servconn->processing)
-- {
-- servconn->wasted = TRUE;
-- return;
-- }
--
-- msn_servconn_disconnect(servconn);
--
-- if (servconn->destroy_cb)
-- servconn->destroy_cb(servconn);
--
-- if (servconn->httpconn != NULL)
-- msn_httpconn_destroy(servconn->httpconn);
--
-- g_free(servconn->host);
--
-- purple_circ_buffer_destroy(servconn->tx_buf);
-- if (servconn->tx_handler > 0)
-- purple_input_remove(servconn->tx_handler);
-- if (servconn->timeout_handle > 0)
-- purple_timeout_remove(servconn->timeout_handle);
--
-- msn_cmdproc_destroy(servconn->cmdproc);
-- g_free(servconn);
--}
--
--void
--msn_servconn_set_connect_cb(MsnServConn *servconn,
-- void (*connect_cb)(MsnServConn *))
--{
-- g_return_if_fail(servconn != NULL);
-- servconn->connect_cb = connect_cb;
--}
--
--void
--msn_servconn_set_disconnect_cb(MsnServConn *servconn,
-- void (*disconnect_cb)(MsnServConn *))
--{
-- g_return_if_fail(servconn != NULL);
--
-- servconn->disconnect_cb = disconnect_cb;
--}
--
--void
--msn_servconn_set_destroy_cb(MsnServConn *servconn,
-- void (*destroy_cb)(MsnServConn *))
--{
-- g_return_if_fail(servconn != NULL);
--
-- servconn->destroy_cb = destroy_cb;
--}
--
--/**************************************************************************
-- * Utility
-- **************************************************************************/
--
--void
--msn_servconn_got_error(MsnServConn *servconn, MsnServConnError error,
-- const char *reason)
--{
-- MsnSession *session = servconn->session;
-- MsnServConnType type = servconn->type;
--
-- const char *names[] = { "Notification", "Switchboard" };
-- const char *name;
--
-- name = names[type];
--
-- if (reason == NULL) {
-- switch (error)
-- {
-- case MSN_SERVCONN_ERROR_CONNECT:
-- reason = _("Unable to connect"); break;
-- case MSN_SERVCONN_ERROR_WRITE:
-- reason = _("Writing error"); break;
-- case MSN_SERVCONN_ERROR_READ:
-- reason = _("Reading error"); break;
-- default:
-- reason = _("Unknown error"); break;
-- }
-- }
--
-- purple_debug_error("msn", "Connection error from %s server (%s): %s\n",
-- name, servconn->host, reason);
--
-- if (type == MSN_SERVCONN_SB)
-- {
-- MsnSwitchBoard *swboard;
-- swboard = servconn->cmdproc->data;
-- if (swboard != NULL)
-- swboard->error = MSN_SB_ERROR_CONNECTION;
-- }
--
-- /* servconn->disconnect_cb may destroy servconn, so don't use it again */
-- msn_servconn_disconnect(servconn);
--
-- if (type == MSN_SERVCONN_NS)
-- {
-- char *tmp = g_strdup_printf(_("Connection error from %s server:\n%s"),
-- name, reason);
-- msn_session_set_error(session, MSN_ERROR_SERVCONN, tmp);
-- g_free(tmp);
-- }
--}
--
--/**************************************************************************
-- * Connect
-- **************************************************************************/
--
--static void
--connect_cb(gpointer data, gint source, const char *error_message)
--{
-- MsnServConn *servconn;
--
-- servconn = data;
-- servconn->connect_data = NULL;
--
-- servconn->fd = source;
--
-- if (source >= 0)
-- {
-- servconn->connected = TRUE;
--
-- /* Someone wants to know we connected. */
-- servconn->connect_cb(servconn);
-- servconn->inpa = purple_input_add(servconn->fd, PURPLE_INPUT_READ,
-- read_cb, data);
-- servconn_timeout_renew(servconn);
-- }
-- else
-- {
-- purple_debug_error("msn", "Connection error: %s\n", error_message);
-- msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_CONNECT, error_message);
-- }
--}
--
--gboolean
--msn_servconn_connect(MsnServConn *servconn, const char *host, int port, gboolean force)
--{
-- MsnSession *session;
--
-- g_return_val_if_fail(servconn != NULL, FALSE);
-- g_return_val_if_fail(host != NULL, FALSE);
-- g_return_val_if_fail(port > 0, FALSE);
--
-- session = servconn->session;
--
-- if (servconn->connected)
-- msn_servconn_disconnect(servconn);
--
-- g_free(servconn->host);
-- servconn->host = g_strdup(host);
--
-- if (session->http_method)
-- {
-- /* HTTP Connection. */
--
-- if (!servconn->httpconn->connected || force)
-- if (!msn_httpconn_connect(servconn->httpconn, host, port))
-- return FALSE;
--
-- servconn->connected = TRUE;
-- servconn->httpconn->virgin = TRUE;
-- servconn_timeout_renew(servconn);
--
-- /* Someone wants to know we connected. */
-- servconn->connect_cb(servconn);
--
-- return TRUE;
-- }
--
-- servconn->connect_data = purple_proxy_connect(NULL, session->account,
-- host, port, connect_cb, servconn);
--
-- return (servconn->connect_data != NULL);
--}
--
--void
--msn_servconn_disconnect(MsnServConn *servconn)
--{
-- g_return_if_fail(servconn != NULL);
--
-- if (servconn->connect_data != NULL)
-- {
-- purple_proxy_connect_cancel(servconn->connect_data);
-- servconn->connect_data = NULL;
-- }
--
-- if (!servconn->connected)
-- {
-- /* We could not connect. */
-- if (servconn->disconnect_cb != NULL)
-- servconn->disconnect_cb(servconn);
--
-- return;
-- }
--
-- if (servconn->session->http_method)
-- {
-- /* Fake disconnection. */
-- if (servconn->disconnect_cb != NULL)
-- servconn->disconnect_cb(servconn);
--
-- return;
-- }
--
-- if (servconn->inpa > 0)
-- {
-- purple_input_remove(servconn->inpa);
-- servconn->inpa = 0;
-- }
--
-- if (servconn->timeout_handle > 0)
-- {
-- purple_timeout_remove(servconn->timeout_handle);
-- servconn->timeout_handle = 0;
-- }
--
-- close(servconn->fd);
--
-- servconn->rx_buf = NULL;
-- servconn->rx_len = 0;
-- servconn->payload_len = 0;
--
-- servconn->connected = FALSE;
--
-- if (servconn->disconnect_cb != NULL)
-- servconn->disconnect_cb(servconn);
--}
--
--static gboolean
--servconn_idle_timeout_cb(MsnServConn *servconn)
--{
-- servconn->timeout_handle = 0;
-- msn_servconn_disconnect(servconn);
-- return FALSE;
--}
--
--static void
--servconn_timeout_renew(MsnServConn *servconn)
--{
-- if (servconn->timeout_handle) {
-- purple_timeout_remove(servconn->timeout_handle);
-- servconn->timeout_handle = 0;
-- }
--
-- if (servconn->connected && servconn->timeout_sec) {
-- servconn->timeout_handle = purple_timeout_add_seconds(
-- servconn->timeout_sec, (GSourceFunc)servconn_idle_timeout_cb, servconn);
-- }
--}
--
--void
--msn_servconn_set_idle_timeout(MsnServConn *servconn, guint seconds)
--{
-- servconn->timeout_sec = seconds;
-- if (servconn->connected)
-- servconn_timeout_renew(servconn);
--}
--
--static void
--servconn_write_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- MsnServConn *servconn = data;
-- gssize ret;
-- int writelen;
--
-- writelen = purple_circ_buffer_get_max_read(servconn->tx_buf);
--
-- if (writelen == 0) {
-- purple_input_remove(servconn->tx_handler);
-- servconn->tx_handler = 0;
-- return;
-- }
--
-- ret = write(servconn->fd, servconn->tx_buf->outptr, writelen);
--
-- if (ret < 0 && errno == EAGAIN)
-- return;
-- else if (ret <= 0) {
-- msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_WRITE, NULL);
-- return;
-- }
--
-- purple_circ_buffer_mark_read(servconn->tx_buf, ret);
-- servconn_timeout_renew(servconn);
--}
--
--gssize
--msn_servconn_write(MsnServConn *servconn, const char *buf, size_t len)
--{
-- gssize ret = 0;
--
-- g_return_val_if_fail(servconn != NULL, 0);
--
-- if (!servconn->session->http_method)
-- {
-- if (servconn->tx_handler == 0) {
-- switch (servconn->type)
-- {
-- case MSN_SERVCONN_NS:
-- case MSN_SERVCONN_SB:
-- ret = write(servconn->fd, buf, len);
-- break;
--#if 0
-- case MSN_SERVCONN_DC:
-- ret = write(servconn->fd, &buf, sizeof(len));
-- ret = write(servconn->fd, buf, len);
-- break;
--#endif
-- default:
-- ret = write(servconn->fd, buf, len);
-- break;
-- }
-- } else {
-- ret = -1;
-- errno = EAGAIN;
-- }
--
-- if (ret < 0 && errno == EAGAIN)
-- ret = 0;
-- if (ret >= 0 && ret < len) {
-- if (servconn->tx_handler == 0)
-- servconn->tx_handler = purple_input_add(
-- servconn->fd, PURPLE_INPUT_WRITE,
-- servconn_write_cb, servconn);
-- purple_circ_buffer_append(servconn->tx_buf, buf + ret,
-- len - ret);
-- }
-- }
-- else
-- {
-- ret = msn_httpconn_write(servconn->httpconn, buf, len);
-- }
--
-- if (ret == -1)
-- {
-- msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_WRITE, NULL);
-- }
--
-- servconn_timeout_renew(servconn);
-- return ret;
--}
--
--static void
--read_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- MsnServConn *servconn;
-- char buf[MSN_BUF_LEN];
-- gssize len;
--
-- servconn = data;
--
-- if (servconn->type == MSN_SERVCONN_NS)
-- servconn->session->account->gc->last_received = time(NULL);
--
-- len = read(servconn->fd, buf, sizeof(buf) - 1);
-- if (len < 0 && errno == EAGAIN)
-- return;
-- if (len <= 0) {
-- purple_debug_error("msn", "servconn %03d read error, "
-- "len: %" G_GSSIZE_FORMAT ", errno: %d, error: %s\n",
-- servconn->num, len, errno, g_strerror(errno));
-- msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ, NULL);
--
-- return;
-- }
--
-- buf[len] = '\0';
--
-- servconn->rx_buf = g_realloc(servconn->rx_buf, len + servconn->rx_len + 1);
-- memcpy(servconn->rx_buf + servconn->rx_len, buf, len + 1);
-- servconn->rx_len += len;
--
-- servconn = msn_servconn_process_data(servconn);
-- if (servconn)
-- servconn_timeout_renew(servconn);
--}
--
--MsnServConn *msn_servconn_process_data(MsnServConn *servconn)
--{
-- char *cur, *end, *old_rx_buf;
-- int cur_len;
--
-- end = old_rx_buf = servconn->rx_buf;
--
-- servconn->processing = TRUE;
--
-- do
-- {
-- cur = end;
--
-- if (servconn->payload_len)
-- {
-- if (servconn->payload_len > servconn->rx_len)
-- /* The payload is still not complete. */
-- break;
--
-- cur_len = servconn->payload_len;
-- end += cur_len;
-- }
-- else
-- {
-- end = strstr(cur, "\r\n");
--
-- if (end == NULL)
-- /* The command is still not complete. */
-- break;
--
-- *end = '\0';
-- end += 2;
-- cur_len = end - cur;
-- }
--
-- servconn->rx_len -= cur_len;
--
-- if (servconn->payload_len)
-- {
-- msn_cmdproc_process_payload(servconn->cmdproc, cur, cur_len);
-- servconn->payload_len = 0;
-- }
-- else
-- {
-- msn_cmdproc_process_cmd_text(servconn->cmdproc, cur);
-- servconn->payload_len = servconn->cmdproc->last_cmd->payload_len;
-- }
-- } while (servconn->connected && !servconn->wasted && servconn->rx_len > 0);
--
-- if (servconn->connected && !servconn->wasted)
-- {
-- if (servconn->rx_len > 0)
-- servconn->rx_buf = g_memdup(cur, servconn->rx_len);
-- else
-- servconn->rx_buf = NULL;
-- }
--
-- servconn->processing = FALSE;
--
-- if (servconn->wasted) {
-- msn_servconn_destroy(servconn);
-- servconn = NULL;
-- }
--
-- g_free(old_rx_buf);
-- return servconn;
--}
--
--#if 0
--static int
--create_listener(int port)
--{
-- int fd;
-- int flags;
-- const int on = 1;
--
--#if 0
-- struct addrinfo hints;
-- struct addrinfo *c, *res;
-- char port_str[5];
--
-- snprintf(port_str, sizeof(port_str), "%d", port);
--
-- memset(&hints, 0, sizeof(hints));
--
-- hints.ai_flags = AI_PASSIVE;
-- hints.ai_family = AF_UNSPEC;
-- hints.ai_socktype = SOCK_STREAM;
--
-- if (getaddrinfo(NULL, port_str, &hints, &res) != 0)
-- {
-- purple_debug_error("msn", "Could not get address info: %s.\n",
-- port_str);
-- return -1;
-- }
--
-- for (c = res; c != NULL; c = c->ai_next)
-- {
-- fd = socket(c->ai_family, c->ai_socktype, c->ai_protocol);
--
-- if (fd < 0)
-- continue;
--
-- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
--
-- if (bind(fd, c->ai_addr, c->ai_addrlen) == 0)
-- break;
--
-- close(fd);
-- }
--
-- if (c == NULL)
-- {
-- purple_debug_error("msn", "Could not find socket: %s.\n", port_str);
-- return -1;
-- }
--
-- freeaddrinfo(res);
--#else
-- struct sockaddr_in sockin;
--
-- fd = socket(AF_INET, SOCK_STREAM, 0);
--
-- if (fd < 0)
-- return -1;
--
-- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) != 0)
-- {
-- close(fd);
-- return -1;
-- }
--
-- memset(&sockin, 0, sizeof(struct sockaddr_in));
-- sockin.sin_family = AF_INET;
-- sockin.sin_port = htons(port);
--
-- if (bind(fd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0)
-- {
-- close(fd);
-- return -1;
-- }
--#endif
--
-- if (listen (fd, 4) != 0)
-- {
-- close (fd);
-- return -1;
-- }
--
-- flags = fcntl(fd, F_GETFL);
-- fcntl(fd, F_SETFL, flags | O_NONBLOCK);
--#ifndef _WIN32
-- fcntl(fd, F_SETFD, FD_CLOEXEC);
--#endif
--
-- return fd;
--}
--#endif
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/servconn.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/servconn.h
---- pidgin-2.10.7/libpurple/protocols/msn/servconn.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/servconn.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,193 +0,0 @@
--/**
-- * @file servconn.h Server connection functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_SERVCONN_H
--#define MSN_SERVCONN_H
--
--typedef struct _MsnServConn MsnServConn;
--
--/**
-- * Connection error types.
-- */
--typedef enum
--{
-- MSN_SERVCONN_ERROR_NONE,
-- MSN_SERVCONN_ERROR_CONNECT,
-- MSN_SERVCONN_ERROR_WRITE,
-- MSN_SERVCONN_ERROR_READ
--} MsnServConnError;
--
--/**
-- * Connection types.
-- */
--typedef enum
--{
-- MSN_SERVCONN_NS,
-- MSN_SERVCONN_SB
--} MsnServConnType;
--
--#include "internal.h"
--#include "proxy.h"
--
--#include "cmdproc.h"
--#include "httpconn.h"
--#include "session.h"
--
--/**
-- * A Connection.
-- */
--struct _MsnServConn
--{
-- MsnServConnType type; /**< The type of this connection. */
-- MsnSession *session; /**< The MSN session of this connection. */
-- MsnCmdProc *cmdproc; /**< The command processor of this connection. */
--
-- PurpleProxyConnectData *connect_data;
--
-- gboolean connected; /**< A flag that states if it's connected. */
-- gboolean processing; /**< A flag that states if something is working
-- with this connection. */
-- gboolean wasted; /**< A flag that states if it should be destroyed. */
--
-- char *host; /**< The host this connection is connected or should be
-- connected to. */
-- int num; /**< A number id of this connection. */
--
-- MsnHttpConn *httpconn; /**< The HTTP connection this connection should use. */
--
-- int fd; /**< The connection's file descriptor. */
-- int inpa; /**< The connection's input handler. */
--
-- char *rx_buf; /**< The receive buffer. */
-- int rx_len; /**< The receive buffer lenght. */
--
-- size_t payload_len; /**< The length of the payload.
-- It's only set when we've received a command that
-- has a payload. */
--
-- PurpleCircBuffer *tx_buf;
-- guint tx_handler;
-- guint timeout_sec;
-- guint timeout_handle;
--
-- void (*connect_cb)(MsnServConn *); /**< The callback to call when connecting. */
-- void (*disconnect_cb)(MsnServConn *); /**< The callback to call when disconnecting. */
-- void (*destroy_cb)(MsnServConn *); /**< The callback to call when destroying. */
--};
--
--/**
-- * Creates a new connection object.
-- *
-- * @param session The session.
-- * @param type The type of the connection.
-- */
--MsnServConn *msn_servconn_new(MsnSession *session, MsnServConnType type);
--
--/**
-- * Destroys a connection object.
-- *
-- * @param servconn The connection.
-- */
--void msn_servconn_destroy(MsnServConn *servconn);
--
--/**
-- * Connects to a host.
-- *
-- * @param servconn The connection.
-- * @param host The host.
-- * @param port The port.
-- * @param force Force this servconn to connect to a new server.
-- */
--gboolean msn_servconn_connect(MsnServConn *servconn, const char *host, int port,
-- gboolean force);
--
--/**
-- * Disconnects.
-- *
-- * @param servconn The connection.
-- */
--void msn_servconn_disconnect(MsnServConn *servconn);
--
--/**
-- * Sets the connect callback.
-- *
-- * @param servconn The servconn.
-- * @param connect_cb The connect callback.
-- */
--void msn_servconn_set_connect_cb(MsnServConn *servconn,
-- void (*connect_cb)(MsnServConn *));
--/**
-- * Sets the disconnect callback.
-- *
-- * @param servconn The servconn.
-- * @param disconnect_cb The disconnect callback.
-- */
--void msn_servconn_set_disconnect_cb(MsnServConn *servconn,
-- void (*disconnect_cb)(MsnServConn *));
--/**
-- * Sets the destroy callback.
-- *
-- * @param servconn The servconn that's being destroyed.
-- * @param destroy_cb The destroy callback.
-- */
--void msn_servconn_set_destroy_cb(MsnServConn *servconn,
-- void (*destroy_cb)(MsnServConn *));
--
--/**
-- * Writes a chunck of data to the servconn.
-- *
-- * @param servconn The servconn.
-- * @param buf The data to write.
-- * @param size The size of the data.
-- */
--gssize msn_servconn_write(MsnServConn *servconn, const char *buf,
-- size_t size);
--
--/**
-- * Function to call whenever an error related to a switchboard occurs.
-- *
-- * @param servconn The servconn.
-- * @param error The error that happened.
-- */
--void msn_servconn_got_error(MsnServConn *servconn, MsnServConnError error,
-- const char *reason);
--
--/**
-- * Process the data in servconn->rx_buf. This is called after reading
-- * data from the socket.
-- *
-- * @param servconn The servconn.
-- *
-- * @return @c NULL if servconn was destroyed, 'servconn' otherwise.
-- */
--MsnServConn *msn_servconn_process_data(MsnServConn *servconn);
--
--/**
-- * Set a idle timeout fot this servconn
-- *
-- * @param servconn The servconn
-- * @param seconds The idle timeout in seconds
-- */
--void msn_servconn_set_idle_timeout(MsnServConn *servconn, guint seconds);
--
--#endif /* MSN_SERVCONN_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/session.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/session.c
---- pidgin-2.10.7/libpurple/protocols/msn/session.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/session.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,500 +0,0 @@
--/**
-- * @file session.c MSN session functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "error.h"
--#include "msnutils.h"
--#include "session.h"
--#include "notification.h"
--#include "oim.h"
--
--MsnSession *
--msn_session_new(PurpleAccount *account)
--{
-- MsnSession *session;
--
-- g_return_val_if_fail(account != NULL, NULL);
--
-- session = g_new0(MsnSession, 1);
--
-- session->account = account;
-- session->notification = msn_notification_new(session);
-- session->userlist = msn_userlist_new(session);
--
-- session->user = msn_user_new(session->userlist,
-- purple_account_get_username(account), NULL);
-- msn_userlist_add_user(session->userlist, session->user);
-- session->oim = msn_oim_new(session);
--
-- session->protocol_ver = 0;
-- session->enable_mpop = TRUE; /* Default only */
--
-- session->guid = rand_guid();
--
-- return session;
--}
--
--void
--msn_session_destroy(MsnSession *session)
--{
-- g_return_if_fail(session != NULL);
--
-- session->destroying = TRUE;
--
-- while (session->url_datas) {
-- purple_util_fetch_url_cancel(session->url_datas->data);
-- session->url_datas = g_slist_delete_link(session->url_datas, session->url_datas);
-- }
--
-- if (session->connected)
-- msn_session_disconnect(session);
--
-- if (session->soap_cleanup_handle)
-- purple_timeout_remove(session->soap_cleanup_handle);
--
-- if (session->soap_table != NULL)
-- g_hash_table_destroy(session->soap_table);
--
-- while (session->slplinks != NULL)
-- msn_slplink_unref(session->slplinks->data);
--
-- while (session->switches != NULL)
-- msn_switchboard_destroy(session->switches->data);
--
-- if (session->oim != NULL)
-- msn_oim_destroy(session->oim);
--
-- if (session->nexus != NULL)
-- msn_nexus_destroy(session->nexus);
--
-- if (session->user != NULL)
-- msn_user_unref(session->user);
--
-- if (session->notification != NULL)
-- msn_notification_destroy(session->notification);
--
-- msn_userlist_destroy(session->userlist);
--
-- g_free(session->psm);
-- g_free(session->guid);
-- g_free(session->abch_cachekey);
--#if 0
-- g_free(session->blocked_text);
--#endif
--
-- g_free(session->passport_info.sid);
-- g_free(session->passport_info.mspauth);
-- g_free(session->passport_info.client_ip);
-- g_free(session->passport_info.mail_url);
--
-- g_free(session);
--}
--
--gboolean
--msn_session_connect(MsnSession *session, const char *host, int port,
-- gboolean http_method)
--{
-- g_return_val_if_fail(session != NULL, FALSE);
-- g_return_val_if_fail(!session->connected, TRUE);
--
-- session->connected = TRUE;
-- session->http_method = http_method;
--
-- if (session->notification == NULL)
-- {
-- purple_debug_error("msn", "This shouldn't happen\n");
-- g_return_val_if_reached(FALSE);
-- }
--
-- return msn_notification_connect(session->notification, host, port);
--}
--
--void
--msn_session_disconnect(MsnSession *session)
--{
-- g_return_if_fail(session != NULL);
--
-- if (!session->connected)
-- return;
--
-- if (session->login_timeout) {
-- purple_timeout_remove(session->login_timeout);
-- session->login_timeout = 0;
-- }
--
-- session->connected = FALSE;
--
-- while (session->switches != NULL)
-- msn_switchboard_close(session->switches->data);
--
-- if (session->notification != NULL)
-- msn_notification_close(session->notification);
--}
--
--/* TODO: This must go away when conversation is redesigned */
--MsnSwitchBoard *
--msn_session_find_swboard(MsnSession *session, const char *username)
--{
-- GList *l;
--
-- g_return_val_if_fail(session != NULL, NULL);
-- g_return_val_if_fail(username != NULL, NULL);
--
-- for (l = session->switches; l != NULL; l = l->next)
-- {
-- MsnSwitchBoard *swboard;
--
-- swboard = l->data;
--
-- if ((swboard->im_user != NULL) && !strcmp(username, swboard->im_user))
-- return swboard;
-- }
--
-- return NULL;
--}
--
--static PurpleConversation *
--msn_session_get_conv(MsnSession *session,const char *passport)
--{
-- PurpleAccount *account;
-- PurpleConversation * conv;
--
-- g_return_val_if_fail(session != NULL, NULL);
-- account = session->account;
--
-- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-- passport, account);
-- if(conv == NULL){
-- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, passport);
-- }
-- return conv;
--}
--
--/* put Message to User Conversation
-- *
-- * passport - the one want to talk to you
-- */
--void
--msn_session_report_user(MsnSession *session,const char *passport,const char *msg,PurpleMessageFlags flags)
--{
-- PurpleConversation * conv;
--
-- if ((conv = msn_session_get_conv(session,passport)) != NULL){
-- purple_conversation_write(conv, NULL, msg, flags, time(NULL));
-- }
--}
--
--MsnSwitchBoard *
--msn_session_find_swboard_with_conv(MsnSession *session, PurpleConversation *conv)
--{
-- GList *l;
--
-- g_return_val_if_fail(session != NULL, NULL);
-- g_return_val_if_fail(conv != NULL, NULL);
--
-- for (l = session->switches; l != NULL; l = l->next)
-- {
-- MsnSwitchBoard *swboard;
--
-- swboard = l->data;
--
-- if (swboard->conv == conv)
-- return swboard;
-- }
--
-- return NULL;
--}
--
--MsnSwitchBoard *
--msn_session_find_swboard_with_id(const MsnSession *session, int chat_id)
--{
-- GList *l;
--
-- g_return_val_if_fail(session != NULL, NULL);
-- g_return_val_if_fail(chat_id >= 0, NULL);
--
-- for (l = session->switches; l != NULL; l = l->next)
-- {
-- MsnSwitchBoard *swboard;
--
-- swboard = l->data;
--
-- if (swboard->chat_id == chat_id)
-- return swboard;
-- }
--
-- return NULL;
--}
--
--MsnSwitchBoard *
--msn_session_get_swboard(MsnSession *session, const char *username,
-- MsnSBFlag flag)
--{
-- MsnSwitchBoard *swboard;
--
-- g_return_val_if_fail(session != NULL, NULL);
--
-- swboard = msn_session_find_swboard(session, username);
--
-- if (swboard == NULL)
-- {
-- swboard = msn_switchboard_new(session);
-- swboard->im_user = g_strdup(username);
-- if (msn_switchboard_request(swboard))
-- msn_switchboard_request_add_user(swboard, username);
-- else
-- return NULL;
-- }
--
-- swboard->flag |= flag;
--
-- return swboard;
--}
--
--static gboolean
--msn_login_timeout_cb(gpointer data)
--{
-- MsnSession *session = data;
-- /* This forces the login process to finish, even though we haven't heard
-- a response for our FQY requests yet. We'll at least end up online to the
-- people we've already added. The rest will follow later. */
-- msn_session_finish_login(session);
-- session->login_timeout = 0;
-- return FALSE;
--}
--
--void
--msn_session_activate_login_timeout(MsnSession *session)
--{
-- if (!session->logged_in && session->connected) {
-- if (session->login_timeout)
-- purple_timeout_remove(session->login_timeout);
-- session->login_timeout =
-- purple_timeout_add_seconds(MSN_LOGIN_FQY_TIMEOUT,
-- msn_login_timeout_cb, session);
-- }
--}
--
--static void
--msn_session_sync_users(MsnSession *session)
--{
-- PurpleConnection *gc = purple_account_get_connection(session->account);
-- GList *to_remove = NULL;
-- GSList *buddies;
--
-- g_return_if_fail(gc != NULL);
--
-- /* The core used to use msn_add_buddy to add all buddies before
-- * being logged in. This no longer happens, so we manually iterate
-- * over the whole buddy list to identify sync issues.
-- */
-- for (buddies = purple_find_buddies(session->account, NULL); buddies;
-- buddies = g_slist_delete_link(buddies, buddies)) {
-- PurpleBuddy *buddy = buddies->data;
-- const gchar *buddy_name = purple_buddy_get_name(buddy);
-- const gchar *group_name = purple_group_get_name(purple_buddy_get_group(buddy));
-- MsnUser *remote_user;
-- gboolean found = FALSE;
--
-- remote_user = msn_userlist_find_user(session->userlist, buddy_name);
-- if (remote_user && remote_user->list_op & MSN_LIST_FL_OP) {
-- GList *l;
-- for (l = remote_user->group_ids; l; l = l->next) {
-- const char *name = msn_userlist_find_group_name(remote_user->userlist, l->data);
-- if (name && !g_ascii_strcasecmp(group_name, name)) {
-- found = TRUE;
-- break;
-- }
-- }
--
-- /* We don't care if they're in a different group, as long as they're on the
-- * list somewhere. If we check for the group, we cause pain, agony and
-- * suffering for people who decide to re-arrange their buddy list elsewhere.
-- */
-- if (!found) {
-- if ((remote_user == NULL) || !(remote_user->list_op & MSN_LIST_FL_OP)) {
-- /* The user is not on the server list */
-- msn_error_sync_issue(session, buddy_name, group_name);
-- } else {
-- /* The user is not in that group on the server list */
-- to_remove = g_list_prepend(to_remove, buddy);
-- }
-- }
-- }
-- }
--
-- if (to_remove != NULL) {
-- g_list_foreach(to_remove, (GFunc)purple_blist_remove_buddy, NULL);
-- g_list_free(to_remove);
-- }
--}
--
--void
--msn_session_set_error(MsnSession *session, MsnErrorType error,
-- const char *info)
--{
-- PurpleConnection *gc;
-- PurpleConnectionError reason;
-- char *msg;
--
-- if (session->destroying)
-- return;
--
-- gc = purple_account_get_connection(session->account);
--
-- switch (error)
-- {
-- case MSN_ERROR_SERVCONN:
-- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-- msg = g_strdup(info);
-- break;
-- case MSN_ERROR_UNSUPPORTED_PROTOCOL:
-- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-- msg = g_strdup(_("Our protocol is not supported by the "
-- "server"));
-- break;
-- case MSN_ERROR_HTTP_MALFORMED:
-- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-- msg = g_strdup(_("Error parsing HTTP"));
-- break;
-- case MSN_ERROR_SIGN_OTHER:
-- reason = PURPLE_CONNECTION_ERROR_NAME_IN_USE;
-- msg = g_strdup(_("You have signed on from another location"));
-- if (!purple_account_get_remember_password(session->account))
-- purple_account_set_password(session->account, NULL);
-- break;
-- case MSN_ERROR_SERV_UNAVAILABLE:
-- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-- msg = g_strdup(_("The MSN servers are temporarily "
-- "unavailable. Please wait and try "
-- "again."));
-- break;
-- case MSN_ERROR_SERV_DOWN:
-- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-- msg = g_strdup(_("The MSN servers are going down "
-- "temporarily"));
-- break;
-- case MSN_ERROR_AUTH:
-- reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
-- msg = g_strdup_printf(_("Unable to authenticate: %s"),
-- (info == NULL ) ?
-- _("Unknown error") : info);
-- /* Clear the password if it isn't being saved */
-- if (!purple_account_get_remember_password(session->account))
-- purple_account_set_password(session->account, NULL);
-- break;
-- case MSN_ERROR_BAD_BLIST:
-- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-- msg = g_strdup(_("Your MSN buddy list is temporarily "
-- "unavailable. Please wait and try "
-- "again."));
-- break;
-- default:
-- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-- msg = g_strdup(_("Unknown error"));
-- break;
-- }
--
-- msn_session_disconnect(session);
--
-- purple_connection_error_reason(gc, reason, msg);
--
-- g_free(msg);
--}
--
--static const char *
--get_login_step_text(MsnSession *session)
--{
-- const char *steps_text[] = {
-- _("Connecting"),
-- _("Handshaking"),
-- _("Transferring"),
-- _("Handshaking"),
-- _("Starting authentication"),
-- _("Getting cookie"),
-- _("Authenticating"),
-- _("Sending cookie"),
-- _("Retrieving buddy list")
-- };
--
-- return steps_text[session->login_step];
--}
--
--void
--msn_session_set_login_step(MsnSession *session, MsnLoginStep step)
--{
-- PurpleConnection *gc;
--
-- /* Prevent the connection progress going backwards, eg. if we get
-- * transferred several times during login */
-- if (session->login_step >= step)
-- return;
--
-- /* If we're already logged in, we're probably here because of a
-- * mid-session XFR from the notification server, so we don't want to
-- * popup the connection progress dialog */
-- if (session->logged_in)
-- return;
--
-- gc = session->account->gc;
--
-- session->login_step = step;
--
-- purple_connection_update_progress(gc, get_login_step_text(session), step,
-- MSN_LOGIN_STEPS);
--}
--
--void
--msn_session_finish_login(MsnSession *session)
--{
-- PurpleAccount *account;
-- PurpleConnection *gc;
-- PurpleStoredImage *img;
--
-- if (!session->logged_in) {
-- account = session->account;
-- gc = purple_account_get_connection(account);
--
-- img = purple_buddy_icons_find_account_icon(session->account);
-- /* TODO: Do we really want to call this if img is NULL? */
-- msn_user_set_buddy_icon(session->user, img);
-- if (img != NULL)
-- purple_imgstore_unref(img);
--
-- session->logged_in = TRUE;
-- purple_connection_set_state(gc, PURPLE_CONNECTED);
--
-- /* Sync users */
-- msn_session_sync_users(session);
-- }
--
-- /* TODO: Send this when updating status instead? */
-- msn_notification_send_uux_endpointdata(session);
-- msn_notification_send_uux_private_endpointdata(session);
--
-- msn_change_status(session);
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/session.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/session.h
---- pidgin-2.10.7/libpurple/protocols/msn/session.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/session.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,245 +0,0 @@
--/**
-- * @file session.h MSN session functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_SESSION_H
--#define MSN_SESSION_H
--
--typedef struct _MsnSession MsnSession;
--
--/**
-- * Types of errors.
-- */
--typedef enum
--{
-- MSN_ERROR_SERVCONN,
-- MSN_ERROR_UNSUPPORTED_PROTOCOL,
-- MSN_ERROR_HTTP_MALFORMED,
-- MSN_ERROR_AUTH,
-- MSN_ERROR_BAD_BLIST,
-- MSN_ERROR_SIGN_OTHER,
-- MSN_ERROR_SERV_DOWN,
-- MSN_ERROR_SERV_UNAVAILABLE
--} MsnErrorType;
--
--/**
-- * Login steps.
-- */
--typedef enum
--{
-- MSN_LOGIN_STEP_START,
-- MSN_LOGIN_STEP_HANDSHAKE,
-- MSN_LOGIN_STEP_TRANSFER,
-- MSN_LOGIN_STEP_HANDSHAKE2,
-- MSN_LOGIN_STEP_AUTH_START,
-- MSN_LOGIN_STEP_GET_COOKIE,
-- MSN_LOGIN_STEP_AUTH_END,
-- MSN_LOGIN_STEP_SYN,
-- MSN_LOGIN_STEP_END
--} MsnLoginStep;
--
--#define MSN_LOGIN_STEPS MSN_LOGIN_STEP_END
--
--#define MSN_LOGIN_FQY_TIMEOUT 30
--
--#define MSN_LOGIN_FQY_TIMEOUT 30
--
--#include "nexus.h"
--#include "notification.h"
--#include "oim.h"
--#include "switchboard.h"
--#include "user.h"
--#include "userlist.h"
--
--struct _MsnSession
--{
-- PurpleAccount *account;
-- MsnUser *user;
--
-- guint protocol_ver;
--
-- MsnLoginStep login_step; /**< The current step in the login process. */
--
-- gboolean connected:1;
-- gboolean logged_in:1; /**< A temporal flag to ignore local buddy list adds. */
-- gboolean destroying:1; /**< A flag that states if the session is being destroyed. */
-- gboolean http_method:1;
-- gboolean enable_mpop:1; /**< Use Multiple Points of Presence? */
-- int adl_fqy; /**< A count of ADL/FQY so status is only changed once. */
-- guint login_timeout; /**< Timeout to force status change if ADL/FQY fail. */
--
-- MsnNotification *notification;
-- MsnNexus *nexus;
-- MsnOim *oim;
-- MsnUserList *userlist;
-- char *abch_cachekey;
--
-- int servconns_count; /**< The count of server connections. */
-- GList *switches; /**< The list of all the switchboards. */
-- GList *slplinks; /**< The list of all the slplinks. */
--
-- /*psm info*/
-- char *psm;
--
--#if 0
-- char *blocked_text;
--#endif
--
-- struct
-- {
-- char *sid;
-- char *mspauth;
-- unsigned long sl;
-- char *client_ip;
-- int client_port;
-- char *mail_url;
-- gulong mail_timestamp;
-- gboolean email_enabled;
-- } passport_info;
--
-- GHashTable *soap_table;
-- guint soap_cleanup_handle;
-- char *guid;
--
-- GSList *url_datas; /**< PurpleUtilFetchUrlData to be cancelled on exit */
--};
--
--/**
-- * Creates an MSN session.
-- *
-- * @param account The account.
-- *
-- * @return The new MSN session.
-- */
--MsnSession *msn_session_new(PurpleAccount *account);
--
--/**
-- * Destroys an MSN session.
-- *
-- * @param session The MSN session to destroy.
-- */
--void msn_session_destroy(MsnSession *session);
--
--/**
-- * Connects to and initiates an MSN session.
-- *
-- * @param session The MSN session.
-- * @param host The dispatch server host.
-- * @param port The dispatch server port.
-- * @param http_method Whether to use or not http_method.
-- *
-- * @return @c TRUE on success, @c FALSE on failure.
-- */
--gboolean msn_session_connect(MsnSession *session,
-- const char *host, int port,
-- gboolean http_method);
--
--/**
-- * Disconnects from an MSN session.
-- *
-- * @param session The MSN session.
-- */
--void msn_session_disconnect(MsnSession *session);
--
-- /**
-- * Finds a switchboard with the given username.
-- *
-- * @param session The MSN session.
-- * @param username The username to search for.
-- *
-- * @return The switchboard, if found.
-- */
--MsnSwitchBoard *msn_session_find_swboard(MsnSession *session,
-- const char *username);
--
-- /**
-- * Finds a switchboard with the given conversation.
-- *
-- * @param session The MSN session.
-- * @param conv The conversation to search for.
-- *
-- * @return The switchboard, if found.
-- */
--MsnSwitchBoard *msn_session_find_swboard_with_conv(MsnSession *session,
-- PurpleConversation *conv);
--/**
-- * Finds a switchboard with the given chat ID.
-- *
-- * @param session The MSN session.
-- * @param chat_id The chat ID to search for.
-- *
-- * @return The switchboard, if found.
-- */
--MsnSwitchBoard *msn_session_find_swboard_with_id(const MsnSession *session,
-- int chat_id);
--
--/**
-- * Returns a switchboard to communicate with certain username.
-- *
-- * @param session The MSN session.
-- * @param username The username to search for.
-- * @param flag The flag of the switchboard
-- *
-- * @return The switchboard.
-- */
--MsnSwitchBoard *msn_session_get_swboard(MsnSession *session,
-- const char *username, MsnSBFlag flag);
--
--/**
-- * Sets an error for the MSN session.
-- *
-- * @param session The MSN session.
-- * @param error The error.
-- * @param info Extra information.
-- */
--void msn_session_set_error(MsnSession *session, MsnErrorType error,
-- const char *info);
--
--/**
-- * Starts a timeout to initiate finishing login. Sometimes the server ignores
-- * our FQY requests, so this forces ourselves online eventually.
-- *
-- * @param session The MSN session.
-- */
--void
--msn_session_activate_login_timeout(MsnSession *session);
--
--/**
-- * Sets the current step in the login process.
-- *
-- * @param session The MSN session.
-- * @param step The current step.
-- */
--void msn_session_set_login_step(MsnSession *session, MsnLoginStep step);
--
--/**
-- * Finish the login proccess.
-- *
-- * @param session The MSN session.
-- */
--void msn_session_finish_login(MsnSession *session);
--
--/*post message to User*/
--void msn_session_report_user(MsnSession *session,const char *passport,
-- const char *msg,PurpleMessageFlags flags);
--
--#endif /* MSN_SESSION_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slp.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/slp.c
---- pidgin-2.10.7/libpurple/protocols/msn/slp.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slp.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,396 +0,0 @@
--/**
-- * @file msnslp.c MSNSLP support
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "slp.h"
--#include "slpcall.h"
--#include "slpmsg.h"
--#include "msnutils.h"
--
--#include "object.h"
--#include "user.h"
--#include "sbconn.h"
--#include "directconn.h"
--#include "p2p.h"
--#include "xfer.h"
--
--/* seconds to delay between sending buddy icon requests to the server. */
--#define BUDDY_ICON_DELAY 20
--
--typedef struct {
-- MsnSession *session;
-- const char *remote_user;
-- const char *sha1;
--} MsnFetchUserDisplayData;
--
--/**************************************************************************
-- * SLP Control
-- **************************************************************************/
--
--void
--msn_slp_send_ok(MsnSlpCall *slpcall, const char *branch,
-- const char *type, const char *content)
--{
-- MsnSlpLink *slplink;
-- MsnSlpMessage *slpmsg;
--
-- slplink = slpcall->slplink;
--
-- /* 200 OK */
-- slpmsg = msn_slpmsg_sip_new(slpcall, 1,
-- "MSNSLP/1.0 200 OK",
-- branch, type, content);
--
-- slpmsg->info = "SLP 200 OK";
-- slpmsg->text_body = TRUE;
--
-- msn_slplink_queue_slpmsg(slplink, slpmsg);
--}
--
--void
--msn_slp_send_decline(MsnSlpCall *slpcall, const char *branch,
-- const char *type, const char *content)
--{
-- MsnSlpLink *slplink;
-- MsnSlpMessage *slpmsg;
--
-- slplink = slpcall->slplink;
--
-- /* 603 Decline */
-- slpmsg = msn_slpmsg_sip_new(slpcall, 1,
-- "MSNSLP/1.0 603 Decline",
-- branch, type, content);
--
-- slpmsg->info = "SLP 603 Decline";
-- slpmsg->text_body = TRUE;
--
-- msn_slplink_queue_slpmsg(slplink, slpmsg);
--}
--
--/**************************************************************************
-- * Msg Callbacks
-- **************************************************************************/
--
--/*
-- * Called on a timeout from end_user_display(). Frees a buddy icon window slow and dequeues the next
-- * buddy icon request if there is one.
-- */
--static gboolean
--msn_release_buddy_icon_request_timeout(gpointer data)
--{
-- MsnUserList *userlist = (MsnUserList *)data;
--
-- /* Free one window slot */
-- userlist->buddy_icon_window++;
--
-- /* Clear the tag for our former request timer */
-- userlist->buddy_icon_request_timer = 0;
--
-- msn_release_buddy_icon_request(userlist);
--
-- return FALSE;
--}
--
--static void
--got_user_display(MsnSlpCall *slpcall,
-- const guchar *data, gsize size)
--{
-- const char *info;
-- PurpleAccount *account;
--
-- g_return_if_fail(slpcall != NULL);
--
-- info = slpcall->data_info;
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "Got User Display: %s\n", slpcall->slplink->remote_user);
--
-- account = slpcall->slplink->session->account;
--
-- purple_buddy_icons_set_for_user(account, slpcall->slplink->remote_user,
-- g_memdup(data, size), size, info);
--}
--
--static void
--end_user_display(MsnSlpCall *slpcall, MsnSession *session)
--{
-- MsnUserList *userlist;
--
-- g_return_if_fail(session != NULL);
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "End User Display\n");
--
-- userlist = session->userlist;
--
-- /* If the session is being destroyed we better stop doing anything. */
-- if (session->destroying)
-- return;
--
-- /* Delay before freeing a buddy icon window slot and requesting the next icon, if appropriate.
-- * If we don't delay, we'll rapidly hit the MSN equivalent of AIM's rate limiting; the server will
-- * send us an error 800 like so:
-- *
-- * C: NS 000: XFR 21 SB
-- * S: NS 000: 800 21
-- */
-- if (userlist->buddy_icon_request_timer) {
-- /* Free the window slot used by this previous request */
-- userlist->buddy_icon_window++;
--
-- /* Clear our pending timeout */
-- purple_timeout_remove(userlist->buddy_icon_request_timer);
-- }
--
-- /* Wait BUDDY_ICON_DELAY s before freeing our window slot and requesting the next icon. */
-- userlist->buddy_icon_request_timer = purple_timeout_add_seconds(BUDDY_ICON_DELAY,
-- msn_release_buddy_icon_request_timeout, userlist);
--}
--
--static void
--fetched_user_display(PurpleUtilFetchUrlData *url_data, gpointer user_data,
-- const gchar *url_text, gsize len, const gchar *error_message)
--{
-- MsnFetchUserDisplayData *data = user_data;
-- MsnSession *session = data->session;
--
-- session->url_datas = g_slist_remove(session->url_datas, url_data);
--
-- if (url_text) {
-- purple_buddy_icons_set_for_user(session->account, data->remote_user,
-- g_memdup(url_text, len), len,
-- data->sha1);
-- }
--
-- end_user_display(NULL, session);
--
-- g_free(user_data);
--}
--
--static void
--request_own_user_display(MsnUser *user)
--{
-- PurpleAccount *account;
-- MsnSession *session;
-- MsnObject *my_obj = NULL;
-- gconstpointer data = NULL;
-- const char *info = NULL;
-- size_t len = 0;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "Requesting our own user display\n");
--
-- session = user->userlist->session;
-- account = session->account;
-- my_obj = msn_user_get_object(user);
--
-- if (my_obj != NULL) {
-- PurpleStoredImage *img = msn_object_get_image(my_obj);
-- data = purple_imgstore_get_data(img);
-- len = purple_imgstore_get_size(img);
-- info = msn_object_get_sha1(my_obj);
-- }
--
-- purple_buddy_icons_set_for_user(account, user->passport, g_memdup(data, len), len, info);
--
-- /* Free one window slot */
-- session->userlist->buddy_icon_window++;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "msn_request_user_display(): buddy_icon_window++ yields =%d\n",
-- session->userlist->buddy_icon_window);
--
-- msn_release_buddy_icon_request(session->userlist);
--}
--
--void
--msn_request_user_display(MsnUser *user)
--{
-- PurpleAccount *account;
-- MsnSession *session;
-- MsnSlpLink *slplink;
-- MsnObject *obj;
-- const char *info;
--
-- session = user->userlist->session;
-- account = session->account;
--
-- slplink = msn_session_get_slplink(session, user->passport);
--
-- obj = msn_user_get_object(user);
--
-- info = msn_object_get_sha1(obj);
--
-- if (g_ascii_strcasecmp(user->passport,
-- purple_account_get_username(account)))
-- {
-- const char *url = msn_object_get_url1(obj);
-- if (url) {
-- MsnFetchUserDisplayData *data = g_new0(MsnFetchUserDisplayData, 1);
-- PurpleUtilFetchUrlData *url_data;
-- data->session = session;
-- data->remote_user = user->passport;
-- data->sha1 = info;
-- url_data = purple_util_fetch_url_len(url, TRUE, NULL, TRUE, 200*1024,
-- fetched_user_display, data);
-- session->url_datas = g_slist_prepend(session->url_datas, url_data);
-- } else {
-- msn_slplink_request_object(slplink, info, got_user_display,
-- end_user_display, obj);
-- }
-- }
-- else
-- request_own_user_display(user);
--}
--
--static void
--send_file_cb(MsnSlpCall *slpcall)
--{
-- MsnSlpMessage *slpmsg;
-- PurpleXfer *xfer;
--
-- xfer = (PurpleXfer *)slpcall->xfer;
-- if (purple_xfer_get_status(xfer) >= PURPLE_XFER_STATUS_STARTED)
-- return;
--
-- purple_xfer_ref(xfer);
-- purple_xfer_start(xfer, -1, NULL, 0);
-- if (purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_STARTED) {
-- purple_xfer_unref(xfer);
-- return;
-- }
-- purple_xfer_unref(xfer);
--
-- slpmsg = msn_slpmsg_file_new(slpcall, purple_xfer_get_size(xfer));
--
-- msn_slplink_send_slpmsg(slpcall->slplink, slpmsg);
--}
--
--static gchar *
--gen_context(PurpleXfer *xfer, const char *file_name, const char *file_path)
--{
-- gsize size = 0;
-- MsnFileContext context;
-- gchar *u8 = NULL;
-- gchar *ret;
-- gunichar2 *uni = NULL;
-- glong currentChar = 0;
-- glong len = 0;
-- const char *preview;
-- gsize preview_len;
--
-- size = purple_xfer_get_size(xfer);
--
-- purple_xfer_prepare_thumbnail(xfer, "png");
--
-- if (!file_name) {
-- gchar *basename = g_path_get_basename(file_path);
-- u8 = purple_utf8_try_convert(basename);
-- g_free(basename);
-- file_name = u8;
-- }
--
-- uni = g_utf8_to_utf16(file_name, -1, NULL, &len, NULL);
--
-- if (u8) {
-- g_free(u8);
-- file_name = NULL;
-- u8 = NULL;
-- }
--
-- preview = purple_xfer_get_thumbnail(xfer, &preview_len);
--
-- context.length = MSN_FILE_CONTEXT_SIZE;
-- context.version = 2; /* V.3 contains additional unnecessary data */
-- context.file_size = size;
-- if (preview)
-- context.type = 0;
-- else
-- context.type = 1;
--
-- len = MIN(len, MAX_FILE_NAME_LEN);
-- for (currentChar = 0; currentChar < len; currentChar++) {
-- context.file_name[currentChar] = GUINT16_TO_LE(uni[currentChar]);
-- }
-- memset(&context.file_name[currentChar], 0x00, (MAX_FILE_NAME_LEN - currentChar) * 2);
--
-- memset(&context.unknown1, 0, sizeof(context.unknown1));
-- context.unknown2 = 0xffffffff;
--
-- /* Mind the cast, as in, don't free it after! */
-- context.preview = (char *)preview;
-- context.preview_len = preview_len;
--
-- u8 = msn_file_context_to_wire(&context);
-- ret = purple_base64_encode((const guchar *)u8, MSN_FILE_CONTEXT_SIZE + preview_len);
--
-- g_free(uni);
-- g_free(u8);
--
-- return ret;
--}
--
--void
--msn_request_ft(PurpleXfer *xfer)
--{
-- MsnSlpCall *slpcall;
-- MsnSlpLink *slplink;
-- char *context;
-- const char *fn;
-- const char *fp;
--
-- fn = purple_xfer_get_filename(xfer);
-- fp = purple_xfer_get_local_filename(xfer);
--
-- slplink = xfer->data;
--
-- g_return_if_fail(slplink != NULL);
-- g_return_if_fail(fp != NULL);
--
-- slpcall = msn_slpcall_new(slplink);
-- msn_slpcall_init(slpcall, MSN_SLPCALL_DC);
--
-- slpcall->session_init_cb = send_file_cb;
-- slpcall->end_cb = msn_xfer_end_cb;
-- slpcall->cb = msn_xfer_completed_cb;
-- slpcall->xfer = xfer;
-- purple_xfer_ref(slpcall->xfer);
--
-- slpcall->pending = TRUE;
--
-- purple_xfer_set_cancel_send_fnc(xfer, msn_xfer_cancel);
-- purple_xfer_set_read_fnc(xfer, msn_xfer_read);
-- purple_xfer_set_write_fnc(xfer, msn_xfer_write);
--
-- xfer->data = slpcall;
--
-- context = gen_context(xfer, fn, fp);
--
-- msn_slpcall_invite(slpcall, MSN_FT_GUID, P2P_APPID_FILE, context);
-- msn_slplink_unref(slplink);
--
-- g_free(context);
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slpcall.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpcall.c
---- pidgin-2.10.7/libpurple/protocols/msn/slpcall.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpcall.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1157 +0,0 @@
--/**
-- * @file slpcall.c SLP Call Functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--#include "smiley.h"
--
--#include "msnutils.h"
--#include "slpcall.h"
--
--#include "slp.h"
--#include "p2p.h"
--#include "xfer.h"
--
--/**************************************************************************
-- * Main
-- **************************************************************************/
--
--static gboolean
--msn_slpcall_timeout(gpointer data)
--{
-- MsnSlpCall *slpcall;
--
-- slpcall = data;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "slpcall_timeout: slpcall(%p)\n", slpcall);
--
-- if (!slpcall->pending && !slpcall->progress)
-- {
-- msn_slpcall_destroy(slpcall);
-- return TRUE;
-- }
--
-- slpcall->progress = FALSE;
--
-- return TRUE;
--}
--
--MsnSlpCall *
--msn_slpcall_new(MsnSlpLink *slplink)
--{
-- MsnSlpCall *slpcall;
--
-- g_return_val_if_fail(slplink != NULL, NULL);
--
-- slpcall = g_new0(MsnSlpCall, 1);
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "slpcall_new: slpcall(%p)\n", slpcall);
--
-- slpcall->slplink = slplink;
--
-- msn_slplink_add_slpcall(slplink, slpcall);
--
-- slpcall->timer = purple_timeout_add_seconds(MSN_SLPCALL_TIMEOUT, msn_slpcall_timeout, slpcall);
--
-- return slpcall;
--}
--
--void
--msn_slpcall_destroy(MsnSlpCall *slpcall)
--{
-- GList *e;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "slpcall_destroy: slpcall(%p)\n", slpcall);
--
-- g_return_if_fail(slpcall != NULL);
--
-- if (slpcall->timer)
-- purple_timeout_remove(slpcall->timer);
--
-- for (e = slpcall->slplink->slp_msgs; e != NULL; )
-- {
-- MsnSlpMessage *slpmsg = e->data;
-- e = e->next;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "slpcall_destroy: trying slpmsg(%p)\n",
-- slpmsg);
--
-- if (slpmsg->slpcall == slpcall)
-- {
-- msn_slpmsg_destroy(slpmsg);
-- }
-- }
--
-- if (slpcall->end_cb != NULL)
-- slpcall->end_cb(slpcall, slpcall->slplink->session);
--
-- if (slpcall->xfer != NULL) {
-- if (purple_xfer_get_type(slpcall->xfer) == PURPLE_XFER_RECEIVE)
-- g_byte_array_free(slpcall->u.incoming_data, TRUE);
-- slpcall->xfer->data = NULL;
-- purple_xfer_unref(slpcall->xfer);
-- }
--
--
-- msn_slplink_remove_slpcall(slpcall->slplink, slpcall);
--
-- g_free(slpcall->id);
-- g_free(slpcall->branch);
-- g_free(slpcall->data_info);
--
-- g_free(slpcall);
--}
--
--void
--msn_slpcall_init(MsnSlpCall *slpcall, MsnSlpCallType type)
--{
-- slpcall->session_id = rand() % 0xFFFFFF00 + 4;
-- slpcall->id = rand_guid();
-- slpcall->type = type;
--}
--
--void
--msn_slpcall_session_init(MsnSlpCall *slpcall)
--{
-- if (slpcall->session_init_cb)
-- slpcall->session_init_cb(slpcall);
--
-- slpcall->started = TRUE;
--}
--
--void
--msn_slpcall_invite(MsnSlpCall *slpcall, const char *euf_guid,
-- MsnP2PAppId app_id, const char *context)
--{
-- MsnSlpLink *slplink;
-- MsnSlpMessage *slpmsg;
-- char *header;
-- char *content;
--
-- g_return_if_fail(slpcall != NULL);
-- g_return_if_fail(context != NULL);
--
-- slplink = slpcall->slplink;
--
-- slpcall->branch = rand_guid();
--
-- content = g_strdup_printf(
-- "EUF-GUID: {%s}\r\n"
-- "SessionID: %lu\r\n"
-- "AppID: %d\r\n"
-- "Context: %s\r\n\r\n",
-- euf_guid,
-- slpcall->session_id,
-- app_id,
-- context);
--
-- header = g_strdup_printf("INVITE MSNMSGR:%s MSNSLP/1.0",
-- slplink->remote_user);
--
-- slpmsg = msn_slpmsg_sip_new(slpcall, 0, header, slpcall->branch,
-- "application/x-msnmsgr-sessionreqbody", content);
--
-- slpmsg->info = "SLP INVITE";
-- slpmsg->text_body = TRUE;
--
-- msn_slplink_send_slpmsg(slplink, slpmsg);
--
-- g_free(header);
-- g_free(content);
--}
--
--void
--msn_slpcall_close(MsnSlpCall *slpcall)
--{
-- g_return_if_fail(slpcall != NULL);
-- g_return_if_fail(slpcall->slplink != NULL);
--
-- send_bye(slpcall, "application/x-msnmsgr-sessionclosebody");
-- msn_slplink_send_queued_slpmsgs(slpcall->slplink);
-- msn_slpcall_destroy(slpcall);
--}
--
--/*****************************************************************************
-- * Parse received SLP messages
-- ****************************************************************************/
--
--/**************************************************************************
-- *** Util
-- **************************************************************************/
--
--static char *
--get_token(const char *str, const char *start, const char *end)
--{
-- const char *c, *c2;
--
-- if ((c = strstr(str, start)) == NULL)
-- return NULL;
--
-- c += strlen(start);
--
-- if (end != NULL)
-- {
-- if ((c2 = strstr(c, end)) == NULL)
-- return NULL;
--
-- return g_strndup(c, c2 - c);
-- }
-- else
-- {
-- /* This has to be changed */
-- return g_strdup(c);
-- }
--
--}
--
--/* XXX: this could be improved if we tracked custom smileys
-- * per-protocol, per-account, per-session or (ideally) per-conversation
-- */
--static PurpleStoredImage *
--find_valid_emoticon(PurpleAccount *account, const char *path)
--{
-- GList *smileys;
--
-- if (!purple_account_get_bool(account, "custom_smileys", TRUE))
-- return NULL;
--
-- smileys = purple_smileys_get_all();
--
-- for (; smileys; smileys = g_list_delete_link(smileys, smileys)) {
-- PurpleSmiley *smiley;
-- PurpleStoredImage *img;
--
-- smiley = smileys->data;
-- img = purple_smiley_get_stored_image(smiley);
--
-- if (purple_strequal(path, purple_imgstore_get_filename(img))) {
-- g_list_free(smileys);
-- return img;
-- }
--
-- purple_imgstore_unref(img);
-- }
--
-- purple_debug_error("msn", "Received illegal request for file %s\n", path);
-- return NULL;
--}
--
--static char *
--parse_dc_nonce(const char *content, MsnDirectConnNonceType *ntype)
--{
-- char *nonce;
--
-- *ntype = DC_NONCE_UNKNOWN;
--
-- nonce = get_token(content, "Hashed-Nonce: {", "}\r\n");
-- if (nonce) {
-- *ntype = DC_NONCE_SHA1;
-- } else {
-- guint32 n1, n6;
-- guint16 n2, n3, n4, n5;
-- nonce = get_token(content, "Nonce: {", "}\r\n");
-- if (nonce
-- && sscanf(nonce, "%08x-%04hx-%04hx-%04hx-%04hx%08x",
-- &n1, &n2, &n3, &n4, &n5, &n6) == 6) {
-- *ntype = DC_NONCE_PLAIN;
-- g_free(nonce);
-- nonce = g_malloc(16);
-- *(guint32 *)(nonce + 0) = GUINT32_TO_LE(n1);
-- *(guint16 *)(nonce + 4) = GUINT16_TO_LE(n2);
-- *(guint16 *)(nonce + 6) = GUINT16_TO_LE(n3);
-- *(guint16 *)(nonce + 8) = GUINT16_TO_BE(n4);
-- *(guint16 *)(nonce + 10) = GUINT16_TO_BE(n5);
-- *(guint32 *)(nonce + 12) = GUINT32_TO_BE(n6);
-- } else {
-- /* Invalid nonce, so ignore request */
-- g_free(nonce);
-- nonce = NULL;
-- }
-- }
--
-- return nonce;
--}
--
--static void
--msn_slp_process_transresp(MsnSlpCall *slpcall, const char *content)
--{
-- /* A direct connection negotiation response */
-- char *bridge;
-- char *nonce;
-- char *listening;
-- MsnDirectConn *dc = slpcall->slplink->dc;
-- MsnDirectConnNonceType ntype;
--
-- purple_debug_info("msn", "process_transresp\n");
--
-- /* Direct connections are disabled. */
-- if (!purple_account_get_bool(slpcall->slplink->session->account, "direct_connect", TRUE))
-- return;
--
-- g_return_if_fail(dc != NULL);
-- g_return_if_fail(dc->state == DC_STATE_CLOSED);
--
-- bridge = get_token(content, "Bridge: ", "\r\n");
-- nonce = parse_dc_nonce(content, &ntype);
-- listening = get_token(content, "Listening: ", "\r\n");
-- if (listening && bridge && !strcmp(bridge, "TCPv1")) {
-- /* Ok, the client supports direct TCP connection */
--
-- /* We always need this. */
-- if (ntype == DC_NONCE_SHA1) {
-- strncpy(dc->remote_nonce, nonce, 36);
-- dc->remote_nonce[36] = '\0';
-- }
--
-- if (!strcasecmp(listening, "false")) {
-- if (dc->listen_data != NULL) {
-- /*
-- * We'll listen for incoming connections but
-- * the listening socket isn't ready yet so we cannot
-- * send the INVITE packet now. Put the slpcall into waiting mode
-- * and let the callback send the invite.
-- */
-- slpcall->wait_for_socket = TRUE;
--
-- } else if (dc->listenfd != -1) {
-- /* The listening socket is ready. Send the INVITE here. */
-- msn_dc_send_invite(dc);
--
-- } else {
-- /* We weren't able to create a listener either. Use SB. */
-- msn_dc_fallback_to_sb(dc);
-- }
--
-- } else {
-- /*
-- * We should connect to the client so parse
-- * IP/port from response.
-- */
-- char *ip, *port_str;
-- int port = 0;
--
-- if (ntype == DC_NONCE_PLAIN) {
-- /* Only needed for listening side. */
-- memcpy(dc->nonce, nonce, 16);
-- }
--
-- /* Cancel any listen attempts because we don't need them. */
-- if (dc->listenfd_handle != 0) {
-- purple_input_remove(dc->listenfd_handle);
-- dc->listenfd_handle = 0;
-- }
-- if (dc->connect_timeout_handle != 0) {
-- purple_timeout_remove(dc->connect_timeout_handle);
-- dc->connect_timeout_handle = 0;
-- }
-- if (dc->listenfd != -1) {
-- purple_network_remove_port_mapping(dc->listenfd);
-- close(dc->listenfd);
-- dc->listenfd = -1;
-- }
-- if (dc->listen_data != NULL) {
-- purple_network_listen_cancel(dc->listen_data);
-- dc->listen_data = NULL;
-- }
--
-- /* Save external IP/port for later use. We'll try local connection first. */
-- dc->ext_ip = get_token(content, "IPv4External-Addrs: ", "\r\n");
-- port_str = get_token(content, "IPv4External-Port: ", "\r\n");
-- if (port_str) {
-- dc->ext_port = atoi(port_str);
-- g_free(port_str);
-- }
--
-- ip = get_token(content, "IPv4Internal-Addrs: ", "\r\n");
-- port_str = get_token(content, "IPv4Internal-Port: ", "\r\n");
-- if (port_str) {
-- port = atoi(port_str);
-- g_free(port_str);
-- }
--
-- if (ip && port) {
-- /* Try internal address first */
-- dc->connect_data = purple_proxy_connect(
-- NULL,
-- slpcall->slplink->session->account,
-- ip,
-- port,
-- msn_dc_connected_to_peer_cb,
-- dc
-- );
--
-- if (dc->connect_data) {
-- /* Add connect timeout handle */
-- dc->connect_timeout_handle = purple_timeout_add_seconds(
-- DC_OUTGOING_TIMEOUT,
-- msn_dc_outgoing_connection_timeout_cb,
-- dc
-- );
-- } else {
-- /*
-- * Connection failed
-- * Try external IP/port (if specified)
-- */
-- msn_dc_outgoing_connection_timeout_cb(dc);
-- }
--
-- } else {
-- /*
-- * Omitted or invalid internal IP address / port
-- * Try external IP/port (if specified)
-- */
-- msn_dc_outgoing_connection_timeout_cb(dc);
-- }
--
-- g_free(ip);
-- }
--
-- } else {
-- /*
-- * Invalid direct connect invitation or
-- * TCP connection is not supported
-- */
-- }
--
-- g_free(listening);
-- g_free(nonce);
-- g_free(bridge);
--
-- return;
--}
--
--static void
--got_sessionreq(MsnSlpCall *slpcall, const char *branch,
-- const char *euf_guid, const char *context)
--{
-- gboolean accepted = FALSE;
--
-- if (!strcmp(euf_guid, MSN_OBJ_GUID))
-- {
-- /* Emoticon or UserDisplay */
-- char *content;
-- gsize len;
-- MsnSlpLink *slplink;
-- MsnSlpMessage *slpmsg;
-- MsnObject *obj;
-- char *msnobj_data;
-- PurpleStoredImage *img = NULL;
-- int type;
--
-- /* Send Ok */
-- content = g_strdup_printf("SessionID: %lu\r\n\r\n",
-- slpcall->session_id);
--
-- msn_slp_send_ok(slpcall, branch, "application/x-msnmsgr-sessionreqbody",
-- content);
--
-- g_free(content);
--
-- slplink = slpcall->slplink;
--
-- msnobj_data = (char *)purple_base64_decode(context, &len);
-- obj = msn_object_new_from_string(msnobj_data);
-- type = msn_object_get_type(obj);
-- g_free(msnobj_data);
-- if (type == MSN_OBJECT_EMOTICON) {
-- img = find_valid_emoticon(slplink->session->account, obj->location);
-- } else if (type == MSN_OBJECT_USERTILE) {
-- img = msn_object_get_image(obj);
-- if (img)
-- purple_imgstore_ref(img);
-- }
-- msn_object_destroy(obj);
--
-- if (img != NULL) {
-- /* DATA PREP */
-- slpmsg = msn_slpmsg_dataprep_new(slpcall);
-- msn_slplink_queue_slpmsg(slplink, slpmsg);
--
-- /* DATA */
-- slpmsg = msn_slpmsg_obj_new(slpcall, img);
-- msn_slplink_queue_slpmsg(slplink, slpmsg);
-- purple_imgstore_unref(img);
--
-- accepted = TRUE;
--
-- } else {
-- purple_debug_error("msn", "Wrong object.\n");
-- }
-- }
--
-- else if (!strcmp(euf_guid, MSN_FT_GUID))
-- {
-- /* File Transfer */
-- PurpleAccount *account;
-- PurpleXfer *xfer;
-- MsnFileContext *file_context;
-- char *buf;
-- gsize bin_len;
-- guint32 file_size;
-- char *file_name;
--
-- account = slpcall->slplink->session->account;
--
-- slpcall->end_cb = msn_xfer_end_cb;
-- slpcall->branch = g_strdup(branch);
--
-- slpcall->pending = TRUE;
--
-- xfer = purple_xfer_new(account, PURPLE_XFER_RECEIVE,
-- slpcall->slplink->remote_user);
--
-- buf = (char *)purple_base64_decode(context, &bin_len);
-- file_context = msn_file_context_from_wire(buf, bin_len);
--
-- if (file_context != NULL) {
-- file_size = file_context->file_size;
--
-- file_name = g_convert((const gchar *)&file_context->file_name,
-- MAX_FILE_NAME_LEN * 2,
-- "UTF-8", "UTF-16LE",
-- NULL, NULL, NULL);
--
-- purple_xfer_set_filename(xfer, file_name ? file_name : "");
-- g_free(file_name);
-- purple_xfer_set_size(xfer, file_size);
-- purple_xfer_set_init_fnc(xfer, msn_xfer_init);
-- purple_xfer_set_request_denied_fnc(xfer, msn_xfer_cancel);
-- purple_xfer_set_cancel_recv_fnc(xfer, msn_xfer_cancel);
-- purple_xfer_set_read_fnc(xfer, msn_xfer_read);
-- purple_xfer_set_write_fnc(xfer, msn_xfer_write);
--
-- slpcall->u.incoming_data = g_byte_array_new();
--
-- slpcall->xfer = xfer;
-- purple_xfer_ref(slpcall->xfer);
--
-- xfer->data = slpcall;
--
-- if (file_context->preview) {
-- purple_xfer_set_thumbnail(xfer, file_context->preview,
-- file_context->preview_len,
-- "image/png");
-- g_free(file_context->preview);
-- }
--
-- purple_xfer_request(xfer);
-- }
-- g_free(file_context);
-- g_free(buf);
--
-- accepted = TRUE;
--
-- } else if (!strcmp(euf_guid, MSN_CAM_REQUEST_GUID)) {
-- purple_debug_info("msn", "Cam request.\n");
-- if (slpcall->slplink && slpcall->slplink->session) {
-- PurpleConversation *conv;
-- gchar *from = slpcall->slplink->remote_user;
-- conv = purple_find_conversation_with_account(
-- PURPLE_CONV_TYPE_IM, from,
-- slpcall->slplink->session->account);
-- if (conv) {
-- char *buf;
-- buf = g_strdup_printf(
-- _("%s requests to view your "
-- "webcam, but this request is "
-- "not yet supported."), from);
-- purple_conversation_write(conv, NULL, buf,
-- PURPLE_MESSAGE_SYSTEM |
-- PURPLE_MESSAGE_NOTIFY,
-- time(NULL));
-- g_free(buf);
-- }
-- }
--
-- } else if (!strcmp(euf_guid, MSN_CAM_GUID)) {
-- purple_debug_info("msn", "Cam invite.\n");
-- if (slpcall->slplink && slpcall->slplink->session) {
-- PurpleConversation *conv;
-- gchar *from = slpcall->slplink->remote_user;
-- conv = purple_find_conversation_with_account(
-- PURPLE_CONV_TYPE_IM, from,
-- slpcall->slplink->session->account);
-- if (conv) {
-- char *buf;
-- buf = g_strdup_printf(
-- _("%s invited you to view his/her webcam, but "
-- "this is not yet supported."), from);
-- purple_conversation_write(conv, NULL, buf,
-- PURPLE_MESSAGE_SYSTEM |
-- PURPLE_MESSAGE_NOTIFY,
-- time(NULL));
-- g_free(buf);
-- }
-- }
--
-- } else
-- purple_debug_warning("msn", "SLP SessionReq with unknown EUF-GUID: %s\n", euf_guid);
--
-- if (!accepted) {
-- char *content = g_strdup_printf("SessionID: %lu\r\n\r\n",
-- slpcall->session_id);
-- msn_slp_send_decline(slpcall, branch, "application/x-msnmsgr-sessionreqbody", content);
-- g_free(content);
-- }
--}
--
--void
--send_bye(MsnSlpCall *slpcall, const char *type)
--{
-- MsnSlpLink *slplink;
-- PurpleAccount *account;
-- MsnSlpMessage *slpmsg;
-- char *header;
--
-- slplink = slpcall->slplink;
--
-- g_return_if_fail(slplink != NULL);
--
-- account = slplink->session->account;
--
-- header = g_strdup_printf("BYE MSNMSGR:%s MSNSLP/1.0",
-- purple_account_get_username(account));
--
-- slpmsg = msn_slpmsg_sip_new(slpcall, 0, header,
-- "A0D624A6-6C0C-4283-A9E0-BC97B4B46D32",
-- type,
-- "\r\n");
-- g_free(header);
--
-- slpmsg->info = "SLP BYE";
-- slpmsg->text_body = TRUE;
--
-- msn_slplink_queue_slpmsg(slplink, slpmsg);
--}
--
--static void
--got_invite(MsnSlpCall *slpcall,
-- const char *branch, const char *type, const char *content)
--{
-- MsnSlpLink *slplink;
--
-- slplink = slpcall->slplink;
--
-- if (!strcmp(type, "application/x-msnmsgr-sessionreqbody"))
-- {
-- char *euf_guid, *context;
-- char *temp;
--
-- euf_guid = get_token(content, "EUF-GUID: {", "}\r\n");
--
-- temp = get_token(content, "SessionID: ", "\r\n");
-- if (temp != NULL)
-- slpcall->session_id = atoi(temp);
-- g_free(temp);
--
-- temp = get_token(content, "AppID: ", "\r\n");
-- if (temp != NULL)
-- slpcall->app_id = atoi(temp);
-- g_free(temp);
--
-- context = get_token(content, "Context: ", "\r\n");
--
-- if (context != NULL)
-- got_sessionreq(slpcall, branch, euf_guid, context);
--
-- g_free(context);
-- g_free(euf_guid);
-- }
-- else if (!strcmp(type, "application/x-msnmsgr-transreqbody"))
-- {
-- /* A direct connection negotiation request */
-- char *bridges;
-- char *nonce;
-- MsnDirectConnNonceType ntype;
--
-- purple_debug_info("msn", "got_invite: transreqbody received\n");
--
-- /* Direct connections may be disabled. */
-- if (!purple_account_get_bool(slplink->session->account, "direct_connect", TRUE)) {
-- msn_slp_send_ok(slpcall, branch,
-- "application/x-msnmsgr-transrespbody",
-- "Bridge: TCPv1\r\n"
-- "Listening: false\r\n"
-- "Nonce: {00000000-0000-0000-0000-000000000000}\r\n"
-- "\r\n");
-- msn_slpcall_session_init(slpcall);
--
-- return;
-- }
--
-- /* Don't do anything if we already have a direct connection */
-- if (slplink->dc != NULL)
-- return;
--
-- bridges = get_token(content, "Bridges: ", "\r\n");
-- nonce = parse_dc_nonce(content, &ntype);
-- if (bridges && strstr(bridges, "TCPv1") != NULL) {
-- /*
-- * Ok, the client supports direct TCP connection
-- * Try to create a listening port
-- */
-- MsnDirectConn *dc;
--
-- dc = msn_dc_new(slpcall);
-- if (ntype == DC_NONCE_PLAIN) {
-- /* There is only one nonce for plain auth. */
-- dc->nonce_type = ntype;
-- memcpy(dc->nonce, nonce, 16);
-- } else if (ntype == DC_NONCE_SHA1) {
-- /* Each side has a nonce in SHA1 auth. */
-- dc->nonce_type = ntype;
-- strncpy(dc->remote_nonce, nonce, 36);
-- dc->remote_nonce[36] = '\0';
-- }
--
-- dc->listen_data = purple_network_listen_range(
-- 0, 0,
-- SOCK_STREAM,
-- msn_dc_listen_socket_created_cb,
-- dc
-- );
--
-- if (dc->listen_data == NULL) {
-- /* Listen socket creation failed */
--
-- purple_debug_info("msn", "got_invite: listening failed\n");
--
-- if (dc->nonce_type != DC_NONCE_PLAIN)
-- msn_slp_send_ok(slpcall, branch,
-- "application/x-msnmsgr-transrespbody",
-- "Bridge: TCPv1\r\n"
-- "Listening: false\r\n"
-- "Hashed-Nonce: {00000000-0000-0000-0000-000000000000}\r\n"
-- "\r\n");
-- else
-- msn_slp_send_ok(slpcall, branch,
-- "application/x-msnmsgr-transrespbody",
-- "Bridge: TCPv1\r\n"
-- "Listening: false\r\n"
-- "Nonce: {00000000-0000-0000-0000-000000000000}\r\n"
-- "\r\n");
--
-- } else {
-- /*
-- * Listen socket created successfully.
-- * Don't send anything here because we don't know the parameters
-- * of the created socket yet. msn_dc_send_ok will be called from
-- * the callback function: dc_listen_socket_created_cb
-- */
-- purple_debug_info("msn", "got_invite: listening socket created\n");
--
-- dc->send_connection_info_msg_cb = msn_dc_send_ok;
-- slpcall->wait_for_socket = TRUE;
-- }
--
-- } else {
-- /*
-- * Invalid direct connect invitation or
-- * TCP connection is not supported.
-- */
-- }
--
-- g_free(nonce);
-- g_free(bridges);
-- }
-- else if (!strcmp(type, "application/x-msnmsgr-transrespbody"))
-- {
-- /* A direct connection negotiation response */
-- msn_slp_process_transresp(slpcall, content);
-- }
--}
--
--static void
--got_ok(MsnSlpCall *slpcall,
-- const char *type, const char *content)
--{
-- g_return_if_fail(slpcall != NULL);
-- g_return_if_fail(type != NULL);
--
-- if (!strcmp(type, "application/x-msnmsgr-sessionreqbody"))
-- {
-- char *content;
-- char *header;
-- char *nonce = NULL;
-- MsnSession *session = slpcall->slplink->session;
-- MsnSlpMessage *msg;
-- MsnDirectConn *dc;
-- MsnUser *user;
--
-- if (!purple_account_get_bool(session->account, "direct_connect", TRUE)) {
-- /* Don't attempt a direct connection if disabled. */
-- msn_slpcall_session_init(slpcall);
-- return;
-- }
--
-- if (slpcall->slplink->dc != NULL) {
-- /* If we already have an established direct connection
-- * then just start the transfer.
-- */
-- msn_slpcall_session_init(slpcall);
-- return;
-- }
--
-- user = msn_userlist_find_user(session->userlist,
-- slpcall->slplink->remote_user);
-- if (!user || !(user->clientid & 0xF0000000)) {
-- /* Just start a normal SB transfer. */
-- msn_slpcall_session_init(slpcall);
-- return;
-- }
--
-- /* Try direct file transfer by sending a second INVITE */
-- dc = msn_dc_new(slpcall);
-- g_free(slpcall->branch);
-- slpcall->branch = rand_guid();
--
-- dc->listen_data = purple_network_listen_range(
-- 0, 0,
-- SOCK_STREAM,
-- msn_dc_listen_socket_created_cb,
-- dc
-- );
--
-- header = g_strdup_printf(
-- "INVITE MSNMSGR:%s MSNSLP/1.0",
-- slpcall->slplink->remote_user
-- );
--
-- if (dc->nonce_type == DC_NONCE_SHA1)
-- nonce = g_strdup_printf("Hashed-Nonce: {%s}\r\n", dc->nonce_hash);
--
-- if (dc->listen_data == NULL) {
-- /* Listen socket creation failed */
-- purple_debug_info("msn", "got_ok: listening failed\n");
--
-- content = g_strdup_printf(
-- "Bridges: TCPv1\r\n"
-- "NetID: %u\r\n"
-- "Conn-Type: IP-Restrict-NAT\r\n"
-- "UPnPNat: false\r\n"
-- "ICF: false\r\n"
-- "%s"
-- "\r\n",
--
-- rand() % G_MAXUINT32,
-- nonce ? nonce : ""
-- );
--
-- } else {
-- /* Listen socket created successfully. */
-- purple_debug_info("msn", "got_ok: listening socket created\n");
--
-- content = g_strdup_printf(
-- "Bridges: TCPv1\r\n"
-- "NetID: 0\r\n"
-- "Conn-Type: Direct-Connect\r\n"
-- "UPnPNat: false\r\n"
-- "ICF: false\r\n"
-- "%s"
-- "\r\n",
--
-- nonce ? nonce : ""
-- );
-- }
--
-- msg = msn_slpmsg_sip_new(
-- slpcall,
-- 0,
-- header,
-- slpcall->branch,
-- "application/x-msnmsgr-transreqbody",
-- content
-- );
-- msg->info = "DC INVITE";
-- msg->text_body = TRUE;
-- g_free(nonce);
-- g_free(header);
-- g_free(content);
--
-- msn_slplink_queue_slpmsg(slpcall->slplink, msg);
-- }
-- else if (!strcmp(type, "application/x-msnmsgr-transreqbody"))
-- {
-- /* Do we get this? */
-- purple_debug_info("msn", "OK with transreqbody\n");
-- }
-- else if (!strcmp(type, "application/x-msnmsgr-transrespbody"))
-- {
-- msn_slp_process_transresp(slpcall, content);
-- }
--}
--
--static void
--got_error(MsnSlpCall *slpcall,
-- const char *error, const char *type, const char *content)
--{
-- /* It's not valid. Kill this off. */
-- purple_debug_error("msn", "Received non-OK result: %s\n",
-- error ? error : "Unknown");
--
-- if (type && !strcmp(type, "application/x-msnmsgr-transreqbody")) {
-- MsnDirectConn *dc = slpcall->slplink->dc;
-- if (dc) {
-- msn_dc_fallback_to_sb(dc);
-- return;
-- }
-- }
--
-- slpcall->wasted = TRUE;
--}
--
--static MsnSlpCall *
--msn_slp_sip_recv(MsnSlpLink *slplink, const char *body)
--{
-- MsnSlpCall *slpcall;
--
-- if (body == NULL)
-- {
-- purple_debug_warning("msn", "received bogus message\n");
-- return NULL;
-- }
--
-- if (!strncmp(body, "INVITE", strlen("INVITE")))
-- {
-- /* This is an INVITE request */
-- char *branch;
-- char *call_id;
-- char *content;
-- char *content_type;
--
-- /* From: <msnmsgr:buddy@hotmail.com> */
--#if 0
-- slpcall->remote_user = get_token(body, "From: <msnmsgr:", ">\r\n");
--#endif
--
-- branch = get_token(body, ";branch={", "}");
--
-- call_id = get_token(body, "Call-ID: {", "}");
--
--#if 0
-- long content_len = -1;
--
-- temp = get_token(body, "Content-Length: ", "\r\n");
-- if (temp != NULL)
-- content_len = atoi(temp);
-- g_free(temp);
--#endif
-- content_type = get_token(body, "Content-Type: ", "\r\n");
--
-- content = get_token(body, "\r\n\r\n", NULL);
--
-- slpcall = NULL;
-- if (branch && call_id)
-- {
-- slpcall = msn_slplink_find_slp_call(slplink, call_id);
-- if (slpcall)
-- {
-- g_free(slpcall->branch);
-- slpcall->branch = g_strdup(branch);
-- got_invite(slpcall, branch, content_type, content);
-- }
-- else if (content_type && content)
-- {
-- slpcall = msn_slpcall_new(slplink);
-- slpcall->id = g_strdup(call_id);
-- got_invite(slpcall, branch, content_type, content);
-- }
-- }
--
-- g_free(call_id);
-- g_free(branch);
-- g_free(content_type);
-- g_free(content);
-- }
-- else if (!strncmp(body, "MSNSLP/1.0 ", strlen("MSNSLP/1.0 ")))
-- {
-- /* This is a response */
-- char *content;
-- char *content_type;
-- /* Make sure this is "OK" */
-- const char *status = body + strlen("MSNSLP/1.0 ");
-- char *call_id;
--
-- call_id = get_token(body, "Call-ID: {", "}");
-- slpcall = msn_slplink_find_slp_call(slplink, call_id);
-- g_free(call_id);
--
-- g_return_val_if_fail(slpcall != NULL, NULL);
--
-- content_type = get_token(body, "Content-Type: ", "\r\n");
--
-- content = get_token(body, "\r\n\r\n", NULL);
--
-- if (strncmp(status, "200 OK", 6))
-- {
-- char *error = NULL;
-- const char *c;
--
-- /* Eww */
-- if ((c = strchr(status, '\r')) || (c = strchr(status, '\n')) ||
-- (c = strchr(status, '\0')))
-- {
-- size_t len = c - status;
-- error = g_strndup(status, len);
-- }
--
-- got_error(slpcall, error, content_type, content);
-- g_free(error);
--
-- } else {
-- /* Everything's just dandy */
-- got_ok(slpcall, content_type, content);
-- }
--
-- g_free(content_type);
-- g_free(content);
-- }
-- else if (!strncmp(body, "BYE", strlen("BYE")))
-- {
-- /* This is a BYE request */
-- char *call_id;
--
-- call_id = get_token(body, "Call-ID: {", "}");
-- slpcall = msn_slplink_find_slp_call(slplink, call_id);
-- g_free(call_id);
--
-- if (slpcall != NULL)
-- slpcall->wasted = TRUE;
--
-- /* msn_slpcall_destroy(slpcall); */
-- }
-- else
-- slpcall = NULL;
--
-- return slpcall;
--}
--
--MsnSlpCall *
--msn_slp_process_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
--{
-- MsnSlpCall *slpcall;
-- const guchar *body;
-- gsize body_len;
-- guint32 session_id;
-- guint32 flags;
--
-- slpcall = NULL;
-- body = slpmsg->buffer;
-- body_len = msn_p2p_info_get_offset(slpmsg->p2p_info);
--
-- session_id = msn_p2p_info_get_session_id(slpmsg->p2p_info);
-- flags = msn_p2p_info_get_flags(slpmsg->p2p_info);
--
-- if (flags == P2P_NO_FLAG || flags == P2P_WLM2009_COMP)
-- {
-- char *body_str;
--
-- if (session_id == 64)
-- {
-- /* This is for handwritten messages (Ink) */
-- GError *error = NULL;
-- gsize bytes_read, bytes_written;
--
-- body_str = g_convert((const gchar *)body, body_len / 2,
-- "UTF-8", "UTF-16LE",
-- &bytes_read, &bytes_written, &error);
-- body_len -= bytes_read + 2;
-- body += bytes_read + 2;
-- if (body_str == NULL
-- || body_len <= 0
-- || strstr(body_str, "image/gif") == NULL)
-- {
-- if (error != NULL) {
-- purple_debug_error("msn",
-- "Unable to convert Ink header from UTF-16 to UTF-8: %s\n",
-- error->message);
-- g_error_free(error);
-- }
-- else
-- purple_debug_error("msn",
-- "Received Ink in unknown format\n");
-- g_free(body_str);
-- return NULL;
-- }
-- g_free(body_str);
--
-- body_str = g_convert((const gchar *)body, body_len / 2,
-- "UTF-8", "UTF-16LE",
-- &bytes_read, &bytes_written, &error);
-- if (!body_str)
-- {
-- if (error != NULL) {
-- purple_debug_error("msn",
-- "Unable to convert Ink body from UTF-16 to UTF-8: %s\n",
-- error->message);
-- g_error_free(error);
-- }
-- else
-- purple_debug_error("msn",
-- "Received Ink in unknown format\n");
-- return NULL;
-- }
--
-- msn_switchboard_show_ink(slpmsg->slplink->swboard,
-- slplink->remote_user,
-- body_str);
-- }
-- else
-- {
-- body_str = g_strndup((const char *)body, body_len);
-- slpcall = msn_slp_sip_recv(slplink, body_str);
-- }
-- g_free(body_str);
-- }
-- else if (msn_p2p_msg_is_data(slpmsg->p2p_info))
-- {
-- slpcall = msn_slplink_find_slp_call_with_session_id(slplink, session_id);
--
-- if (slpcall != NULL)
-- {
-- if (slpcall->timer) {
-- purple_timeout_remove(slpcall->timer);
-- slpcall->timer = 0;
-- }
--
-- if (slpcall->cb)
-- slpcall->cb(slpcall, body, body_len);
--
-- slpcall->wasted = TRUE;
-- }
-- }
-- else if (msn_p2p_info_is_ack(slpmsg->p2p_info))
-- {
-- /* Acknowledgement of previous message. Don't do anything currently. */
-- }
-- else
-- purple_debug_warning("msn", "Unprocessed SLP message with flags 0x%04x\n",
-- flags);
--
-- return slpcall;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slpcall.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpcall.h
---- pidgin-2.10.7/libpurple/protocols/msn/slpcall.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpcall.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,98 +0,0 @@
--/**
-- * @file slpcall.h SLP Call functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_SLPCALL_H
--#define MSN_SLPCALL_H
--
--typedef struct _MsnSlpCall MsnSlpCall;
--
--typedef enum
--{
-- MSN_SLPCALL_ANY,
-- MSN_SLPCALL_DC
--} MsnSlpCallType;
--
--#include "internal.h"
--
--#include "slplink.h"
--
--/* The official client seems to timeout slp calls after 5 minutes */
--#define MSN_SLPCALL_TIMEOUT 300
--
--struct _MsnSlpCall
--{
-- /* Our parent slplink */
-- MsnSlpLink *slplink;
--
-- MsnSlpCallType type;
--
-- /* Call-ID */
-- char *id;
-- char *branch;
--
-- long session_id;
-- long app_id;
--
-- gboolean pending; /**< A flag that states if we should wait for this
-- slpcall to start and do not time out. */
-- gboolean progress; /**< A flag that states if there has been progress since
-- the last time out. */
-- gboolean wasted; /**< A flag that states if this slpcall is going to be
-- destroyed. */
-- gboolean started; /**< A flag that states if this slpcall's session has
-- been initiated. */
--
-- gboolean wait_for_socket;
--
-- void (*progress_cb)(MsnSlpCall *slpcall,
-- gsize total_length, gsize len);
-- void (*session_init_cb)(MsnSlpCall *slpcall);
--
-- /* Can be checksum, or smile */
-- char *data_info;
--
-- PurpleXfer *xfer;
-- union {
-- GByteArray *incoming_data;
-- struct {
-- gsize len;
-- const guchar *data;
-- } outgoing;
-- } u;
-- MsnSlpMessage *xfer_msg; /* A dirty hack */
--
-- MsnSlpCb cb;
-- void (*end_cb)(MsnSlpCall *slpcall, MsnSession *session);
--
-- guint timer;
--};
--
--MsnSlpCall *msn_slpcall_new(MsnSlpLink *slplink);
--void msn_slpcall_init(MsnSlpCall *slpcall, MsnSlpCallType type);
--void msn_slpcall_session_init(MsnSlpCall *slpcall);
--void msn_slpcall_destroy(MsnSlpCall *slpcall);
--void msn_slpcall_invite(MsnSlpCall *slpcall, const char *euf_guid,
-- MsnP2PAppId app_id, const char *context);
--void msn_slpcall_close(MsnSlpCall *slpcall);
--
--#endif /* MSN_SLPCALL_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slp.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/slp.h
---- pidgin-2.10.7/libpurple/protocols/msn/slp.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slp.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,51 +0,0 @@
--/**
-- * @file slp.h MSNSLP support
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_SLP_H
--#define MSN_SLP_H
--
--#include "internal.h"
--#include "ft.h"
--
--#include "session.h"
--#include "slpcall.h"
--#include "slplink.h"
--#include "user.h"
--
--void
--msn_slp_send_ok(MsnSlpCall *slpcall, const char *branch,
-- const char *type, const char *content);
--
--void
--msn_slp_send_decline(MsnSlpCall *slpcall, const char *branch,
-- const char *type, const char *content);
--
--
--void send_bye(MsnSlpCall *slpcall, const char *type);
--
--
--void msn_request_user_display(MsnUser *user);
--
--void msn_request_ft(PurpleXfer *xfer);
--
--#endif /* MSN_SLP_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slplink.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/slplink.c
---- pidgin-2.10.7/libpurple/protocols/msn/slplink.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slplink.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,646 +0,0 @@
--/**
-- * @file slplink.c MSNSLP Link support
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "msn.h"
--#include "slplink.h"
--#include "slpmsg_part.h"
--
--#include "sbconn.h"
--#include "switchboard.h"
--#include "slp.h"
--#include "p2p.h"
--
--#ifdef MSN_DEBUG_SLP_FILES
--static int m_sc = 0;
--static int m_rc = 0;
--
--static void
--debug_part_to_file(MsnSlpMessage *msg, gboolean send)
--{
-- char *tmp;
-- char *dir;
-- char *data;
-- int c;
-- gsize data_size;
--
-- dir = send ? "send" : "recv";
-- c = send ? m_sc++ : m_rc++;
-- tmp = g_strdup_printf("%s/msntest/%s/%03d", purple_user_dir(), dir, c);
-- data = msn_slpmsg_serialize(msg, &data_size);
-- if (!purple_util_write_data_to_file_absolute(tmp, data, data_size))
-- {
-- purple_debug_error("msn", "could not save debug file\n");
-- }
-- g_free(tmp);
--}
--#endif
--
--/**************************************************************************
-- * Main
-- **************************************************************************/
--
--static MsnSlpLink *
--msn_slplink_new(MsnSession *session, const char *username)
--{
-- MsnSlpLink *slplink;
--
-- g_return_val_if_fail(session != NULL, NULL);
--
-- slplink = g_new0(MsnSlpLink, 1);
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "slplink_new: slplink(%p)\n", slplink);
--
-- slplink->session = session;
-- slplink->slp_seq_id = rand() % 0xFFFFFF00 + 4;
--
-- slplink->remote_user = g_strdup(username);
-- slplink->p2p_version = MSN_P2P_VERSION_ONE;
--
-- slplink->slp_msg_queue = g_queue_new();
--
-- session->slplinks =
-- g_list_append(session->slplinks, slplink);
--
-- return msn_slplink_ref(slplink);
--}
--
--static void
--msn_slplink_destroy(MsnSlpLink *slplink)
--{
-- MsnSession *session;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "slplink_destroy: slplink(%p)\n", slplink);
--
-- if (slplink->swboard != NULL) {
-- slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink);
-- slplink->swboard = NULL;
-- }
--
-- session = slplink->session;
--
-- if (slplink->dc != NULL) {
-- slplink->dc->slplink = NULL;
-- msn_dc_destroy(slplink->dc);
-- slplink->dc = NULL;
-- }
--
-- while (slplink->slp_calls != NULL)
-- msn_slpcall_destroy(slplink->slp_calls->data);
--
-- g_queue_free(slplink->slp_msg_queue);
--
-- session->slplinks =
-- g_list_remove(session->slplinks, slplink);
--
-- g_free(slplink->remote_user);
--
-- g_free(slplink);
--}
--
--MsnSlpLink *
--msn_slplink_ref(MsnSlpLink *slplink)
--{
-- g_return_val_if_fail(slplink != NULL, NULL);
--
-- slplink->refs++;
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "slplink ref (%p)[%d]\n", slplink, slplink->refs);
--
-- return slplink;
--}
--
--void
--msn_slplink_unref(MsnSlpLink *slplink)
--{
-- g_return_if_fail(slplink != NULL);
--
-- slplink->refs--;
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "slplink unref (%p)[%d]\n", slplink, slplink->refs);
--
-- if (slplink->refs == 0)
-- msn_slplink_destroy(slplink);
--}
--
--MsnSlpLink *
--msn_session_find_slplink(MsnSession *session, const char *who)
--{
-- GList *l;
--
-- for (l = session->slplinks; l != NULL; l = l->next)
-- {
-- MsnSlpLink *slplink;
--
-- slplink = l->data;
--
-- if (!strcmp(slplink->remote_user, who))
-- return slplink;
-- }
--
-- return NULL;
--}
--
--MsnSlpLink *
--msn_session_get_slplink(MsnSession *session, const char *username)
--{
-- MsnSlpLink *slplink;
--
-- g_return_val_if_fail(session != NULL, NULL);
-- g_return_val_if_fail(username != NULL, NULL);
--
-- slplink = msn_session_find_slplink(session, username);
--
-- if (slplink == NULL)
-- slplink = msn_slplink_new(session, username);
--
-- return slplink;
--}
--
--void
--msn_slplink_add_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall)
--{
-- if (slplink->swboard != NULL)
-- slplink->swboard->flag |= MSN_SB_FLAG_FT;
--
-- slplink->slp_calls = g_list_append(slplink->slp_calls, slpcall);
--
-- /*
-- if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED)
-- msn_dc_ref(slplink->dc);
-- */
--}
--
--void
--msn_slplink_remove_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall)
--{
-- /*
-- if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED)
-- msn_dc_unref(slplink->dc);
-- */
--
-- slplink->slp_calls = g_list_remove(slplink->slp_calls, slpcall);
--
-- /* The slplink has no slpcalls in it, release it from MSN_SB_FLAG_FT.
-- * If nothing else is using it then this might cause swboard to be
-- * destroyed. */
-- if (slplink->slp_calls == NULL && slplink->swboard != NULL) {
-- slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink);
-- msn_switchboard_release(slplink->swboard, MSN_SB_FLAG_FT);
-- slplink->swboard = NULL;
-- }
--
-- if (slplink->dc != NULL) {
-- if ((slplink->dc->state != DC_STATE_ESTABLISHED && slplink->dc->slpcall == slpcall)
-- || (slplink->slp_calls == NULL)) {
-- /* The DC is not established and its corresponding slpcall is dead,
-- * or the slplink has no slpcalls in it and no longer needs the DC.
-- */
-- slplink->dc->slplink = NULL;
-- msn_dc_destroy(slplink->dc);
-- slplink->dc = NULL;
-- }
-- }
--}
--
--MsnSlpCall *
--msn_slplink_find_slp_call(MsnSlpLink *slplink, const char *id)
--{
-- GList *l;
-- MsnSlpCall *slpcall;
--
-- if (!id)
-- return NULL;
--
-- for (l = slplink->slp_calls; l != NULL; l = l->next)
-- {
-- slpcall = l->data;
--
-- if (slpcall->id && !strcmp(slpcall->id, id))
-- return slpcall;
-- }
--
-- return NULL;
--}
--
--MsnSlpCall *
--msn_slplink_find_slp_call_with_session_id(MsnSlpLink *slplink, long id)
--{
-- GList *l;
-- MsnSlpCall *slpcall;
--
-- for (l = slplink->slp_calls; l != NULL; l = l->next)
-- {
-- slpcall = l->data;
--
-- if (slpcall->session_id == id)
-- return slpcall;
-- }
--
-- return NULL;
--}
--
--MsnP2PVersion
--msn_slplink_get_p2p_version(MsnSlpLink *slplink)
--{
-- return slplink->p2p_version;
--}
--
--static void
--msn_slplink_send_part(MsnSlpLink *slplink, MsnSlpMessagePart *part)
--{
-- if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED)
-- {
-- msn_dc_enqueue_part(slplink->dc, part);
-- }
-- else
-- {
-- msn_sbconn_send_part(slplink, part);
-- }
--}
--
--void
--msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
--{
-- MsnSlpMessagePart *part;
-- MsnP2PInfo *info;
-- long long real_size;
-- size_t len = 0;
-- guint64 offset;
--
-- /* Maybe we will want to create a new msg for this slpmsg instead of
-- * reusing the same one all the time. */
-- info = slpmsg->p2p_info;
-- part = msn_slpmsgpart_new(msn_p2p_info_dup(info));
-- part->ack_data = slpmsg;
--
-- real_size = msn_p2p_info_is_ack(info) ? 0 : slpmsg->size;
--
-- offset = msn_p2p_info_get_offset(info);
-- if (offset < real_size)
-- {
-- if (slpmsg->slpcall && slpmsg->slpcall->xfer && purple_xfer_get_type(slpmsg->slpcall->xfer) == PURPLE_XFER_SEND &&
-- purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
-- {
-- len = MIN(MSN_SBCONN_MAX_SIZE, slpmsg->slpcall->u.outgoing.len);
-- msn_slpmsgpart_set_bin_data(part, slpmsg->slpcall->u.outgoing.data, len);
-- }
-- else
-- {
-- len = slpmsg->size - offset;
--
-- if (len > MSN_SBCONN_MAX_SIZE)
-- len = MSN_SBCONN_MAX_SIZE;
--
-- msn_slpmsgpart_set_bin_data(part, slpmsg->buffer + offset, len);
-- }
--
-- msn_p2p_info_set_length(slpmsg->p2p_info, len);
-- }
--
--#if 0
-- /* TODO: port this function to SlpMessageParts */
-- if (purple_debug_is_verbose())
-- msn_message_show_readable(msg, slpmsg->info, slpmsg->text_body);
--#endif
--
--#ifdef MSN_DEBUG_SLP_FILES
-- debug_part_to_file(slpmsg, TRUE);
--#endif
--
-- slpmsg->parts = g_list_append(slpmsg->parts, part);
-- msn_slplink_send_part(slplink, part);
--
--
-- if (msn_p2p_msg_is_data(info) && slpmsg->slpcall != NULL)
-- {
-- slpmsg->slpcall->progress = TRUE;
--
-- if (slpmsg->slpcall->progress_cb != NULL)
-- {
-- slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size,
-- len);
-- }
-- }
--
-- /* slpmsg->offset += len; */
--}
--
--static void
--msn_slplink_release_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
--{
-- MsnP2PInfo *info;
-- guint32 flags;
--
-- info = slpmsg->p2p_info;
--
-- flags = msn_p2p_info_get_flags(info);
-- if (flags == P2P_NO_FLAG)
-- {
-- msn_p2p_info_set_ack_id(info, rand() % 0xFFFFFF00);
-- }
-- else if (msn_p2p_msg_is_data(info))
-- {
-- MsnSlpCall *slpcall;
-- slpcall = slpmsg->slpcall;
--
-- g_return_if_fail(slpcall != NULL);
-- msn_p2p_info_set_session_id(info, slpcall->session_id);
-- msn_p2p_info_set_app_id(info, slpcall->app_id);
-- msn_p2p_info_set_ack_id(info, rand() % 0xFFFFFF00);
-- }
--
-- msn_p2p_info_set_id(info, slpmsg->id);
--
-- msn_p2p_info_set_total_size(info, slpmsg->size);
--
-- msn_slplink_send_msgpart(slplink, slpmsg);
--}
--
--void
--msn_slplink_queue_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
--{
-- g_return_if_fail(slpmsg != NULL);
--
-- slpmsg->id = slplink->slp_seq_id++;
--
-- g_queue_push_tail(slplink->slp_msg_queue, slpmsg);
--}
--
--void
--msn_slplink_send_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
--{
-- slpmsg->id = slplink->slp_seq_id++;
--
-- msn_slplink_release_slpmsg(slplink, slpmsg);
--}
--
--void
--msn_slplink_send_queued_slpmsgs(MsnSlpLink *slplink)
--{
-- MsnSlpMessage *slpmsg;
--
-- /* Send the queued msgs in the order they were created */
-- while ((slpmsg = g_queue_pop_head(slplink->slp_msg_queue)) != NULL)
-- {
-- msn_slplink_release_slpmsg(slplink, slpmsg);
-- }
--}
--
--static void
--msn_slplink_send_ack(MsnSlpLink *slplink, MsnP2PInfo *info)
--{
-- MsnSlpMessage *slpmsg = msn_slpmsg_ack_new(slplink, info);
--
-- msn_slplink_send_slpmsg(slplink, slpmsg);
-- msn_slpmsg_destroy(slpmsg);
--}
--
--static MsnSlpMessage *
--msn_slplink_message_find(MsnSlpLink *slplink, long session_id, long id)
--{
-- GList *e;
--
-- for (e = slplink->slp_msgs; e != NULL; e = e->next)
-- {
-- MsnSlpMessage *slpmsg = e->data;
--
-- if ((msn_p2p_info_get_session_id(slpmsg->p2p_info) == session_id) && (slpmsg->id == id))
-- return slpmsg;
-- }
--
-- return NULL;
--}
--
--static MsnSlpMessage *
--init_first_msg(MsnSlpLink *slplink, MsnP2PInfo *info)
--{
-- MsnSlpMessage *slpmsg;
-- guint32 session_id;
--
-- slpmsg = msn_slpmsg_new(slplink, NULL);
-- slpmsg->id = msn_p2p_info_get_id(info);
-- session_id = msn_p2p_info_get_session_id(info);
-- slpmsg->size = msn_p2p_info_get_total_size(info);
-- msn_p2p_info_init_first(slpmsg->p2p_info, info);
--
-- if (session_id)
-- {
-- slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, session_id);
-- if (slpmsg->slpcall != NULL)
-- {
-- if (msn_p2p_msg_is_data(info))
-- {
-- PurpleXfer *xfer = slpmsg->slpcall->xfer;
-- if (xfer != NULL)
-- {
-- slpmsg->ft = TRUE;
-- slpmsg->slpcall->xfer_msg = slpmsg;
--
-- purple_xfer_ref(xfer);
-- purple_xfer_start(xfer, -1, NULL, 0);
--
-- if (xfer->data == NULL) {
-- purple_xfer_unref(xfer);
-- msn_slpmsg_destroy(slpmsg);
-- g_return_val_if_reached(NULL);
-- } else {
-- purple_xfer_unref(xfer);
-- }
-- }
-- }
-- }
-- }
-- if (!slpmsg->ft && slpmsg->size)
-- {
-- slpmsg->buffer = g_try_malloc(slpmsg->size);
-- if (slpmsg->buffer == NULL)
-- {
-- purple_debug_error("msn", "Failed to allocate buffer for slpmsg\n");
-- msn_slpmsg_destroy(slpmsg);
-- return NULL;
-- }
-- }
--
-- return slpmsg;
--}
--
--static void
--process_complete_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg, MsnP2PInfo *info)
--{
-- MsnSlpCall *slpcall;
--
-- slpcall = msn_slp_process_msg(slplink, slpmsg);
--
-- if (slpcall == NULL) {
-- msn_slpmsg_destroy(slpmsg);
-- return;
-- }
--
-- purple_debug_info("msn", "msn_slplink_process_msg: slpmsg complete\n");
--
-- if (msn_p2p_info_require_ack(slpmsg->p2p_info))
-- {
-- /* Release all the messages and send the ACK */
--
-- if (slpcall->wait_for_socket) {
-- /*
-- * Save ack for later because we have to send
-- * a 200 OK message to the previous direct connect
-- * invitation before ACK but the listening socket isn't
-- * created yet.
-- */
-- purple_debug_info("msn", "msn_slplink_process_msg: save ACK\n");
--
-- slpcall->slplink->dc->prev_ack = msn_slpmsg_ack_new(slplink, info);
-- } else if (!slpcall->wasted) {
-- purple_debug_info("msn", "msn_slplink_process_msg: send ACK\n");
--
-- msn_slplink_send_ack(slplink, info);
-- msn_slplink_send_queued_slpmsgs(slplink);
-- }
-- }
--
-- msn_slpmsg_destroy(slpmsg);
--
-- if (!slpcall->wait_for_socket && slpcall->wasted)
-- msn_slpcall_destroy(slpcall);
--}
--
--static void
--slpmsg_add_part(MsnSlpMessage *slpmsg, MsnSlpMessagePart *part)
--{
-- if (slpmsg->ft) {
-- slpmsg->slpcall->u.incoming_data =
-- g_byte_array_append(slpmsg->slpcall->u.incoming_data, (const guchar *)part->buffer, part->size);
-- purple_xfer_prpl_ready(slpmsg->slpcall->xfer);
-- }
-- else if (slpmsg->size && slpmsg->buffer) {
-- guint64 offset = msn_p2p_info_get_offset(part->info);
-- if (G_MAXSIZE - part->size < offset
-- || (offset + part->size) > slpmsg->size
-- || msn_p2p_info_get_offset(slpmsg->p2p_info) != offset) {
-- purple_debug_error("msn",
-- "Oversized slpmsg - msgsize=%lld offset=%" G_GUINT64_FORMAT " len=%" G_GSIZE_FORMAT "\n",
-- slpmsg->size, offset, part->size);
-- g_return_if_reached();
-- } else {
-- memcpy(slpmsg->buffer + offset, part->buffer, part->size);
-- msn_p2p_info_set_offset(slpmsg->p2p_info, offset + part->size);
-- }
-- }
--}
--
--void
--msn_slplink_process_msg(MsnSlpLink *slplink, MsnSlpMessagePart *part)
--{
-- MsnSlpMessage *slpmsg;
-- MsnP2PInfo *info;
--
-- info = part->info;
--
-- if (!msn_p2p_info_is_valid(info))
-- {
-- /* We seem to have received a bad header */
-- purple_debug_warning("msn", "Total size listed in SLP binary header "
-- "was less than length of this particular message. This "
-- "should not happen. Dropping message.\n");
-- return;
-- }
--
-- if (msn_p2p_info_is_first(info))
-- slpmsg = init_first_msg(slplink, info);
-- else {
-- guint32 session_id, id;
-- session_id = msn_p2p_info_get_session_id(info);
-- id = msn_p2p_info_get_id(info);
-- slpmsg = msn_slplink_message_find(slplink, session_id, id);
-- if (slpmsg == NULL)
-- {
-- /* Probably the transfer was cancelled */
-- purple_debug_error("msn", "Couldn't find slpmsg\n");
-- return;
-- }
-- }
--
-- slpmsg_add_part(slpmsg, part);
--
-- if (msn_p2p_msg_is_data(slpmsg->p2p_info) && slpmsg->slpcall != NULL)
-- {
-- slpmsg->slpcall->progress = TRUE;
--
-- if (slpmsg->slpcall->progress_cb != NULL)
-- {
-- slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size,
-- part->size);
-- }
-- }
--
--#if 0
-- if (slpmsg->buffer == NULL)
-- return;
--#endif
--
-- /* All the pieces of the slpmsg have been received */
-- if (msn_p2p_info_is_final(info))
-- process_complete_msg(slplink, slpmsg, info);
--
-- /* NOTE: The slpmsg will be destroyed in process_complete_msg or left in
-- the slplink until fully received. Don't free it here!
-- */
--}
--
--void
--msn_slplink_request_object(MsnSlpLink *slplink,
-- const char *info,
-- MsnSlpCb cb,
-- MsnSlpEndCb end_cb,
-- const MsnObject *obj)
--{
-- MsnSlpCall *slpcall;
-- char *msnobj_data;
-- char *msnobj_base64;
--
-- g_return_if_fail(slplink != NULL);
-- g_return_if_fail(obj != NULL);
--
-- msnobj_data = msn_object_to_string(obj);
-- msnobj_base64 = purple_base64_encode((const guchar *)msnobj_data, strlen(msnobj_data));
-- g_free(msnobj_data);
--
-- slpcall = msn_slpcall_new(slplink);
-- msn_slpcall_init(slpcall, MSN_SLPCALL_ANY);
--
-- slpcall->data_info = g_strdup(info);
-- slpcall->cb = cb;
-- slpcall->end_cb = end_cb;
--
-- msn_slpcall_invite(slpcall, MSN_OBJ_GUID, P2P_APPID_OBJ, msnobj_base64);
--
-- g_free(msnobj_base64);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slplink.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/slplink.h
---- pidgin-2.10.7/libpurple/protocols/msn/slplink.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slplink.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,98 +0,0 @@
--/**
-- * @file slplink.h MSNSLP Link support
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_SLPLINK_H
--#define MSN_SLPLINK_H
--
--typedef struct _MsnSlpLink MsnSlpLink;
--
--#include "directconn.h"
--#include "session.h"
--#include "slpcall.h"
--#include "slpmsg.h"
--#include "switchboard.h"
--
--typedef void (*MsnSlpCb)(MsnSlpCall *slpcall,
-- const guchar *data, gsize size);
--typedef void (*MsnSlpEndCb)(MsnSlpCall *slpcall, MsnSession *session);
--
--struct _MsnSlpLink
--{
-- MsnSession *session;
-- MsnSwitchBoard *swboard;
-- MsnDirectConn *dc;
--
-- guint refs;
--
-- char *remote_user;
-- MsnP2PVersion p2p_version;
--
-- int slp_seq_id;
--
-- GList *slp_calls;
-- GList *slp_msgs;
--
-- GQueue *slp_msg_queue;
--};
--
--MsnSlpLink *msn_slplink_ref(MsnSlpLink *slplink);
--void msn_slplink_unref(MsnSlpLink *slplink);
--
--/**
-- * @return An MsnSlpLink for the given user, or NULL if there is no
-- * existing MsnSlpLink.
-- */
--MsnSlpLink *msn_session_find_slplink(MsnSession *session,
-- const char *who);
--
--/**
-- * @return An MsnSlpLink for the given user. One will be created if
-- * it does not already exist.
-- */
--MsnSlpLink *msn_session_get_slplink(MsnSession *session, const char *username);
--
--void msn_slplink_add_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall);
--void msn_slplink_remove_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall);
--MsnSlpCall *msn_slplink_find_slp_call(MsnSlpLink *slplink,
-- const char *id);
--MsnSlpCall *msn_slplink_find_slp_call_with_session_id(MsnSlpLink *slplink, long id);
--MsnP2PVersion msn_slplink_get_p2p_version(MsnSlpLink *slplink);
--
--void msn_slplink_queue_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);
--void msn_slplink_send_slpmsg(MsnSlpLink *slplink,
-- MsnSlpMessage *slpmsg);
--void msn_slplink_send_queued_slpmsgs(MsnSlpLink *slplink);
--void msn_slplink_process_msg(MsnSlpLink *slplink, MsnSlpMessagePart *part);
--
--/* Only exported for msn_xfer_write */
--void msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);
--
--void msn_slplink_request_object(MsnSlpLink *slplink,
-- const char *info,
-- MsnSlpCb cb,
-- MsnSlpEndCb end_cb,
-- const MsnObject *obj);
--
--MsnSlpCall *msn_slp_process_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);
--
--#endif /* MSN_SLPLINK_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slpmsg.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpmsg.c
---- pidgin-2.10.7/libpurple/protocols/msn/slpmsg.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpmsg.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,309 +0,0 @@
--/**
-- * @file slpmsg.c SLP Message functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "slpmsg.h"
--#include "slpmsg_part.h"
--#include "slplink.h"
--
--/**************************************************************************
-- * SLP Message
-- **************************************************************************/
--
--MsnSlpMessage *
--msn_slpmsg_new(MsnSlpLink *slplink, MsnSlpCall *slpcall)
--{
-- MsnSlpMessage *slpmsg;
-- MsnP2PVersion p2p;
--
-- g_return_val_if_fail(slplink != NULL, NULL);
--
-- slpmsg = g_new0(MsnSlpMessage, 1);
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "slpmsg new (%p)\n", slpmsg);
--
-- msn_slpmsg_set_slplink(slpmsg, slplink);
-- slpmsg->slpcall = slpcall;
--
-- p2p = msn_slplink_get_p2p_version(slplink);
-- slpmsg->p2p_info = msn_p2p_info_new(p2p);
--
-- return slpmsg;
--}
--
--void
--msn_slpmsg_destroy(MsnSlpMessage *slpmsg)
--{
-- MsnSlpLink *slplink;
-- GList *cur;
--
-- g_return_if_fail(slpmsg != NULL);
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "slpmsg destroy (%p)\n", slpmsg);
--
-- slplink = slpmsg->slplink;
--
-- purple_imgstore_unref(slpmsg->img);
--
-- /* We don't want to free the data of the PurpleStoredImage,
-- * but to avoid code duplication, it's sharing buffer. */
-- if (slpmsg->img == NULL)
-- g_free(slpmsg->buffer);
--
-- for (cur = slpmsg->parts; cur != NULL; cur = g_list_delete_link(cur, cur))
-- {
-- /* Something is pointing to this slpmsg, so we should remove that
-- * pointer to prevent a crash. */
-- /* Ex: a user goes offline and after that we receive an ACK */
--
-- MsnSlpMessagePart *part = cur->data;
--
-- part->ack_cb = NULL;
-- part->nak_cb = NULL;
-- part->ack_data = NULL;
-- msn_slpmsgpart_unref(part);
-- }
--
-- slplink->slp_msgs = g_list_remove(slplink->slp_msgs, slpmsg);
--
-- msn_p2p_info_free(slpmsg->p2p_info);
--
-- g_free(slpmsg);
--}
--
--void
--msn_slpmsg_set_slplink(MsnSlpMessage *slpmsg, MsnSlpLink *slplink)
--{
-- g_return_if_fail(slplink != NULL);
--
-- slpmsg->slplink = slplink;
--
-- slplink->slp_msgs =
-- g_list_append(slplink->slp_msgs, slpmsg);
--}
--
--void
--msn_slpmsg_set_body(MsnSlpMessage *slpmsg, const char *body,
-- long long size)
--{
-- /* We can only have one data source at a time. */
-- g_return_if_fail(slpmsg->buffer == NULL);
-- g_return_if_fail(slpmsg->img == NULL);
-- g_return_if_fail(slpmsg->ft == FALSE);
--
-- if (body != NULL)
-- slpmsg->buffer = g_memdup(body, size);
-- else
-- slpmsg->buffer = g_new0(guchar, size);
--
-- slpmsg->size = size;
--}
--
--void
--msn_slpmsg_set_image(MsnSlpMessage *slpmsg, PurpleStoredImage *img)
--{
-- /* We can only have one data source at a time. */
-- g_return_if_fail(slpmsg->buffer == NULL);
-- g_return_if_fail(slpmsg->img == NULL);
-- g_return_if_fail(slpmsg->ft == FALSE);
--
-- slpmsg->img = purple_imgstore_ref(img);
-- slpmsg->buffer = (guchar *)purple_imgstore_get_data(img);
-- slpmsg->size = purple_imgstore_get_size(img);
--}
--
--
--MsnSlpMessage *
--msn_slpmsg_sip_new(MsnSlpCall *slpcall, int cseq,
-- const char *header, const char *branch,
-- const char *content_type, const char *content)
--{
-- MsnSlpLink *slplink;
-- PurpleAccount *account;
-- MsnSlpMessage *slpmsg;
-- char *body;
-- gsize body_len;
-- gsize content_len;
--
-- g_return_val_if_fail(slpcall != NULL, NULL);
-- g_return_val_if_fail(header != NULL, NULL);
--
-- slplink = slpcall->slplink;
-- account = slplink->session->account;
--
-- /* Let's remember that "content" should end with a 0x00 */
--
-- content_len = (content != NULL) ? strlen(content) + 1 : 0;
--
-- body = g_strdup_printf(
-- "%s\r\n"
-- "To: <msnmsgr:%s>\r\n"
-- "From: <msnmsgr:%s>\r\n"
-- "Via: MSNSLP/1.0/TLP ;branch={%s}\r\n"
-- "CSeq: %d\r\n"
-- "Call-ID: {%s}\r\n"
-- "Max-Forwards: 0\r\n"
-- "Content-Type: %s\r\n"
-- "Content-Length: %" G_GSIZE_FORMAT "\r\n"
-- "\r\n",
-- header,
-- slplink->remote_user,
-- purple_account_get_username(account),
-- branch,
-- cseq,
-- slpcall->id,
-- content_type,
-- content_len);
--
-- body_len = strlen(body);
--
-- if (content_len > 0)
-- {
-- body_len += content_len;
-- body = g_realloc(body, body_len);
-- g_strlcat(body, content, body_len);
-- }
--
-- slpmsg = msn_slpmsg_new(slplink, slpcall);
-- msn_slpmsg_set_body(slpmsg, body, body_len);
--
-- g_free(body);
--
-- return slpmsg;
--}
--
--MsnSlpMessage *msn_slpmsg_ack_new(MsnSlpLink *slplink, MsnP2PInfo *ack_info)
--{
-- MsnSlpMessage *slpmsg;
-- MsnP2PInfo *new_info;
--
-- slpmsg = msn_slpmsg_new(slplink, NULL);
--
-- new_info = slpmsg->p2p_info;
-- msn_p2p_info_create_ack(ack_info, new_info);
-- slpmsg->size = msn_p2p_info_get_total_size(ack_info);
-- slpmsg->info = "SLP ACK";
--
-- return slpmsg;
--}
--
--MsnSlpMessage *msn_slpmsg_obj_new(MsnSlpCall *slpcall, PurpleStoredImage *img)
--{
-- MsnSlpMessage *slpmsg;
--
-- slpmsg = msn_slpmsg_new(slpcall->slplink, slpcall);
-- msn_p2p_info_set_flags(slpmsg->p2p_info, P2P_MSN_OBJ_DATA);
-- slpmsg->info = "SLP DATA";
--
-- msn_slpmsg_set_image(slpmsg, img);
--
-- return slpmsg;
--}
--
--MsnSlpMessage *msn_slpmsg_dataprep_new(MsnSlpCall *slpcall)
--{
-- MsnSlpMessage *slpmsg;
--
-- slpmsg = msn_slpmsg_new(slpcall->slplink, slpcall);
--
-- msn_p2p_info_set_session_id(slpmsg->p2p_info, slpcall->session_id);
-- msn_slpmsg_set_body(slpmsg, NULL, 4);
-- slpmsg->info = "SLP DATA PREP";
--
-- return slpmsg;
--
--}
--
--MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, size_t size)
--{
-- MsnSlpMessage *slpmsg;
--
-- slpmsg = msn_slpmsg_new(slpcall->slplink, slpcall);
--
-- msn_p2p_info_set_flags(slpmsg->p2p_info, P2P_FILE_DATA);
-- slpmsg->info = "SLP FILE";
-- slpmsg->size = size;
--
-- return slpmsg;
--}
--
--char *msn_slpmsg_serialize(MsnSlpMessage *slpmsg, size_t *ret_size)
--{
-- char *header;
-- char *footer;
-- char *base;
-- char *tmp;
-- size_t header_size, footer_size;
--
-- header = msn_p2p_header_to_wire(slpmsg->p2p_info, &header_size);
-- footer = msn_p2p_footer_to_wire(slpmsg->p2p_info, &footer_size);
--
-- base = g_malloc(header_size + slpmsg->size + footer_size);
-- tmp = base;
--
-- /* Copy header */
-- memcpy(tmp, header, header_size);
-- tmp += header_size;
--
-- /* Copy body */
-- memcpy(tmp, slpmsg->buffer, slpmsg->size);
-- tmp += slpmsg->size;
--
-- /* Copy footer */
-- memcpy(tmp, footer, footer_size);
-- tmp += footer_size;
--
-- *ret_size = tmp - base;
--
-- g_free(header);
-- g_free(footer);
--
-- return base;
--}
--
--void msn_slpmsg_show_readable(MsnSlpMessage *slpmsg)
--{
-- GString *str;
--
-- str = g_string_new(NULL);
--
-- msn_p2p_info_to_string(slpmsg->p2p_info, str);
--
-- if (purple_debug_is_verbose() && slpmsg->buffer != NULL) {
-- g_string_append_len(str, (gchar*)slpmsg->buffer, slpmsg->size);
--
-- if (slpmsg->buffer[slpmsg->size - 1] == '\0') {
-- str->len--;
-- g_string_append(str, " 0x00");
-- }
-- g_string_append(str, "\r\n");
--
-- }
--
-- purple_debug_info("msn", "SlpMessage %s:\n{%s}\n", slpmsg->info, str->str);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slpmsg.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpmsg.h
---- pidgin-2.10.7/libpurple/protocols/msn/slpmsg.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpmsg.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,150 +0,0 @@
--/**
-- * @file slpmsg.h SLP Message functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef _MSN_SLPMSG_H_
--#define _MSN_SLPMSG_H_
--
--typedef struct _MsnSlpMessage MsnSlpMessage;
--
--#include "imgstore.h"
--
--#include "slpcall.h"
--#include "slplink.h"
--#include "session.h"
--#include "p2p.h"
--
--#include "slp.h"
--
--/**
-- * A SLP Message This contains everything that we will need to send a SLP
-- * Message even if has to be sent in several parts.
-- */
--struct _MsnSlpMessage
--{
-- MsnSlpCall *slpcall; /**< The slpcall to which this slp message belongs (if applicable). */
-- MsnSlpLink *slplink; /**< The slplink through which this slp message is being sent. */
-- MsnSession *session;
--
-- MsnP2PInfo *p2p_info;
--
-- long id;
--
-- gboolean ft;
-- PurpleStoredImage *img;
-- guchar *buffer;
--
-- /**
-- * This is the size of buffer, unless this is an outgoing file transfer,
-- * in which case this is the size of the file.
-- */
-- long long size;
--
-- GList *parts; /**< A list with the SlpMsgParts */
--
-- const char *info;
-- gboolean text_body;
--};
--
--/**
-- * Creates a new slp message
-- *
-- * @param slplink The slplink through which this slp message will be sent.
-- * If it's set to NULL, it is a temporary SlpMessage.
-- * @return The created slp message.
-- */
--MsnSlpMessage *msn_slpmsg_new(MsnSlpLink *slplink, MsnSlpCall *slpcall);
--
--/**
-- * Destroys a slp message
-- *
-- * @param slpmsg The slp message to destory.
-- */
--void msn_slpmsg_destroy(MsnSlpMessage *slpmsg);
--
--/**
-- * Relate this SlpMessage with an existing SlpLink
-- *
-- * @param slplink The SlpLink that will send this message.
-- */
--void msn_slpmsg_set_slplink(MsnSlpMessage *slpmsg, MsnSlpLink *slplink);
--
--void msn_slpmsg_set_body(MsnSlpMessage *slpmsg, const char *body,
-- long long size);
--void msn_slpmsg_set_image(MsnSlpMessage *slpmsg, PurpleStoredImage *img);
--MsnSlpMessage * msn_slpmsg_sip_new(MsnSlpCall *slpcall, int cseq,
-- const char *header,
-- const char *branch,
-- const char *content_type,
-- const char *content);
--
--/**
-- * Create a new SLP Ack message
-- *
-- * @param header the value of the header in this slpmsg.
-- *
-- * @return A new SlpMessage with ACK headers
-- */
--MsnSlpMessage *msn_slpmsg_ack_new(MsnSlpLink *slplink, MsnP2PInfo *info);
--
--/**
-- * Create a new SLP message for MsnObject data.
-- *
-- * @param slpcall The slpcall that manages this message.
-- * @param img The image to be sent in this message.
-- *
-- * @return A new SlpMessage with MsnObject info.
-- */
--MsnSlpMessage *msn_slpmsg_obj_new(MsnSlpCall *slpcall, PurpleStoredImage *img);
--
--/**
-- * Create a new SLP message for data preparation.
-- *
-- * @param slpcall The slpcall that manages this message.
-- *
-- * @return A new SlpMessage with data preparation info.
-- */
--MsnSlpMessage *msn_slpmsg_dataprep_new(MsnSlpCall *slpcall);
--
--/**
-- * Create a new SLP message for File transfer.
-- *
-- * @param slpcall The slpcall that manages this message.
-- * @param size The size of the file being transsmited.
-- *
-- * @return A new SlpMessage with the file transfer info.
-- */
--MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, size_t size);
--
--/**
-- * Serialize the MsnSlpMessage in a way it can be used to be transmited
-- *
-- * @param slpmsg The MsnSlpMessage.
-- * @param ret_size The size of the buffer cointaining the message.
-- *
-- * @return a buffer with the serialized data.
-- */
--char *msn_slpmsg_serialize(MsnSlpMessage *slpmsg, size_t *ret_size);
--
--void msn_slpmsg_show_readable(MsnSlpMessage *slpmsg);
--
--#endif /* _MSN_SLPMSG_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slpmsg_part.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpmsg_part.c
---- pidgin-2.10.7/libpurple/protocols/msn/slpmsg_part.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpmsg_part.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,232 +0,0 @@
--/**
-- * @file slpmsg_part.c MSNSLP Parts
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "slpmsg.h"
--#include "slpmsg_part.h"
--
--MsnSlpMessagePart *msn_slpmsgpart_new(MsnP2PInfo *info)
--{
-- MsnSlpMessagePart *part;
--
-- part = g_new0(MsnSlpMessagePart, 1);
--
-- part->info = info;
--
-- part->ack_cb = msn_slpmsgpart_ack;
-- part->nak_cb = msn_slpmsgpart_nak;
--
-- return msn_slpmsgpart_ref(part);
--}
--
--MsnSlpMessagePart *
--msn_slpmsgpart_new_from_data(MsnP2PVersion p2p, const char *data, size_t data_len)
--{
-- MsnSlpMessagePart *part;
-- MsnP2PInfo *info;
-- size_t len;
-- int body_len;
--
-- info = msn_p2p_info_new(p2p);
--
-- /* Extract the binary SLP header */
-- len = msn_p2p_header_from_wire(info, data, data_len);
-- if (len == 0) {
-- msn_p2p_info_free(info);
-- return NULL;
-- }
-- data += len;
-- part = msn_slpmsgpart_new(info);
--
-- /* Extract the body */
-- body_len = data_len - len - P2P_PACKET_FOOTER_SIZE;
-- /* msg->body_len = msg->msnslp_header.length; */
--
-- if (body_len > 0) {
-- part->size = body_len;
-- part->buffer = g_malloc(body_len);
-- memcpy(part->buffer, data, body_len);
-- data += body_len;
-- }
--
-- /* Extract the footer */
-- if (body_len >= 0)
-- msn_p2p_footer_from_wire(part->info, data);
--
-- return part;
--}
--
--static void msn_slpmsgpart_destroy(MsnSlpMessagePart *part)
--{
-- g_free(part->info);
-- g_free(part->buffer);
--
-- g_free(part);
--
--}
--
--MsnSlpMessagePart *msn_slpmsgpart_ref(MsnSlpMessagePart *part)
--{
-- g_return_val_if_fail(part != NULL, NULL);
-- part->ref_count++;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "part ref (%p)[%u]\n", part, part->ref_count);
--
-- return part;
--}
--
--void msn_slpmsgpart_unref(MsnSlpMessagePart *part)
--{
-- g_return_if_fail(part != NULL);
-- g_return_if_fail(part->ref_count > 0);
--
-- part->ref_count--;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "part unref (%p)[%u]\n", part, part->ref_count);
--
-- if (part->ref_count == 0) {
-- msn_slpmsgpart_destroy(part);
-- }
--}
--
--void msn_slpmsgpart_set_bin_data(MsnSlpMessagePart *part, const void *data, size_t len)
--{
-- g_return_if_fail(part != NULL);
--
-- g_free(part->buffer);
--
-- if (data != NULL && len > 0) {
-- part->buffer = g_malloc(len + 1);
-- memcpy(part->buffer, data, len);
-- part->buffer[len] = '\0';
-- part->size = len;
-- } else {
-- part->buffer = NULL;
-- part->size = 0;
-- }
--
--}
--
--char *msn_slpmsgpart_serialize(MsnSlpMessagePart *part, size_t *ret_size)
--{
-- char *header;
-- char *footer;
-- char *base;
-- char *tmp;
-- size_t header_size, footer_size;
--
-- header = msn_p2p_header_to_wire(part->info, &header_size);
-- footer = msn_p2p_footer_to_wire(part->info, &footer_size);
--
-- base = g_malloc(header_size + part->size + footer_size);
-- tmp = base;
--
-- /* Copy header */
-- memcpy(tmp, header, header_size);
-- tmp += header_size;
--
-- /* Copy body */
-- memcpy(tmp, part->buffer, part->size);
-- tmp += part->size;
--
-- /* Copy footer */
-- memcpy(tmp, footer, footer_size);
-- tmp += footer_size;
--
-- *ret_size = tmp - base;
--
-- g_free(header);
-- g_free(footer);
--
-- return base;
--}
--
--/* We have received the message ack */
--void
--msn_slpmsgpart_ack(MsnSlpMessagePart *part, void *data)
--{
-- MsnSlpMessage *slpmsg;
-- guint64 offset;
-- long long real_size;
--
-- slpmsg = data;
--
-- real_size = msn_p2p_info_is_ack(slpmsg->p2p_info) ? 0 : slpmsg->size;
--
-- offset = msn_p2p_info_get_offset(slpmsg->p2p_info);
-- offset += msn_p2p_info_get_length(part->info);
-- msn_p2p_info_set_offset(slpmsg->p2p_info, offset);
--
-- slpmsg->parts = g_list_remove(slpmsg->parts, part);
-- msn_slpmsgpart_unref(part);
--
-- if (offset < real_size)
-- {
-- if (slpmsg->slpcall->xfer && purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
-- {
-- slpmsg->slpcall->xfer_msg = slpmsg;
-- purple_xfer_prpl_ready(slpmsg->slpcall->xfer);
-- }
-- else
-- msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);
-- }
-- else
-- {
-- /* The whole message has been sent */
-- if (msn_p2p_msg_is_data(slpmsg->p2p_info))
-- {
-- if (slpmsg->slpcall != NULL)
-- {
-- if (slpmsg->slpcall->cb)
-- slpmsg->slpcall->cb(slpmsg->slpcall,
-- NULL, 0);
-- }
-- }
-- }
--}
--
--/* We have received the message nak. */
--void
--msn_slpmsgpart_nak(MsnSlpMessagePart *part, void *data)
--{
-- MsnSlpMessage *slpmsg;
--
-- slpmsg = data;
--
-- msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);
--
-- slpmsg->parts = g_list_remove(slpmsg->parts, part);
-- msn_slpmsgpart_unref(part);
--}
--
--void
--msn_slpmsgpart_to_string(MsnSlpMessagePart *part, GString *str)
--{
-- msn_p2p_info_to_string(part->info, str);
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slpmsg_part.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpmsg_part.h
---- pidgin-2.10.7/libpurple/protocols/msn/slpmsg_part.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpmsg_part.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,66 +0,0 @@
--/**
-- * @file slpmsg_part.h MSNSLP Parts
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef MSN_SLPMSG_PART_H
--#define MSN_SLPMSG_PART_H
--
--#include "p2p.h"
--
--typedef struct _MsnSlpMessagePart MsnSlpMessagePart;
--typedef void (*MsnSlpPartCb)(MsnSlpMessagePart *part, void *data);
--
--struct _MsnSlpMessagePart
--{
-- guint ref_count;
--
-- MsnP2PInfo *info;
--
-- MsnSlpPartCb ack_cb;
-- MsnSlpPartCb nak_cb;
-- void *ack_data;
--
-- guchar *buffer;
-- size_t size;
--};
--
--MsnSlpMessagePart *msn_slpmsgpart_new(MsnP2PInfo *info);
--
--MsnSlpMessagePart *msn_slpmsgpart_new_from_data(MsnP2PVersion p2p, const char *data, size_t data_len);
--
--MsnSlpMessagePart *msn_slpmsgpart_ref(MsnSlpMessagePart *part);
--
--void msn_slpmsgpart_unref(MsnSlpMessagePart *part);
--
--void msn_slpmsgpart_set_bin_data(MsnSlpMessagePart *part, const void *data, size_t len);
--
--char *msn_slpmsgpart_serialize(MsnSlpMessagePart *part, size_t *ret_size);
--
--void msn_slpmsgpart_ack(MsnSlpMessagePart *part, void *data);
--
--void msn_slpmsgpart_nak(MsnSlpMessagePart *part, void *data);
--
--void msn_slpmsgpart_to_string(MsnSlpMessagePart *part, GString *str);
--
--#endif /* MSN_SLPMSG_PART_H */
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/soap.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/soap.c
---- pidgin-2.10.7/libpurple/protocols/msn/soap.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/soap.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,683 +0,0 @@
--/**
-- * @file soap.c
-- * Functions relating to SOAP connections.
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-- */
--
--#include "internal.h"
--
--#include "soap.h"
--
--#include "session.h"
--
--#include "debug.h"
--#include "xmlnode.h"
--
--#include <glib.h>
--#if !defined(_WIN32) || !defined(_WINERROR_)
--#include <error.h>
--#endif
--
--#define SOAP_TIMEOUT (5 * 60)
--
--typedef struct _MsnSoapRequest {
-- char *path;
-- MsnSoapMessage *message;
-- gboolean secure;
-- MsnSoapCallback cb;
-- gpointer cb_data;
--} MsnSoapRequest;
--
--typedef struct _MsnSoapConnection {
-- MsnSession *session;
-- char *host;
--
-- time_t last_used;
-- PurpleSslConnection *ssl;
-- gboolean connected;
--
-- guint event_handle;
-- guint run_timer;
-- GString *buf;
-- gsize handled_len;
-- gsize body_len;
-- int response_code;
-- gboolean headers_done;
-- gboolean close_when_done;
--
-- MsnSoapMessage *message;
--
-- GQueue *queue;
-- MsnSoapRequest *current_request;
--} MsnSoapConnection;
--
--static gboolean msn_soap_connection_run(gpointer data);
--
--static MsnSoapConnection *
--msn_soap_connection_new(MsnSession *session, const char *host)
--{
-- MsnSoapConnection *conn = g_new0(MsnSoapConnection, 1);
-- conn->session = session;
-- conn->host = g_strdup(host);
-- conn->queue = g_queue_new();
-- return conn;
--}
--
--static void
--msn_soap_message_destroy(MsnSoapMessage *message)
--{
-- g_slist_foreach(message->headers, (GFunc)g_free, NULL);
-- g_slist_free(message->headers);
-- g_free(message->action);
-- if (message->xml)
-- xmlnode_free(message->xml);
-- g_free(message);
--}
--
--static void
--msn_soap_request_destroy(MsnSoapRequest *req, gboolean keep_message)
--{
-- g_free(req->path);
-- if (!keep_message)
-- msn_soap_message_destroy(req->message);
-- g_free(req);
--}
--
--static void
--msn_soap_connection_sanitize(MsnSoapConnection *conn, gboolean disconnect)
--{
-- if (conn->event_handle) {
-- purple_input_remove(conn->event_handle);
-- conn->event_handle = 0;
-- }
--
-- if (conn->run_timer) {
-- purple_timeout_remove(conn->run_timer);
-- conn->run_timer = 0;
-- }
--
-- if (conn->message) {
-- msn_soap_message_destroy(conn->message);
-- conn->message = NULL;
-- }
--
-- if (conn->buf) {
-- g_string_free(conn->buf, TRUE);
-- conn->buf = NULL;
-- }
--
-- if (conn->ssl && (disconnect || conn->close_when_done)) {
-- purple_ssl_close(conn->ssl);
-- conn->ssl = NULL;
-- }
--
-- if (conn->current_request) {
-- msn_soap_request_destroy(conn->current_request, FALSE);
-- conn->current_request = NULL;
-- }
--}
--
--static void
--msn_soap_connection_destroy_foreach_cb(gpointer item, gpointer data)
--{
-- MsnSoapRequest *req = item;
--
-- req->cb(req->message, NULL, req->cb_data);
--
-- msn_soap_request_destroy(req, FALSE);
--}
--
--static void
--msn_soap_connection_destroy(MsnSoapConnection *conn)
--{
-- if (conn->current_request) {
-- MsnSoapRequest *req = conn->current_request;
-- conn->current_request = NULL;
-- msn_soap_connection_destroy_foreach_cb(req, conn);
-- }
--
-- msn_soap_connection_sanitize(conn, TRUE);
-- g_queue_foreach(conn->queue, msn_soap_connection_destroy_foreach_cb, conn);
-- g_queue_free(conn->queue);
--
-- g_free(conn->host);
-- g_free(conn);
--}
--
--static gboolean
--msn_soap_cleanup_each(gpointer key, gpointer value, gpointer data)
--{
-- MsnSoapConnection *conn = value;
-- time_t *t = data;
--
-- if ((*t - conn->last_used) > SOAP_TIMEOUT * 2) {
-- purple_debug_info("soap", "cleaning up soap conn %p\n", conn);
-- return TRUE;
-- }
--
-- return FALSE;
--}
--
--static gboolean
--msn_soap_cleanup_for_session(gpointer data)
--{
-- MsnSession *sess = data;
-- time_t t = time(NULL);
--
-- purple_debug_info("soap", "session cleanup timeout\n");
--
-- if (sess->soap_table) {
-- g_hash_table_foreach_remove(sess->soap_table, msn_soap_cleanup_each,
-- &t);
--
-- if (g_hash_table_size(sess->soap_table) != 0)
-- return TRUE;
-- }
--
-- sess->soap_cleanup_handle = 0;
-- return FALSE;
--}
--
--static MsnSoapConnection *
--msn_soap_get_connection(MsnSession *session, const char *host)
--{
-- MsnSoapConnection *conn = NULL;
--
-- if (session->soap_table) {
-- conn = g_hash_table_lookup(session->soap_table, host);
-- } else {
-- session->soap_table = g_hash_table_new_full(g_str_hash, g_str_equal,
-- NULL, (GDestroyNotify)msn_soap_connection_destroy);
-- }
--
-- if (session->soap_cleanup_handle == 0)
-- session->soap_cleanup_handle = purple_timeout_add_seconds(SOAP_TIMEOUT,
-- msn_soap_cleanup_for_session, session);
--
-- if (conn == NULL) {
-- conn = msn_soap_connection_new(session, host);
-- g_hash_table_insert(session->soap_table, conn->host, conn);
-- }
--
-- conn->last_used = time(NULL);
--
-- return conn;
--}
--
--static void
--msn_soap_connection_handle_next(MsnSoapConnection *conn)
--{
-- msn_soap_connection_sanitize(conn, FALSE);
--
-- conn->run_timer = purple_timeout_add(0, msn_soap_connection_run, conn);
--}
--
--static void
--msn_soap_message_send_internal(MsnSession *session, MsnSoapMessage *message,
-- const char *host, const char *path, gboolean secure,
-- MsnSoapCallback cb, gpointer cb_data, gboolean first)
--{
-- MsnSoapConnection *conn = msn_soap_get_connection(session, host);
-- MsnSoapRequest *req = g_new0(MsnSoapRequest, 1);
--
-- req->path = g_strdup(path);
-- req->message = message;
-- req->secure = secure;
-- req->cb = cb;
-- req->cb_data = cb_data;
--
-- if (first) {
-- g_queue_push_head(conn->queue, req);
-- } else {
-- g_queue_push_tail(conn->queue, req);
-- }
--
-- if (conn->run_timer == 0)
-- conn->run_timer = purple_timeout_add(0, msn_soap_connection_run,
-- conn);
--}
--
--void
--msn_soap_message_send(MsnSession *session, MsnSoapMessage *message,
-- const char *host, const char *path, gboolean secure,
-- MsnSoapCallback cb, gpointer cb_data)
--{
-- g_return_if_fail(message != NULL);
-- g_return_if_fail(cb != NULL);
--
-- msn_soap_message_send_internal(session, message, host, path, secure,
-- cb, cb_data, FALSE);
--}
--
--static gboolean
--msn_soap_handle_redirect(MsnSoapConnection *conn, const char *url)
--{
-- char *host;
-- char *path;
--
-- if (purple_url_parse(url, &host, NULL, &path, NULL, NULL)) {
-- MsnSoapRequest *req = conn->current_request;
-- conn->current_request = NULL;
--
-- msn_soap_message_send_internal(conn->session, req->message, host, path,
-- req->secure, req->cb, req->cb_data, TRUE);
--
-- msn_soap_request_destroy(req, TRUE);
--
-- g_free(host);
-- g_free(path);
--
-- return TRUE;
-- }
--
-- return FALSE;
--}
--
--static gboolean
--msn_soap_handle_body(MsnSoapConnection *conn, MsnSoapMessage *response)
--{
-- xmlnode *body = xmlnode_get_child(response->xml, "Body");
-- xmlnode *fault = xmlnode_get_child(response->xml, "Fault");
--
-- if (fault) {
-- xmlnode *faultcode = xmlnode_get_child(fault, "faultcode");
--
-- if (faultcode != NULL) {
-- char *faultdata = xmlnode_get_data(faultcode);
--
-- if (g_str_equal(faultdata, "psf:Redirect")) {
-- xmlnode *url = xmlnode_get_child(fault, "redirectUrl");
--
-- if (url) {
-- char *urldata = xmlnode_get_data(url);
-- msn_soap_handle_redirect(conn, urldata);
-- g_free(urldata);
-- }
--
-- g_free(faultdata);
-- msn_soap_message_destroy(response);
-- return TRUE;
-- } else if (g_str_equal(faultdata, "wsse:FailedAuthentication")) {
-- xmlnode *reason = xmlnode_get_child(fault, "faultstring");
-- char *reasondata = xmlnode_get_data(reason);
--
-- msn_soap_connection_sanitize(conn, TRUE);
-- msn_session_set_error(conn->session, MSN_ERROR_AUTH,
-- reasondata);
--
-- g_free(reasondata);
-- g_free(faultdata);
-- msn_soap_message_destroy(response);
-- return FALSE;
-- }
--
-- g_free(faultdata);
-- }
-- }
--
-- if (fault || body) {
-- if (conn->current_request) {
-- MsnSoapRequest *request = conn->current_request;
-- conn->current_request = NULL;
-- request->cb(request->message, response,
-- request->cb_data);
-- msn_soap_request_destroy(request, FALSE);
-- }
-- msn_soap_message_destroy(response);
-- }
--
-- return TRUE;
--}
--
--static void
--msn_soap_message_add_header(MsnSoapMessage *message,
-- const char *name, const char *value)
--{
-- char *header = g_strdup_printf("%s: %s\r\n", name, value);
--
-- message->headers = g_slist_prepend(message->headers, header);
--}
--
--static void
--msn_soap_process(MsnSoapConnection *conn)
--{
-- gboolean handled = FALSE;
-- char *cursor;
-- char *linebreak;
--
-- cursor = conn->buf->str + conn->handled_len;
--
-- if (!conn->headers_done) {
-- while ((linebreak = strstr(cursor, "\r\n")) != NULL) {
-- conn->handled_len = linebreak - conn->buf->str + 2;
--
-- if (conn->response_code == 0) {
-- if (sscanf(cursor, "HTTP/1.1 %d", &conn->response_code) != 1) {
-- /* something horribly wrong */
-- purple_ssl_close(conn->ssl);
-- conn->ssl = NULL;
-- handled = TRUE;
-- break;
-- } else if (conn->response_code == 503 && conn->session->login_step < MSN_LOGIN_STEP_END) {
-- msn_soap_connection_sanitize(conn, TRUE);
-- msn_session_set_error(conn->session, MSN_ERROR_SERV_UNAVAILABLE, NULL);
-- return;
-- }
-- } else if (cursor == linebreak) {
-- /* blank line */
-- conn->headers_done = TRUE;
-- cursor = conn->buf->str + conn->handled_len;
-- break;
-- } else {
-- char *line = g_strndup(cursor, linebreak - cursor);
-- char *sep = strstr(line, ": ");
-- char *key = line;
-- char *value;
--
-- if (sep == NULL) {
-- purple_debug_info("soap", "ignoring malformed line: %s\n", line);
-- g_free(line);
-- goto loop_end;
-- }
--
-- value = sep + 2;
-- *sep = '\0';
-- msn_soap_message_add_header(conn->message, key, value);
--
-- if ((conn->response_code == 301 || conn->response_code == 300)
-- && strcmp(key, "Location") == 0) {
--
-- msn_soap_handle_redirect(conn, value);
--
-- handled = TRUE;
-- g_free(line);
-- break;
-- } else if (conn->response_code == 401 &&
-- strcmp(key, "WWW-Authenticate") == 0) {
-- char *error = strstr(value, "cbtxt=");
--
-- if (error) {
-- error += strlen("cbtxt=");
-- }
--
-- msn_soap_connection_sanitize(conn, TRUE);
-- msn_session_set_error(conn->session, MSN_ERROR_AUTH,
-- error ? purple_url_decode(error) : NULL);
--
-- g_free(line);
-- return;
-- } else if (strcmp(key, "Content-Length") == 0) {
-- sscanf(value, "%" G_GSIZE_FORMAT, &(conn->body_len));
-- } else if (strcmp(key, "Connection") == 0) {
-- if (strcmp(value, "close") == 0) {
-- conn->close_when_done = TRUE;
-- }
-- }
-- g_free(line);
-- }
--
-- loop_end:
-- cursor = conn->buf->str + conn->handled_len;
-- }
-- }
--
-- if (!handled && conn->headers_done) {
-- if (conn->buf->len - conn->handled_len >=
-- conn->body_len) {
-- xmlnode *node = xmlnode_from_str(cursor, conn->body_len);
--
-- if (node == NULL) {
-- purple_debug_info("soap", "Malformed SOAP response: %s\n",
-- cursor);
-- } else {
-- MsnSoapMessage *message = conn->message;
-- conn->message = NULL;
-- message->xml = node;
--
-- if (!msn_soap_handle_body(conn, message)) {
-- return;
-- }
-- }
--
-- msn_soap_connection_handle_next(conn);
-- }
--
-- return;
-- }
--
-- if (handled) {
-- msn_soap_connection_handle_next(conn);
-- }
--}
--
--static void
--msn_soap_read_cb(gpointer data, gint fd, PurpleInputCondition cond)
--{
-- MsnSoapConnection *conn = data;
-- int count = 0, cnt, perrno;
-- /* This buffer needs to be larger than any packets received from
-- login.live.com or Adium will fail to receive the packet
-- (something weird with the login.live.com server). With NSS it works
-- fine, so I believe it's some bug with OS X */
-- char buf[16 * 1024];
-- gsize cursor;
--
-- if (conn->message == NULL) {
-- conn->message = msn_soap_message_new(NULL, NULL);
-- }
--
-- if (conn->buf == NULL) {
-- conn->buf = g_string_new_len(buf, 0);
-- }
--
-- cursor = conn->buf->len;
-- while ((cnt = purple_ssl_read(conn->ssl, buf, sizeof(buf))) > 0) {
-- purple_debug_info("soap", "read %d bytes\n", cnt);
-- count += cnt;
-- g_string_append_len(conn->buf, buf, cnt);
-- }
--
-- perrno = errno;
-- if (cnt < 0 && perrno != EAGAIN)
-- purple_debug_info("soap", "read: %s\n", g_strerror(perrno));
--
-- if (conn->current_request && conn->current_request->secure &&
-- !purple_debug_is_unsafe())
-- purple_debug_misc("soap", "Received secure request.\n");
-- else if (count != 0)
-- purple_debug_misc("soap", "current %s\n", conn->buf->str + cursor);
--
-- /* && count is necessary for Adium, on OS X the last read always
-- return an error, so we want to proceed anyway. See #5212 for
-- discussion on this and the above buffer size issues */
-- if(cnt < 0 && errno == EAGAIN && count == 0)
-- return;
--
-- /* msn_soap_process could alter errno */
-- msn_soap_process(conn);
--
-- if ((cnt < 0 && perrno != EAGAIN) || cnt == 0) {
-- /* It's possible msn_soap_process closed the ssl connection */
-- if (conn->ssl) {
-- purple_ssl_close(conn->ssl);
-- conn->ssl = NULL;
-- msn_soap_connection_handle_next(conn);
-- }
-- }
--}
--
--static gboolean
--msn_soap_write_cb_internal(gpointer data, gint fd, PurpleInputCondition cond,
-- gboolean initial)
--{
-- MsnSoapConnection *conn = data;
-- int written;
--
-- if (cond != PURPLE_INPUT_WRITE)
-- return TRUE;
--
-- written = purple_ssl_write(conn->ssl, conn->buf->str + conn->handled_len,
-- conn->buf->len - conn->handled_len);
--
-- if (written < 0 && errno == EAGAIN)
-- return TRUE;
-- else if (written <= 0) {
-- purple_ssl_close(conn->ssl);
-- conn->ssl = NULL;
-- if (!initial)
-- msn_soap_connection_handle_next(conn);
-- return FALSE;
-- }
--
-- conn->handled_len += written;
--
-- if (conn->handled_len < conn->buf->len)
-- return TRUE;
--
-- /* we are done! */
-- g_string_free(conn->buf, TRUE);
-- conn->buf = NULL;
-- conn->handled_len = 0;
-- conn->body_len = 0;
-- conn->response_code = 0;
-- conn->headers_done = FALSE;
-- conn->close_when_done = FALSE;
--
-- purple_input_remove(conn->event_handle);
-- conn->event_handle = purple_input_add(conn->ssl->fd, PURPLE_INPUT_READ,
-- msn_soap_read_cb, conn);
-- return TRUE;
--}
--
--static void
--msn_soap_write_cb(gpointer data, gint fd, PurpleInputCondition cond)
--{
-- msn_soap_write_cb_internal(data, fd, cond, FALSE);
--}
--
--static void
--msn_soap_error_cb(PurpleSslConnection *ssl, PurpleSslErrorType error,
-- gpointer data)
--{
-- MsnSoapConnection *conn = data;
--
-- /* sslconn already frees the connection in case of error */
-- conn->ssl = NULL;
--
-- g_hash_table_remove(conn->session->soap_table, conn->host);
--}
--
--static void
--msn_soap_connected_cb(gpointer data, PurpleSslConnection *ssl,
-- PurpleInputCondition cond)
--{
-- MsnSoapConnection *conn = data;
--
-- conn->connected = TRUE;
--
-- if (conn->run_timer == 0)
-- conn->run_timer = purple_timeout_add(0, msn_soap_connection_run, conn);
--}
--
--MsnSoapMessage *
--msn_soap_message_new(const char *action, xmlnode *xml)
--{
-- MsnSoapMessage *message = g_new0(MsnSoapMessage, 1);
--
-- message->action = g_strdup(action);
-- message->xml = xml;
--
-- return message;
--}
--
--static gboolean
--msn_soap_connection_run(gpointer data)
--{
-- MsnSoapConnection *conn = data;
-- MsnSoapRequest *req = g_queue_peek_head(conn->queue);
--
-- conn->run_timer = 0;
--
-- if (req) {
-- if (conn->ssl == NULL) {
-- conn->ssl = purple_ssl_connect(conn->session->account, conn->host,
-- 443, msn_soap_connected_cb, msn_soap_error_cb, conn);
-- } else if (conn->connected) {
-- int len = -1;
-- char *body = xmlnode_to_str(req->message->xml, &len);
-- GSList *iter;
--
-- g_queue_pop_head(conn->queue);
--
-- conn->buf = g_string_new("");
--
-- g_string_append_printf(conn->buf,
-- "POST /%s HTTP/1.1\r\n"
-- "SOAPAction: %s\r\n"
-- "Content-Type:text/xml; charset=utf-8\r\n"
-- "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n"
-- "Accept: */*\r\n"
-- "Host: %s\r\n"
-- "Content-Length: %d\r\n"
-- "Connection: Keep-Alive\r\n"
-- "Cache-Control: no-cache\r\n",
-- req->path, req->message->action ? req->message->action : "",
-- conn->host, len);
--
-- for (iter = req->message->headers; iter; iter = iter->next) {
-- g_string_append(conn->buf, (char *)iter->data);
-- g_string_append(conn->buf, "\r\n");
-- }
--
-- g_string_append(conn->buf, "\r\n");
-- g_string_append(conn->buf, body);
--
-- if (req->secure && !purple_debug_is_unsafe())
-- purple_debug_misc("soap", "Sending secure request.\n");
-- else
-- purple_debug_misc("soap", "%s\n", conn->buf->str);
--
-- conn->handled_len = 0;
-- conn->current_request = req;
--
-- if (conn->event_handle)
-- purple_input_remove(conn->event_handle);
-- conn->event_handle = purple_input_add(conn->ssl->fd,
-- PURPLE_INPUT_WRITE, msn_soap_write_cb, conn);
-- if (!msn_soap_write_cb_internal(conn, conn->ssl->fd, PURPLE_INPUT_WRITE, TRUE)) {
-- /* Not connected => reconnect and retry */
-- purple_debug_info("soap", "not connected, reconnecting\n");
--
-- conn->connected = FALSE;
-- conn->current_request = NULL;
-- msn_soap_connection_sanitize(conn, FALSE);
--
-- g_queue_push_head(conn->queue, req);
-- conn->run_timer = purple_timeout_add(0, msn_soap_connection_run, conn);
-- }
--
-- g_free(body);
-- }
-- }
--
-- return FALSE;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/soap.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/soap.h
---- pidgin-2.10.7/libpurple/protocols/msn/soap.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/soap.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,52 +0,0 @@
--/**
-- * @file soap.h
-- * header file for SOAP connection related process
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-- */
--#ifndef MSN_SOAP_H
--#define MSN_SOAP_H
--
--typedef struct _MsnSoapMessage MsnSoapMessage;
--
--#include <glib.h>
--
--#include "xmlnode.h"
--
--#include "session.h"
--#include "sslconn.h"
--
--typedef void (*MsnSoapCallback)(MsnSoapMessage *request,
-- MsnSoapMessage *response, gpointer cb_data);
--
--struct _MsnSoapMessage {
-- char *action;
-- xmlnode *xml;
-- GSList *headers;
--};
--
--MsnSoapMessage *msn_soap_message_new(const char *action, xmlnode *xml);
--
--void msn_soap_message_send(MsnSession *session, MsnSoapMessage *message,
-- const char *host, const char *path, gboolean secure,
-- MsnSoapCallback cb, gpointer cb_data);
--
--#endif /* MSN_SOAP_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/state.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/state.c
---- pidgin-2.10.7/libpurple/protocols/msn/state.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/state.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,315 +0,0 @@
--/**
-- * @file state.c State functions and definitions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "core.h"
--
--#include "notification.h"
--#include "state.h"
--
--static const char *away_text[] =
--{
-- N_("Available"),
-- N_("Available"),
-- N_("Busy"),
-- N_("Idle"),
-- N_("Be Right Back"),
-- N_("Away From Computer"),
-- N_("On The Phone"),
-- N_("Out To Lunch"),
-- N_("Available"),
-- N_("Available")
--};
--
--/*
-- * WLM media PSM info build prcedure
-- *
-- * Result can like:
-- * <CurrentMedia>\0Music\01\0{0} - {1}\0Song Title\0Song Artist\0Song Album\0\0</CurrentMedia>\
-- * <CurrentMedia>\0Games\01\0Playing {0}\0Game Name\0</CurrentMedia>\
-- * <CurrentMedia>\0Office\01\0Office Message\0Office App Name\0</CurrentMedia>"
-- */
--static char *
--msn_build_psm(const char *psmstr,const char *mediastr, const char *guidstr, guint protocol_ver)
--{
-- xmlnode *dataNode,*psmNode,*mediaNode,*guidNode;
-- char *result;
-- int length;
--
-- dataNode = xmlnode_new("Data");
--
-- psmNode = xmlnode_new("PSM");
-- if(psmstr != NULL){
-- xmlnode_insert_data(psmNode, psmstr, -1);
-- }
-- xmlnode_insert_child(dataNode, psmNode);
--
-- mediaNode = xmlnode_new("CurrentMedia");
-- if(mediastr != NULL){
-- xmlnode_insert_data(mediaNode, mediastr, -1);
-- }
-- xmlnode_insert_child(dataNode, mediaNode);
--
-- guidNode = xmlnode_new("MachineGuid");
-- if(guidstr != NULL){
-- xmlnode_insert_data(guidNode, guidstr, -1);
-- }
-- xmlnode_insert_child(dataNode, guidNode);
--
-- if (protocol_ver >= 16) {
-- /* TODO: What is this for? */
-- xmlnode *ddpNode = xmlnode_new("DDP");
-- xmlnode_insert_child(dataNode, ddpNode);
-- }
--
-- result = xmlnode_to_str(dataNode, &length);
-- xmlnode_free(dataNode);
-- return result;
--}
--
--/* get the CurrentMedia info from the XML node */
--char *
--msn_get_currentmedia(xmlnode *payloadNode)
--{
-- xmlnode *currentmediaNode;
-- char *currentmedia;
--
-- purple_debug_info("msn", "Get CurrentMedia\n");
-- currentmediaNode = xmlnode_get_child(payloadNode, "CurrentMedia");
-- if (currentmediaNode == NULL) {
-- purple_debug_info("msn", "No CurrentMedia Node\n");
-- return NULL;
-- }
-- currentmedia = xmlnode_get_data(currentmediaNode);
--
-- return currentmedia;
--}
--
--/* Get the PSM info from the XML node */
--char *
--msn_get_psm(xmlnode *payloadNode)
--{
-- xmlnode *psmNode;
-- char *psm;
--
-- purple_debug_info("msn", "msn get PSM\n");
-- psmNode = xmlnode_get_child(payloadNode, "PSM");
-- if (psmNode == NULL) {
-- purple_debug_info("msn", "No PSM status Node\n");
-- return NULL;
-- }
-- psm = xmlnode_get_data(psmNode);
--
-- return psm;
--}
--
--static char *
--create_media_string(PurplePresence *presence)
--{
-- const char *title, *game, *office;
-- char *ret;
-- PurpleStatus *status = purple_presence_get_status(presence, "tune");
-- if (!status || !purple_status_is_active(status))
-- return NULL;
--
-- title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
-- game = purple_status_get_attr_string(status, "game");
-- office = purple_status_get_attr_string(status, "office");
--
-- if (title && *title) {
-- const char *artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
-- const char *album = purple_status_get_attr_string(status, PURPLE_TUNE_ALBUM);
-- ret = g_strdup_printf("WMP\\0Music\\01\\0{0}%s%s\\0%s\\0%s\\0%s\\0",
-- artist ? " - {1}" : "",
-- album ? " ({2})" : "",
-- title,
-- artist ? artist : "",
-- album ? album : "");
-- }
-- else if (game && *game)
-- ret = g_strdup_printf("\\0Games\\01\\0Playing {0}\\0%s\\0", game);
-- else if (office && *office)
-- ret = g_strdup_printf("\\0Office\\01\\0Editing {0}\\0%s\\0", office);
-- else
-- ret = NULL;
--
-- return ret;
--}
--
--/* set the MSN's PSM info,Currently Read from the status Line
-- * Thanks for Cris Code
-- */
--static void
--msn_set_psm(MsnSession *session)
--{
-- PurpleAccount *account;
-- PurplePresence *presence;
-- PurpleStatus *status;
-- char *payload;
-- const char *statusline;
-- gchar *statusline_stripped, *media = NULL;
--
-- g_return_if_fail(session != NULL);
-- g_return_if_fail(session->notification != NULL);
--
-- account = session->account;
--
-- /* Get the PSM string from Purple's Status Line */
-- presence = purple_account_get_presence(account);
-- status = purple_presence_get_active_status(presence);
-- statusline = purple_status_get_attr_string(status, "message");
--
-- /* MSN expects plain text, not HTML */
-- statusline_stripped = purple_markup_strip_html(statusline);
-- media = create_media_string(presence);
-- g_free(session->psm);
-- session->psm = msn_build_psm(statusline_stripped, media, session->guid, session->protocol_ver);
--
-- payload = session->psm;
--
-- msn_notification_send_uux(session, payload);
--
-- g_free(statusline_stripped);
-- g_free(media);
--}
--
--void
--msn_change_status(MsnSession *session)
--{
-- PurpleAccount *account;
-- MsnCmdProc *cmdproc;
-- MsnTransaction *trans;
-- MsnUser *user;
-- MsnObject *msnobj;
-- const char *state_text;
-- GHashTable *ui_info = purple_core_get_ui_info();
-- MsnClientCaps caps = MSN_CLIENT_ID;
--
-- g_return_if_fail(session != NULL);
-- g_return_if_fail(session->notification != NULL);
--
-- /* set client caps based on what the UI tells us it is... */
-- if (ui_info) {
-- const gchar *client_type = g_hash_table_lookup(ui_info, "client_type");
-- if (client_type) {
-- if (strcmp(client_type, "phone") == 0 ||
-- strcmp(client_type, "handheld") == 0) {
-- caps |= MSN_CAP_VIA_MOBILE;
-- } else if (strcmp(client_type, "web") == 0) {
-- caps |= MSN_CAP_VIA_WEBIM;
-- } else if (strcmp(client_type, "bot") == 0) {
-- caps |= MSN_CAP_BOT;
-- }
-- /* MSN doesn't a "console" type...
-- What, they have no ncurses UI? :-) */
-- }
-- }
--
-- account = session->account;
-- cmdproc = session->notification->cmdproc;
-- user = session->user;
-- state_text = msn_state_get_text(msn_state_from_account(account));
--
-- /* If we're not logged in yet, don't send the status to the server,
-- * it will be sent when login completes
-- */
-- if (!session->logged_in)
-- return;
--
-- msn_set_psm(session);
--
-- msnobj = msn_user_get_object(user);
--
-- if (msnobj == NULL)
-- {
-- trans = msn_transaction_new(cmdproc, "CHG", "%s %u:%02u 0", state_text,
-- caps, MSN_CLIENT_ID_EXT_CAPS);
-- }
-- else
-- {
-- char *msnobj_str;
--
-- msnobj_str = msn_object_to_string(msnobj);
--
-- trans = msn_transaction_new(cmdproc, "CHG", "%s %u:%02u %s", state_text,
-- caps, MSN_CLIENT_ID_EXT_CAPS,
-- purple_url_encode(msnobj_str));
--
-- g_free(msnobj_str);
-- }
--
-- msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--const char *
--msn_away_get_text(MsnAwayType type)
--{
-- g_return_val_if_fail(type <= MSN_HIDDEN, NULL);
--
-- return _(away_text[type]);
--}
--
--const char *
--msn_state_get_text(MsnAwayType state)
--{
-- static char *status_text[] =
-- { "NLN", "NLN", "BSY", "IDL", "BRB", "AWY", "PHN", "LUN", "HDN", "HDN" };
--
-- return status_text[state];
--}
--
--MsnAwayType
--msn_state_from_account(PurpleAccount *account)
--{
-- MsnAwayType msnstatus;
-- PurplePresence *presence;
-- PurpleStatus *status;
-- const char *status_id;
--
-- presence = purple_account_get_presence(account);
-- status = purple_presence_get_active_status(presence);
-- status_id = purple_status_get_id(status);
--
-- if (!strcmp(status_id, "away"))
-- msnstatus = MSN_AWAY;
-- else if (!strcmp(status_id, "brb"))
-- msnstatus = MSN_BRB;
-- else if (!strcmp(status_id, "busy"))
-- msnstatus = MSN_BUSY;
-- else if (!strcmp(status_id, "phone"))
-- msnstatus = MSN_PHONE;
-- else if (!strcmp(status_id, "lunch"))
-- msnstatus = MSN_LUNCH;
-- else if (!strcmp(status_id, "invisible"))
-- msnstatus = MSN_HIDDEN;
-- else
-- msnstatus = MSN_ONLINE;
--
-- if ((msnstatus == MSN_ONLINE) && purple_presence_is_idle(presence))
-- msnstatus = MSN_IDLE;
--
-- return msnstatus;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/state.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/state.h
---- pidgin-2.10.7/libpurple/protocols/msn/state.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/state.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,69 +0,0 @@
--/**
-- * @file state.h State functions and definitions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_STATE_H
--#define MSN_STATE_H
--
--/**
-- * Away types.
-- */
--typedef enum
--{
-- MSN_ONLINE = 1,
-- MSN_BUSY = 2,
-- MSN_IDLE = 3,
-- MSN_BRB = 4,
-- MSN_AWAY = 5,
-- MSN_PHONE = 6,
-- MSN_LUNCH = 7,
-- MSN_OFFLINE = 8,
-- MSN_HIDDEN = 9
--} MsnAwayType;
--
--/**
-- * Changes the status of the user.
-- *
-- * @param session The MSN session.
-- */
--void msn_change_status(MsnSession *session);
--
--/**
-- * Returns the string representation of an away type.
-- *
-- * @param type The away type.
-- *
-- * @return The string representation of the away type.
-- */
--const char *msn_away_get_text(MsnAwayType type);
--
--const char *msn_state_get_text(MsnAwayType state);
--
--/* Get the CurrentMedia info from the XML node */
--char *msn_get_currentmedia(xmlnode *payloadNode);
--
--/* Get the PSM info from the XML node */
--char *msn_get_psm(xmlnode *payloadNode);
--
--MsnAwayType msn_state_from_account(PurpleAccount *account);
--
--#endif /* MSN_STATE_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/switchboard.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/switchboard.c
---- pidgin-2.10.7/libpurple/protocols/msn/switchboard.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/switchboard.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1197 +0,0 @@
--/**
-- * @file switchboard.c MSN switchboard functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "msnutils.h"
--#include "switchboard.h"
--#include "sbconn.h"
--#include "slplink.h"
--#include "user.h"
--#include "userlist.h"
--
--static MsnTable *cbs_table;
--
--/**************************************************************************
-- * Main
-- **************************************************************************/
--
--MsnSwitchBoard *
--msn_switchboard_new(MsnSession *session)
--{
-- MsnSwitchBoard *swboard;
--
-- g_return_val_if_fail(session != NULL, NULL);
--
-- swboard = g_new0(MsnSwitchBoard, 1);
--
-- swboard->session = session;
-- swboard->servconn = msn_servconn_new(session, MSN_SERVCONN_SB);
-- msn_servconn_set_idle_timeout(swboard->servconn, 60);
-- swboard->cmdproc = swboard->servconn->cmdproc;
--
-- swboard->msg_queue = g_queue_new();
-- swboard->empty = TRUE;
--
-- swboard->cmdproc->data = swboard;
-- swboard->cmdproc->cbs_table = cbs_table;
--
-- session->switches = g_list_prepend(session->switches, swboard);
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "switchboard new: swboard(%p)\n", swboard);
--
-- return swboard;
--}
--
--void
--msn_switchboard_destroy(MsnSwitchBoard *swboard)
--{
-- MsnSession *session;
-- MsnMessage *msg;
-- GList *l;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "switchboard destroy: swboard(%p)\n", swboard);
--
-- g_return_if_fail(swboard != NULL);
--
-- if (swboard->destroying)
-- return;
--
-- swboard->destroying = TRUE;
--
-- if (swboard->reconn_timeout_h > 0)
-- purple_timeout_remove(swboard->reconn_timeout_h);
--
-- /* If it linked us is because its looking for trouble */
-- while (swboard->slplinks != NULL) {
-- MsnSlpLink *slplink = swboard->slplinks->data;
--
-- swboard->slplinks = g_list_remove(swboard->slplinks, slplink);
--
-- /* Destroy only those slplinks which use the switchboard */
-- if (slplink->dc == NULL)
-- msn_slplink_unref(slplink);
-- else {
-- swboard->slplinks = g_list_remove(swboard->slplinks, slplink);
-- slplink->swboard = NULL;
-- }
-- }
--
-- /* Destroy the message queue */
-- while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL)
-- {
-- if (swboard->error != MSN_SB_ERROR_NONE)
-- {
-- /* The messages could not be sent due to a switchboard error */
-- msg_error_helper(swboard->cmdproc, msg,
-- MSN_MSG_ERROR_SB);
-- }
-- msn_message_unref(msg);
-- }
--
-- g_queue_free(swboard->msg_queue);
--
-- /* msg_error_helper will both remove the msg from ack_list and
-- unref it, so we don't need to do either here */
-- while ((l = swboard->ack_list) != NULL)
-- msg_error_helper(swboard->cmdproc, l->data, MSN_MSG_ERROR_SB);
--
-- g_free(swboard->im_user);
-- g_free(swboard->auth_key);
-- g_free(swboard->session_id);
--
-- for (; swboard->users; swboard->users = g_list_delete_link(swboard->users, swboard->users))
-- msn_user_unref(swboard->users->data);
--
-- session = swboard->session;
-- session->switches = g_list_remove(session->switches, swboard);
--
-- for (l = session->slplinks; l; l = l->next) {
-- MsnSlpLink *slplink = l->data;
-- if (slplink->swboard == swboard) slplink->swboard = NULL;
-- }
--
--#if 0
-- /* This should never happen or we are in trouble. */
-- if (swboard->servconn != NULL)
-- msn_servconn_destroy(swboard->servconn);
--#endif
--
-- swboard->cmdproc->data = NULL;
--
-- msn_servconn_set_disconnect_cb(swboard->servconn, NULL);
--
-- msn_servconn_destroy(swboard->servconn);
--
-- g_free(swboard);
--}
--
--void
--msn_switchboard_set_auth_key(MsnSwitchBoard *swboard, const char *key)
--{
-- g_return_if_fail(swboard != NULL);
-- g_return_if_fail(key != NULL);
--
-- swboard->auth_key = g_strdup(key);
--}
--
--const char *
--msn_switchboard_get_auth_key(MsnSwitchBoard *swboard)
--{
-- g_return_val_if_fail(swboard != NULL, NULL);
--
-- return swboard->auth_key;
--}
--
--void
--msn_switchboard_set_session_id(MsnSwitchBoard *swboard, const char *id)
--{
-- g_return_if_fail(swboard != NULL);
-- g_return_if_fail(id != NULL);
--
-- g_free(swboard->session_id);
-- swboard->session_id = g_strdup(id);
--}
--
--const char *
--msn_switchboard_get_session_id(MsnSwitchBoard *swboard)
--{
-- g_return_val_if_fail(swboard != NULL, NULL);
--
-- return swboard->session_id;
--}
--
--int
--msn_switchboard_get_chat_id(void)
--{
-- static int chat_id = 1;
--
-- return chat_id++;
--}
--
--void
--msn_switchboard_set_invited(MsnSwitchBoard *swboard, gboolean invited)
--{
-- g_return_if_fail(swboard != NULL);
--
-- swboard->invited = invited;
--}
--
--gboolean
--msn_switchboard_is_invited(MsnSwitchBoard *swboard)
--{
-- g_return_val_if_fail(swboard != NULL, FALSE);
--
-- return swboard->invited;
--}
--
--/**************************************************************************
-- * Utility
-- **************************************************************************/
--
--static void
--send_clientcaps(MsnSwitchBoard *swboard)
--{
-- MsnMessage *msg;
--
-- msg = msn_message_new(MSN_MSG_CAPS);
-- msn_message_set_content_type(msg, "text/x-clientcaps");
-- msn_message_set_flag(msg, 'U');
-- msn_message_set_bin_data(msg, MSN_CLIENTINFO, strlen(MSN_CLIENTINFO));
--
-- msn_switchboard_send_msg(swboard, msg, TRUE);
--
-- msn_message_unref(msg);
--}
--
--static void
--msn_switchboard_add_user(MsnSwitchBoard *swboard, const char *user)
--{
-- MsnCmdProc *cmdproc;
-- PurpleAccount *account;
-- MsnUserList *userlist;
-- MsnUser *msnuser;
-- char *semicolon;
-- char *passport;
--
-- g_return_if_fail(swboard != NULL);
--
-- cmdproc = swboard->cmdproc;
-- account = cmdproc->session->account;
--
-- semicolon = strchr(user, ';');
-- /* We don't really care about the machine ID. */
-- if (semicolon)
-- passport = g_strndup(user, semicolon - user);
-- else
-- passport = g_strdup(user);
--
-- userlist = swboard->session->userlist;
-- msnuser = msn_userlist_find_user(userlist, passport);
--
-- /* Don't add multiple endpoints to the conversation. */
-- if (g_list_find_custom(swboard->users, passport, (GCompareFunc)msn_user_passport_cmp)) {
-- g_free(passport);
-- return;
-- }
--
-- /* Don't add ourselves either... */
-- if (g_str_equal(passport, purple_account_get_username(account))) {
-- g_free(passport);
-- return;
-- }
--
-- if (!msnuser) {
-- purple_debug_info("msn","User %s is not on our list.\n", passport);
-- msnuser = msn_user_new(userlist, passport, NULL);
-- } else
-- msn_user_ref(msnuser);
--
-- g_free(passport);
--
-- swboard->users = g_list_prepend(swboard->users, msnuser);
-- swboard->current_users++;
-- swboard->empty = FALSE;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "user=[%s], total=%d\n",
-- user, swboard->current_users);
--
-- if (!(swboard->flag & MSN_SB_FLAG_IM) && (swboard->conv != NULL))
-- {
-- /* This is a helper switchboard. */
-- purple_debug_error("msn", "switchboard_add_user: conv != NULL\n");
-- return;
-- }
--
-- if ((swboard->conv != NULL) &&
-- (purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
-- {
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv), msnuser->passport, NULL,
-- PURPLE_CBFLAGS_NONE, TRUE);
-- msn_servconn_set_idle_timeout(swboard->servconn, 0);
-- }
-- else if (swboard->current_users > 1)
-- {
-- msn_servconn_set_idle_timeout(swboard->servconn, 0);
-- if (swboard->conv == NULL ||
-- purple_conversation_get_type(swboard->conv) != PURPLE_CONV_TYPE_CHAT)
-- {
-- GList *l;
--
--#if 0
-- /* this is bad - it causes msn_switchboard_close to be called on the
-- * switchboard we're in the middle of using :( */
-- if (swboard->conv != NULL)
-- purple_conversation_destroy(swboard->conv);
--#endif
--
-- swboard->chat_id = msn_switchboard_get_chat_id();
-- swboard->flag |= MSN_SB_FLAG_IM;
-- swboard->conv = serv_got_joined_chat(account->gc,
-- swboard->chat_id,
-- "MSN Chat");
--
-- for (l = swboard->users; l != NULL; l = l->next)
-- {
-- const char *tmp_user;
--
-- tmp_user = ((MsnUser*)l->data)->passport;
--
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv),
-- tmp_user, NULL, PURPLE_CBFLAGS_NONE, TRUE);
-- }
--
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv),
-- purple_account_get_username(account),
-- NULL, PURPLE_CBFLAGS_NONE, TRUE);
--
-- g_free(swboard->im_user);
-- swboard->im_user = NULL;
-- }
-- }
-- else if (swboard->conv == NULL)
-- {
-- swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-- msnuser->passport, account);
-- }
-- else
-- {
-- purple_debug_warning("msn", "switchboard_add_user: This should not happen!\n");
-- }
--}
--
--static PurpleConversation *
--msn_switchboard_get_conv(MsnSwitchBoard *swboard)
--{
-- PurpleAccount *account;
--
-- g_return_val_if_fail(swboard != NULL, NULL);
--
-- if (swboard->conv != NULL)
-- return swboard->conv;
--
-- purple_debug_error("msn", "Switchboard with unassigned conversation\n");
--
-- account = swboard->session->account;
--
-- return (swboard->conv = purple_conversation_new(PURPLE_CONV_TYPE_IM,
-- account, swboard->im_user));
--}
--
--static void
--msn_switchboard_report_user(MsnSwitchBoard *swboard, PurpleMessageFlags flags, const char *msg)
--{
-- PurpleConversation *conv;
--
-- g_return_if_fail(swboard != NULL);
-- g_return_if_fail(msg != NULL);
--
-- if ((conv = msn_switchboard_get_conv(swboard)) != NULL)
-- {
-- purple_conversation_write(conv, NULL, msg, flags, time(NULL));
-- }
--}
--
--static void
--swboard_error_helper(MsnSwitchBoard *swboard, int reason, const char *passport)
--{
-- g_return_if_fail(swboard != NULL);
--
-- purple_debug_warning("msn", "Error: Unable to call the user %s for reason %i\n",
-- passport ? passport : "(null)", reason);
--
-- /* TODO: if current_users > 0, this is probably a chat and an invite failed,
-- * we should report that in the chat or something */
-- if (swboard->current_users == 0)
-- {
-- swboard->error = reason;
-- msn_switchboard_close(swboard);
-- }
--}
--
--static void
--cal_error_helper(MsnTransaction *trans, int reason)
--{
-- MsnSwitchBoard *swboard;
-- const char *passport;
-- char **params;
--
-- params = g_strsplit(trans->params, " ", 0);
--
-- passport = params[0];
--
-- swboard = trans->data;
--
-- purple_debug_warning("msn", "cal_error_helper: command %s failed for reason %i\n",trans->command,reason);
--
-- swboard_error_helper(swboard, reason, passport);
--
-- g_strfreev(params);
--}
--
--static gboolean
--msg_resend_cb(gpointer data)
--{
-- MsnSwitchBoard *swboard = data;
--
-- purple_debug_info("msn", "unqueuing unsent message to %s\n", swboard->im_user);
--
-- if (msn_switchboard_request(swboard)) {
-- msn_switchboard_request_add_user(swboard, swboard->im_user);
-- swboard->reconn_timeout_h = 0;
-- }
-- return FALSE;
--}
--
--void
--msg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, MsnMsgErrorType error)
--{
-- MsnSwitchBoard *swboard;
--
-- g_return_if_fail(cmdproc != NULL);
-- g_return_if_fail(msg != NULL);
--
-- if ((error != MSN_MSG_ERROR_SB) && (msg->nak_cb != NULL))
-- msg->nak_cb(msg, msg->ack_data);
--
-- swboard = cmdproc->data;
--
-- /* This is not good, and should be fixed somewhere else. */
-- g_return_if_fail(swboard != NULL);
--
-- if (msg->type == MSN_MSG_TEXT)
-- {
-- const char *format, *str_reason;
-- char *body_str, *body_enc, *pre, *post;
--
--#if 0
-- if (swboard->conv == NULL)
-- {
-- if (msg->ack_ref)
-- msn_message_unref(msg);
--
-- return;
-- }
--#endif
--
-- if (error == MSN_MSG_ERROR_TIMEOUT)
-- {
-- str_reason = _("Message may have not been sent "
-- "because a timeout occurred:");
-- }
-- else if (error == MSN_MSG_ERROR_SB)
-- {
-- MsnSession *session = swboard->session;
--
-- if (!session->destroying && msg->retries && swboard->im_user &&
-- (swboard->error == MSN_SB_ERROR_CONNECTION ||
-- swboard->error == MSN_SB_ERROR_UNKNOWN)) {
-- MsnSwitchBoard *new_sw = msn_session_find_swboard(session,
-- swboard->im_user);
--
-- if (new_sw == NULL || new_sw->reconn_timeout_h == 0) {
-- new_sw = msn_switchboard_new(session);
-- new_sw->im_user = g_strdup(swboard->im_user);
-- new_sw->reconn_timeout_h = purple_timeout_add_seconds(3, msg_resend_cb, new_sw);
-- new_sw->flag |= MSN_SB_FLAG_IM;
-- }
--
-- body_str = msn_message_to_string(msg);
-- body_enc = g_markup_escape_text(body_str, -1);
-- g_free(body_str);
--
-- purple_debug_info("msn", "queuing unsent message to %s: %s\n",
-- swboard->im_user, body_enc);
-- g_free(body_enc);
-- msn_send_im_message(session, msg);
-- msg->retries--;
--
-- return;
-- }
--
-- switch (swboard->error)
-- {
-- case MSN_SB_ERROR_OFFLINE:
-- str_reason = _("Message could not be sent, "
-- "not allowed while invisible:");
-- break;
-- case MSN_SB_ERROR_USER_OFFLINE:
-- str_reason = _("Message could not be sent "
-- "because the user is offline:");
-- break;
-- case MSN_SB_ERROR_CONNECTION:
-- str_reason = _("Message could not be sent "
-- "because a connection error occurred:");
-- break;
-- case MSN_SB_ERROR_TOO_FAST:
-- str_reason = _("Message could not be sent "
-- "because we are sending too quickly:");
-- break;
-- case MSN_SB_ERROR_AUTHFAILED:
-- str_reason = _("Message could not be sent "
-- "because we were unable to establish a "
-- "session with the server. This is "
-- "likely a server problem, try again in "
-- "a few minutes:");
-- break;
-- default:
-- str_reason = _("Message could not be sent "
-- "because an error with "
-- "the switchboard occurred:");
-- break;
-- }
-- }
-- else
-- {
-- str_reason = _("Message may have not been sent "
-- "because an unknown error occurred:");
-- }
--
-- body_str = msn_message_to_string(msg);
-- body_enc = g_markup_escape_text(body_str, -1);
-- g_free(body_str);
--
-- format = msn_message_get_header_value(msg, "X-MMS-IM-Format");
-- msn_parse_format(format, &pre, &post);
-- body_str = g_strdup_printf("%s%s%s", pre ? pre : "",
-- body_enc ? body_enc : "", post ? post : "");
-- g_free(body_enc);
-- g_free(pre);
-- g_free(post);
--
-- msn_switchboard_report_user(swboard, PURPLE_MESSAGE_ERROR,
-- str_reason);
-- msn_switchboard_report_user(swboard, PURPLE_MESSAGE_RAW,
-- body_str);
--
-- g_free(body_str);
-- }
--
-- /* If a timeout occures we will want the msg around just in case we
-- * receive the ACK after the timeout. */
-- if (msg->ack_ref && error != MSN_MSG_ERROR_TIMEOUT)
-- {
-- swboard->ack_list = g_list_remove(swboard->ack_list, msg);
-- msn_message_unref(msg);
-- }
--}
--
--/**************************************************************************
-- * Message Stuff
-- **************************************************************************/
--
--/** Called when we receive an error of a message. */
--static void
--msg_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
--{
-- msg_error_helper(cmdproc, trans->data, MSN_MSG_ERROR_UNKNOWN);
--}
--
--gboolean
--msn_switchboard_can_send(MsnSwitchBoard *swboard)
--{
-- g_return_val_if_fail(swboard != NULL, FALSE);
--
-- if (swboard->empty || !g_queue_is_empty(swboard->msg_queue))
-- return FALSE;
--
-- return TRUE;
--}
--
--/**************************************************************************
-- * Switchboard Commands
-- **************************************************************************/
--
--static void
--ans_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnSwitchBoard *swboard;
--
-- swboard = cmdproc->data;
-- swboard->ready = TRUE;
--}
--
--static void
--bye_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnSwitchBoard *swboard;
-- const char *user;
--
-- swboard = cmdproc->data;
-- user = cmd->params[0];
--
-- /* cmdproc->data is set to NULL when the switchboard is destroyed;
-- * we may get a bye shortly thereafter. */
-- g_return_if_fail(swboard != NULL);
--
-- if (!(swboard->flag & MSN_SB_FLAG_IM) && (swboard->conv != NULL))
-- purple_debug_error("msn", "bye_cmd: helper bug\n");
--
-- if (swboard->conv == NULL)
-- {
-- /* This is a helper switchboard */
-- msn_switchboard_destroy(swboard);
-- }
-- else if ((swboard->current_users > 1) ||
-- (purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
-- {
-- GList *passport;
-- /* This is a switchboard used for a chat */
-- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(swboard->conv), user, NULL);
--
-- passport = g_list_find_custom(swboard->users, user, (GCompareFunc)strcmp);
-- if (passport)
-- g_free(passport->data);
-- else
-- purple_debug_warning("msn", "Can't find user %s in the switchboard\n", user);
-- swboard->users = g_list_delete_link(swboard->users, passport);
-- swboard->current_users--;
-- if (swboard->current_users == 0)
-- msn_switchboard_destroy(swboard);
-- }
-- else
-- {
-- /* This is a switchboard used for a im session */
-- msn_switchboard_destroy(swboard);
-- }
--}
--
--static void
--iro_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnSwitchBoard *swboard;
--
-- swboard = cmdproc->data;
--
-- swboard->total_users = atoi(cmd->params[2]);
--
-- msn_switchboard_add_user(swboard, cmd->params[3]);
--}
--
--static void
--joi_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnSession *session;
-- MsnSwitchBoard *swboard;
-- const char *passport;
--
-- passport = cmd->params[0];
--
-- session = cmdproc->session;
-- swboard = cmdproc->data;
--
-- msn_switchboard_add_user(swboard, passport);
--
-- msn_sbconn_process_queue(swboard);
--
-- if (!session->http_method)
-- send_clientcaps(swboard);
--
-- if (swboard->closed)
-- msn_switchboard_close(swboard);
--}
--
--static void
--msg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
--{
-- MsnMessage *msg;
--
-- msg = msn_message_new_from_cmd(cmdproc->session, cmd);
--
-- msn_message_parse_payload(msg, payload, len,
-- MSG_LINE_DEM,MSG_BODY_DEM);
-- if (purple_debug_is_verbose())
-- msn_message_show_readable(msg, "SB RECV", FALSE);
--
-- g_free (msg->remote_user);
-- msg->remote_user = g_strdup(cmd->params[0]);
--
-- msn_cmdproc_process_msg(cmdproc, msg);
--
-- msn_message_unref(msg);
--}
--
--static void
--msg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- cmd->payload_len = atoi(cmd->params[2]);
-- cmdproc->last_cmd->payload_cb = msg_cmd_post;
--}
--
--static void
--ubm_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- purple_debug_misc("msn", "get UBM...\n");
-- cmd->payload_len = atoi(cmd->params[5]);
-- cmdproc->last_cmd->payload_cb = msg_cmd_post;
--}
--
--static void
--nak_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnMessage *msg;
--
-- msg = cmd->trans->data;
-- g_return_if_fail(msg != NULL);
--
-- msg_error_helper(cmdproc, msg, MSN_MSG_ERROR_NAK);
-- cmd->trans->data = NULL;
--}
--
--static void
--ack_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnSwitchBoard *swboard;
-- MsnMessage *msg;
--
-- msg = cmd->trans->data;
--
-- if (msg->part && msg->part->ack_cb != NULL)
-- msg->part->ack_cb(msg->part, msg->part->ack_data);
--
-- swboard = cmdproc->data;
-- if (swboard)
-- swboard->ack_list = g_list_remove(swboard->ack_list, msg);
-- msn_message_unref(msg);
-- cmd->trans->data = NULL;
--}
--
--static void
--out_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- PurpleConnection *gc;
-- MsnSwitchBoard *swboard;
--
-- gc = cmdproc->session->account->gc;
-- swboard = cmdproc->data;
--
-- if (swboard->current_users > 1)
-- serv_got_chat_left(gc, swboard->chat_id);
--
-- msn_switchboard_disconnect(swboard);
--}
--
--static void
--usr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnSwitchBoard *swboard;
--
-- swboard = cmdproc->data;
--
--#if 0
-- GList *l;
--
-- for (l = swboard->users; l != NULL; l = l->next)
-- {
-- const char *user;
-- user = l->data;
--
-- msn_cmdproc_send(cmdproc, "CAL", "%s", user);
-- }
--#endif
--
-- swboard->ready = TRUE;
-- msn_cmdproc_process_queue(cmdproc);
--}
--
--/**************************************************************************
-- * Message Handlers
-- **************************************************************************/
--static void
--clientcaps_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
--{
--#if 0
-- MsnSession *session;
-- MsnSwitchBoard *swboard;
-- MsnUser *user;
-- GHashTable *clientcaps;
-- const char *value;
--
-- char *passport = msg->sender;
--
-- session = cmdproc->session;
-- swboard = cmdproc->servconn->swboard;
--
-- clientcaps = msn_message_get_hashtable_from_body(msg);
--#endif
--}
--
--void
--msn_switchboard_show_ink(MsnSwitchBoard *swboard, const char *passport,
-- const char *data)
--{
-- PurpleConnection *gc;
-- guchar *image_data;
-- size_t image_len;
-- int imgid;
-- char *image_msg;
--
-- if (!purple_str_has_prefix(data, "base64:"))
-- {
-- purple_debug_error("msn", "Ignoring Ink not in Base64 format.\n");
-- return;
-- }
--
-- gc = purple_account_get_connection(swboard->session->account);
--
-- data += sizeof("base64:") - 1;
-- image_data = purple_base64_decode(data, &image_len);
-- if (!image_data || !image_len)
-- {
-- purple_debug_error("msn", "Unable to decode Ink from Base64 format.\n");
-- return;
-- }
--
-- imgid = purple_imgstore_add_with_id(image_data, image_len, NULL);
-- image_msg = g_strdup_printf("<IMG ID='%d'>", imgid);
--
-- if (swboard->current_users > 1 ||
-- ((swboard->conv != NULL) &&
-- purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
-- serv_got_chat_in(gc, swboard->chat_id, passport, 0, image_msg,
-- time(NULL));
-- else
-- serv_got_im(gc, passport, image_msg, 0, time(NULL));
--
-- purple_imgstore_unref_by_id(imgid);
-- g_free(image_msg);
--}
--
--/**************************************************************************
-- * Connect stuff
-- **************************************************************************/
--static void
--ans_usr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error);
--
--static void
--connect_cb(MsnServConn *servconn)
--{
-- MsnSwitchBoard *swboard;
-- MsnTransaction *trans;
-- MsnCmdProc *cmdproc;
-- PurpleAccount *account;
-- char *username;
--
-- cmdproc = servconn->cmdproc;
-- g_return_if_fail(cmdproc != NULL);
--
-- account = cmdproc->session->account;
-- swboard = cmdproc->data;
-- g_return_if_fail(swboard != NULL);
--
-- username = g_strdup_printf("%s;{%s}",
-- purple_account_get_username(account),
-- servconn->session->guid);
--
-- if (msn_switchboard_is_invited(swboard))
-- {
-- swboard->empty = FALSE;
--
-- trans = msn_transaction_new(cmdproc, "ANS", "%s %s %s",
-- username,
-- swboard->auth_key, swboard->session_id);
-- }
-- else
-- {
-- trans = msn_transaction_new(cmdproc, "USR", "%s %s",
-- username,
-- swboard->auth_key);
-- }
--
-- msn_transaction_set_error_cb(trans, ans_usr_error);
-- msn_transaction_set_data(trans, swboard);
-- msn_cmdproc_send_trans(cmdproc, trans);
--
-- g_free(username);
--}
--
--static void
--ans_usr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
--{
-- MsnSwitchBoard *swboard;
-- char **params;
-- char *passport;
-- int reason = MSN_SB_ERROR_UNKNOWN;
--
-- if (error == 911)
-- {
-- reason = MSN_SB_ERROR_AUTHFAILED;
-- }
--
-- purple_debug_warning("msn", "ans_usr_error: command %s gave error %i\n", trans->command, error);
--
-- params = g_strsplit(trans->params, " ", 0);
-- passport = params[0];
-- swboard = trans->data;
--
-- swboard_error_helper(swboard, reason, passport);
--
-- g_strfreev(params);
--}
--
--static void
--disconnect_cb(MsnServConn *servconn)
--{
-- MsnSwitchBoard *swboard;
--
-- swboard = servconn->cmdproc->data;
-- g_return_if_fail(swboard != NULL);
--
-- msn_servconn_set_disconnect_cb(swboard->servconn, NULL);
--
-- msn_switchboard_destroy(swboard);
--}
--
--gboolean
--msn_switchboard_connect(MsnSwitchBoard *swboard, const char *host, int port)
--{
-- g_return_val_if_fail(swboard != NULL, FALSE);
--
-- msn_servconn_set_connect_cb(swboard->servconn, connect_cb);
-- msn_servconn_set_disconnect_cb(swboard->servconn, disconnect_cb);
--
-- return msn_servconn_connect(swboard->servconn, host, port, FALSE);
--}
--
--void
--msn_switchboard_disconnect(MsnSwitchBoard *swboard)
--{
-- g_return_if_fail(swboard != NULL);
--
-- msn_servconn_disconnect(swboard->servconn);
--}
--
--/**************************************************************************
-- * Call stuff
-- **************************************************************************/
--static void
--got_cal(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
--#if 0
-- MsnSwitchBoard *swboard;
-- const char *user;
--
-- swboard = cmdproc->data;
--
-- user = cmd->params[0];
--
-- msn_switchboard_add_user(swboard, user);
--#endif
--}
--
--static void
--cal_timeout(MsnCmdProc *cmdproc, MsnTransaction *trans)
--{
-- purple_debug_warning("msn", "cal_timeout: command %s timed out\n", trans->command);
--
-- cal_error_helper(trans, MSN_SB_ERROR_UNKNOWN);
--}
--
--static void
--cal_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
--{
-- int reason = MSN_SB_ERROR_UNKNOWN;
-- MsnMessage *msg;
-- MsnSwitchBoard *swboard = trans->data;
--
-- if (error == 215)
-- {
-- purple_debug_info("msn", "Invited user already in switchboard\n");
-- return;
-- }
-- else if (error == 217)
-- {
-- reason = MSN_SB_ERROR_USER_OFFLINE;
-- }
--
-- purple_debug_warning("msn", "cal_error: command %s gave error %i\n", trans->command, error);
--
-- while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL){
-- purple_debug_warning("msn", "Unable to send msg: {%s}\n", msg->body);
-- /* The messages could not be sent due to a switchboard error */
-- swboard->error = MSN_SB_ERROR_USER_OFFLINE;
-- msg_error_helper(swboard->cmdproc, msg,
-- MSN_MSG_ERROR_SB);
-- }
-- cal_error_helper(trans, reason);
--}
--
--void
--msn_switchboard_request_add_user(MsnSwitchBoard *swboard, const char *user)
--{
-- MsnTransaction *trans;
-- MsnCmdProc *cmdproc;
--
-- g_return_if_fail(swboard != NULL);
--
-- cmdproc = swboard->cmdproc;
--
-- trans = msn_transaction_new(cmdproc, "CAL", "%s", user);
-- /* this doesn't do anything, but users seem to think that
-- * 'Unhandled command' is some kind of error, so we don't report it */
-- msn_transaction_add_cb(trans, "CAL", got_cal);
--
-- msn_transaction_set_data(trans, swboard);
-- msn_transaction_set_timeout_cb(trans, cal_timeout);
--
-- if (swboard->ready)
-- msn_cmdproc_send_trans(cmdproc, trans);
-- else
-- msn_cmdproc_queue_trans(cmdproc, trans);
--}
--
--/**************************************************************************
-- * Create & Transfer stuff
-- **************************************************************************/
--
--static void
--got_swboard(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
-- MsnSwitchBoard *swboard;
-- char *host;
-- int port;
-- swboard = cmd->trans->data;
--
-- if (g_list_find(cmdproc->session->switches, swboard) == NULL)
-- /* The conversation window was closed. */
-- return;
--
-- purple_debug_info("msn", "Switchboard:auth:{%s} socket:{%s}\n", cmd->params[4], cmd->params[2]);
-- msn_switchboard_set_auth_key(swboard, cmd->params[4]);
--
-- msn_parse_socket(cmd->params[2], &host, &port);
--
-- if (!msn_switchboard_connect(swboard, host, port))
-- msn_switchboard_destroy(swboard);
--
-- g_free(host);
--}
--
--static void
--xfr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
--{
-- MsnSwitchBoard *swboard;
-- int reason = MSN_SB_ERROR_UNKNOWN;
--
-- if (error == 913)
-- reason = MSN_SB_ERROR_OFFLINE;
-- else if (error == 800)
-- reason = MSN_SB_ERROR_TOO_FAST;
--
-- swboard = trans->data;
--
-- purple_debug_info("msn",
-- "xfr_error %i for %s: trans %p, command %s, reason %i\n",
-- error, (swboard->im_user ? swboard->im_user : "(null)"), trans,
-- (trans->command ? trans->command : "(null)"), reason);
--
-- swboard_error_helper(swboard, reason, swboard->im_user);
--}
--
--gboolean
--msn_switchboard_request(MsnSwitchBoard *swboard)
--{
-- MsnCmdProc *cmdproc;
-- MsnTransaction *trans;
--
-- g_return_val_if_fail(swboard != NULL, FALSE);
--
-- cmdproc = swboard->session->notification->cmdproc;
--
-- trans = msn_transaction_new(cmdproc, "XFR", "%s", "SB");
-- msn_transaction_add_cb(trans, "XFR", got_swboard);
--
-- msn_transaction_set_data(trans, swboard);
-- msn_transaction_set_error_cb(trans, xfr_error);
--
-- return msn_cmdproc_send_trans(cmdproc, trans);
--}
--
--void
--msn_switchboard_close(MsnSwitchBoard *swboard)
--{
-- g_return_if_fail(swboard != NULL);
--
-- if (swboard->error != MSN_SB_ERROR_NONE)
-- {
-- msn_switchboard_destroy(swboard);
-- }
-- else if (g_queue_is_empty(swboard->msg_queue) ||
-- !swboard->session->connected)
-- {
-- MsnCmdProc *cmdproc;
-- MsnTransaction *trans;
-- cmdproc = swboard->cmdproc;
-- trans = msn_transaction_new(cmdproc, "OUT", NULL);
-- msn_transaction_set_saveable(trans, FALSE);
-- msn_cmdproc_send_trans(cmdproc, trans);
--
-- msn_switchboard_destroy(swboard);
-- }
-- else
-- {
-- swboard->closed = TRUE;
-- }
--}
--
--void
--msn_switchboard_release(MsnSwitchBoard *swboard, MsnSBFlag flag)
--{
-- g_return_if_fail(swboard != NULL);
--
-- swboard->flag &= ~flag;
--
-- if (flag == MSN_SB_FLAG_IM)
-- /* Forget any conversation that used to be associated with this
-- * swboard. */
-- swboard->conv = NULL;
--
-- if (swboard->flag == 0)
-- /* Nothing else is using this switchboard, so close it */
-- msn_switchboard_close(swboard);
--}
--
--/**************************************************************************
-- * Init stuff
-- **************************************************************************/
--
--void
--msn_switchboard_init(void)
--{
-- cbs_table = msn_table_new();
--
-- msn_table_add_cmd(cbs_table, "ANS", "ANS", ans_cmd);
-- msn_table_add_cmd(cbs_table, "ANS", "IRO", iro_cmd);
--
-- msn_table_add_cmd(cbs_table, "MSG", "ACK", ack_cmd);
-- msn_table_add_cmd(cbs_table, "MSG", "NAK", nak_cmd);
--
-- msn_table_add_cmd(cbs_table, "USR", "USR", usr_cmd);
--
-- msn_table_add_cmd(cbs_table, NULL, "MSG", msg_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "UBM", ubm_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "JOI", joi_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "BYE", bye_cmd);
-- msn_table_add_cmd(cbs_table, NULL, "OUT", out_cmd);
--
--#if 0
-- /* They might skip the history */
-- msn_table_add_cmd(cbs_table, NULL, "ACK", NULL);
--#endif
--
-- msn_table_add_error(cbs_table, "MSG", msg_error);
-- msn_table_add_error(cbs_table, "CAL", cal_error);
--
-- /* Register the message type callbacks. */
-- msn_table_add_msg_type(cbs_table, "text/plain",
-- msn_plain_msg);
-- msn_table_add_msg_type(cbs_table, "text/x-msmsgscontrol",
-- msn_control_msg);
-- msn_table_add_msg_type(cbs_table, "text/x-clientcaps",
-- clientcaps_msg);
-- msn_table_add_msg_type(cbs_table, "text/x-clientinfo",
-- clientcaps_msg);
-- msn_table_add_msg_type(cbs_table, "application/x-msnmsgrp2p",
-- msn_p2p_msg);
-- msn_table_add_msg_type(cbs_table, "text/x-mms-emoticon",
-- msn_emoticon_msg);
-- msn_table_add_msg_type(cbs_table, "text/x-mms-animemoticon",
-- msn_emoticon_msg);
-- msn_table_add_msg_type(cbs_table, "text/x-msnmsgr-datacast",
-- msn_datacast_msg);
-- msn_table_add_msg_type(cbs_table, "text/x-msmsgsinvite",
-- msn_invite_msg);
-- msn_table_add_msg_type(cbs_table, "image/gif",
-- msn_handwritten_msg);
--}
--
--void
--msn_switchboard_end(void)
--{
-- msn_table_destroy(cbs_table);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/switchboard.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/switchboard.h
---- pidgin-2.10.7/libpurple/protocols/msn/switchboard.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/switchboard.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,266 +0,0 @@
--/**
-- * @file switchboard.h MSN switchboard functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_SWITCHBOARD_H
--#define MSN_SWITCHBOARD_H
--
--typedef struct _MsnSwitchBoard MsnSwitchBoard;
--
--/**
-- * A switchboard error.
-- */
--typedef enum
--{
-- MSN_SB_ERROR_NONE, /**< No error. */
-- MSN_SB_ERROR_CAL, /**< The user could not join (answer the call). */
-- MSN_SB_ERROR_OFFLINE, /**< The account is offline. */
-- MSN_SB_ERROR_USER_OFFLINE, /**< The user to call is offline. */
-- MSN_SB_ERROR_CONNECTION, /**< There was a connection error. */
-- MSN_SB_ERROR_TOO_FAST, /**< We are sending too fast */
-- MSN_SB_ERROR_AUTHFAILED, /**< Authentication failed joining the switchboard session */
-- MSN_SB_ERROR_UNKNOWN /**< An unknown error occurred. */
--} MsnSBErrorType;
--
--/**
-- * A switchboard flag.
-- */
--typedef enum
--{
-- MSN_SB_FLAG_IM = 0x01, /**< This switchboard is being used for a conversation. */
-- MSN_SB_FLAG_FT = 0x02 /**< This switchboard is being used for file transfer. */
--} MsnSBFlag;
--
--#include "cmdproc.h"
--#include "msg.h"
--#include "servconn.h"
--#include "session.h"
--
--/**
-- * A switchboard.
-- *
-- * A place where a bunch of users send messages to the rest of the users.
-- */
--struct _MsnSwitchBoard
--{
-- MsnSession *session; /**< Our parent session. */
-- MsnServConn *servconn; /**< The physical connection for this switchboard. */
-- MsnCmdProc *cmdproc; /**< Convenience variable for servconn->cmdproc. */
-- char *im_user;
--
-- MsnSBFlag flag;
-- char *auth_key;
-- char *session_id;
--
-- PurpleConversation *conv; /**< The conversation that displays the
-- messages of this switchboard, or @c NULL if
-- this is a helper switchboard. */
--
-- gboolean empty; /**< A flag that states if the swithcboard has no
-- users in it. */
-- gboolean invited; /**< A flag that states if we were invited to the
-- switchboard. */
-- gboolean ready; /**< A flag that states if this switchboard is
-- ready to be used. */
-- gboolean closed; /**< A flag that states if the switchboard has
-- been closed by the user. */
-- gboolean destroying; /**< A flag that states if the switchboard is
-- alredy on the process of destruction. */
--
-- int current_users;
-- int total_users;
-- GList *users;
--
-- int chat_id;
--
-- GQueue *msg_queue; /**< Queue of messages to send. */
-- GList *ack_list; /**< List of messages waiting for an ack. */
--
-- MsnSBErrorType error; /**< The error that occurred in this switchboard
-- (if applicable). */
-- GList *slplinks; /**< The list of slplinks that are using this switchboard. */
-- guint reconn_timeout_h;
--};
--
--/**
-- * Initialize the variables for switchboard creation.
-- */
--void msn_switchboard_init(void);
--
--/**
-- * Destroy the variables for switchboard creation.
-- */
--void msn_switchboard_end(void);
--
--/**
-- * Creates a new switchboard.
-- *
-- * @param session The MSN session.
-- *
-- * @return The new switchboard.
-- */
--MsnSwitchBoard *msn_switchboard_new(MsnSession *session);
--
--/**
-- * Destroys a switchboard.
-- *
-- * @param swboard The switchboard to destroy.
-- */
--void msn_switchboard_destroy(MsnSwitchBoard *swboard);
--
--/**
-- * Sets the auth key the switchboard must use when connecting.
-- *
-- * @param swboard The switchboard.
-- * @param key The auth key.
-- */
--void msn_switchboard_set_auth_key(MsnSwitchBoard *swboard, const char *key);
--
--/**
-- * Returns the auth key the switchboard must use when connecting.
-- *
-- * @param swboard The switchboard.
-- *
-- * @return The auth key.
-- */
--const char *msn_switchboard_get_auth_key(MsnSwitchBoard *swboard);
--
--/**
-- * Sets the session ID the switchboard must use when connecting.
-- *
-- * @param swboard The switchboard.
-- * @param id The session ID.
-- */
--void msn_switchboard_set_session_id(MsnSwitchBoard *swboard, const char *id);
--
--/**
-- * Returns the session ID the switchboard must use when connecting.
-- *
-- * @param swboard The switchboard.
-- *
-- * @return The session ID.
-- */
--const char *msn_switchboard_get_session_id(MsnSwitchBoard *swboard);
--
--/**
-- * Returns the next chat ID for use by a switchboard.
-- *
-- * @return The chat ID.
-- */
--int msn_switchboard_get_chat_id(void);
--
--/**
-- * Sets whether or not we were invited to this switchboard.
-- *
-- * @param swboard The switchboard.
-- * @param invite @c TRUE if invited, @c FALSE otherwise.
-- */
--void msn_switchboard_set_invited(MsnSwitchBoard *swboard, gboolean invited);
--
--/**
-- * Returns whether or not we were invited to this switchboard.
-- *
-- * @param swboard The switchboard.
-- *
-- * @return @c TRUE if invited, @c FALSE otherwise.
-- */
--gboolean msn_switchboard_is_invited(MsnSwitchBoard *swboard);
--
--/**
-- * Connects to a switchboard.
-- *
-- * @param swboard The switchboard.
-- * @param host The switchboard server host.
-- * @param port The switcbharod server port.
-- *
-- * @return @c TRUE if able to connect, or @c FALSE otherwise.
-- */
--gboolean msn_switchboard_connect(MsnSwitchBoard *swboard,
-- const char *host, int port);
--
--/**
-- * Disconnects from a switchboard.
-- *
-- * @param swboard The switchboard to disconnect from.
-- */
--void msn_switchboard_disconnect(MsnSwitchBoard *swboard);
--
--/**
-- * Closes the switchboard.
-- *
-- * Called when a conversation is closed.
-- *
-- * @param swboard The switchboard to close.
-- */
--void msn_switchboard_close(MsnSwitchBoard *swboard);
--
--/**
-- * Release a switchboard from a certain function.
-- *
-- * @param swboard The switchboard to release.
-- * @param flag The flag that states the function.
-- */
--void msn_switchboard_release(MsnSwitchBoard *swboard, MsnSBFlag flag);
--
--/**
-- * Returns whether or not we currently can send a message through this
-- * switchboard.
-- *
-- * @param swboard The switchboard.
-- *
-- * @return @c TRUE if a message can be sent, @c FALSE otherwise.
-- */
--gboolean msn_switchboard_can_send(MsnSwitchBoard *swboard);
--
--/**
-- * Sends a message through this switchboard.
-- *
-- * @param swboard The switchboard.
-- * @param msg The message.
-- * @param queue A flag that states if we want this message to be queued (in
-- * the case it cannot currently be sent).
-- *
-- * @return @c TRUE if a message can be sent, @c FALSE otherwise.
-- */
--void msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg,
-- gboolean queue);
--
--void
--msg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, MsnMsgErrorType error);
--
--gboolean msn_switchboard_chat_leave(MsnSwitchBoard *swboard);
--gboolean msn_switchboard_chat_invite(MsnSwitchBoard *swboard, const char *who);
--
--gboolean msn_switchboard_request(MsnSwitchBoard *swboard);
--void msn_switchboard_request_add_user(MsnSwitchBoard *swboard, const char *user);
--
--/**
-- * Shows an ink message from this switchboard.
-- *
-- * @param swboard The switchboard.
-- * @param passport The user that sent the ink.
-- * @param data The ink data.
-- */
--void msn_switchboard_show_ink(MsnSwitchBoard *swboard, const char *passport,
-- const char *data);
--
--#endif /* MSN_SWITCHBOARD_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/table.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/table.c
---- pidgin-2.10.7/libpurple/protocols/msn/table.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/table.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,132 +0,0 @@
--/**
-- * @file table.c MSN helper structure
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#include "msn.h"
--#include "table.h"
--
--static void
--null_cmd_cb(MsnCmdProc *cmdproc, MsnCommand *cmd)
--{
--}
--
--static void
--null_error_cb(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
--{
--}
--
--MsnTable *
--msn_table_new()
--{
-- MsnTable *table;
--
-- table = g_new0(MsnTable, 1);
--
-- table->cmds = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify)g_hash_table_destroy);
-- table->msgs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
-- table->errors = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
--
-- table->async = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
-- table->fallback = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
--
-- return table;
--}
--
--void
--msn_table_destroy(MsnTable *table)
--{
-- g_return_if_fail(table != NULL);
--
-- g_hash_table_destroy(table->cmds);
-- g_hash_table_destroy(table->msgs);
-- g_hash_table_destroy(table->errors);
--
-- g_hash_table_destroy(table->async);
-- g_hash_table_destroy(table->fallback);
--
-- g_free(table);
--}
--
--void
--msn_table_add_cmd(MsnTable *table,
-- char *command, char *answer, MsnTransCb cb)
--{
-- GHashTable *cbs;
--
-- g_return_if_fail(table != NULL);
-- g_return_if_fail(answer != NULL);
--
-- cbs = NULL;
--
-- if (command == NULL)
-- {
-- cbs = table->async;
-- }
-- else if (strcmp(command, "fallback") == 0)
-- {
-- cbs = table->fallback;
-- }
-- else
-- {
-- cbs = g_hash_table_lookup(table->cmds, command);
--
-- if (cbs == NULL)
-- {
-- cbs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
-- g_hash_table_insert(table->cmds, command, cbs);
-- }
-- }
--
-- if (cb == NULL)
-- cb = null_cmd_cb;
--
-- g_hash_table_insert(cbs, answer, cb);
--}
--
--void
--msn_table_add_error(MsnTable *table,
-- char *answer, MsnErrorCb cb)
--{
-- g_return_if_fail(table != NULL);
-- g_return_if_fail(answer != NULL);
--
-- if (cb == NULL)
-- cb = null_error_cb;
--
-- g_hash_table_insert(table->errors, answer, cb);
--}
--
--void
--msn_table_add_msg_type(MsnTable *table,
-- char *type, MsnMsgTypeCb cb)
--{
-- g_return_if_fail(table != NULL);
-- g_return_if_fail(type != NULL);
-- g_return_if_fail(cb != NULL);
--
--#if 0
-- if (cb == NULL)
-- cb = null_msg_cb;
--#endif
--
-- g_hash_table_insert(table->msgs, type, cb);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/table.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/table.h
---- pidgin-2.10.7/libpurple/protocols/msn/table.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/table.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,93 +0,0 @@
--/**
-- * @file table.h MSN helper structure
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_TABLE_H
--#define MSN_TABLE_H
--
--typedef struct _MsnTable MsnTable;
--
--#include "cmdproc.h"
--#include "transaction.h"
--#include "msg.h"
--
--typedef void (*MsnMsgTypeCb)(MsnCmdProc *cmdproc, MsnMessage *msg);
--
--struct _MsnTable
--{
-- GHashTable *cmds; /**< Callbacks that manage command response. */
-- GHashTable *msgs; /**< Callbacks that manage incoming messages. */
-- GHashTable *errors; /**< Callbacks that manage command errors. */
--
-- GHashTable *async; /**< Callbacks that manage incoming asyncronous messages. */
-- /* TODO: Does this one is really needed? */
-- GHashTable *fallback; /**< Fallback callback. */
--};
--
--/**
-- * Create a new instance of a MsnTable which map commands, errors and messages
-- * with callbacks that will handle it.
-- *
-- * @return A new MsnTable.
-- */
--MsnTable *msn_table_new(void);
--
--/**
-- * Destroy a MsnTable.
-- *
-- * @param table The MsnTable to be destroyed.
-- */
--void msn_table_destroy(MsnTable *table);
--
--/**
-- * Relate an incomming command from server with a callback able to handle
-- * the event.
-- *
-- * @param table The MsnTable.
-- * @param command If NULL this add an incoming asyncronous command set in answer.
-- * Else, the command sent.
-- * @param answer The server answer to 'command'. If 'command' is NULL,
-- * the asyncronous command sent by the server.
-- * @param cb Callback to handle this event.
-- */
--void msn_table_add_cmd(MsnTable *table, char *command, char *answer,
-- MsnTransCb cb);
--
--/**
-- * Set a callback to handle incoming command errors.
-- *
-- * @param table The MsnTable.
-- * @param answer Incoming command with error.
-- * @param cb Callback to handle this error.
-- */
--void msn_table_add_error(MsnTable *table, char *answer, MsnErrorCb cb);
--
--/**
-- * Relate a message Content-type with a callback able to handle it.
-- *
-- * @param table The MsnTable.
-- * @param type The Message Content-Type.
-- * @param cb Callback to handle this Content-type.
-- */
--void msn_table_add_msg_type(MsnTable *table, char *type, MsnMsgTypeCb cb);
--
--#endif /* MSN_TABLE_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/tlv.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/tlv.c
---- pidgin-2.10.7/libpurple/protocols/msn/tlv.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/tlv.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,458 +0,0 @@
--/**
-- * @file tlv.c MSN TLV functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "tlv.h"
--#include "msnutils.h"
--
--static msn_tlv_t *
--createtlv(guint8 type, guint8 length, guint8 *value)
--{
-- msn_tlv_t *ret;
--
-- ret = g_new(msn_tlv_t, 1);
-- ret->type = type;
-- ret->length = length;
-- ret->value = value;
--
-- return ret;
--}
--
--static void
--freetlv(msn_tlv_t *oldtlv)
--{
-- g_free(oldtlv->value);
-- g_free(oldtlv);
--}
--
--GSList *
--msn_tlvlist_read(const char *bs, size_t bs_len)
--{
-- GSList *list = NULL;
--
-- while (bs_len > 0) {
-- guint8 type, length;
-- msn_tlv_t *tlv;
--
-- if (bs_len == 3 && *bs == 0) {
-- /* Padding to multiple of 4 */
-- break;
-- } else if (bs_len == 2 && *bs == 0) {
-- /* Padding to multiple of 4 */
-- break;
-- } else if (bs_len == 1) {
-- if (*bs == 0) {
-- /* Padding to multiple of 4 */
-- break;
-- } else {
-- /* TLV is not small enough to fit here */
-- msn_tlvlist_free(list);
-- return NULL;
-- }
-- }
--
-- type = msn_pop8(bs);
-- length = msn_pop8(bs);
-- bs_len -= 2;
--
-- if (length > bs_len) {
-- msn_tlvlist_free(list);
-- return NULL;
-- }
--
-- tlv = createtlv(type, length, NULL);
-- if (length > 0) {
-- tlv->value = g_memdup(bs, length);
-- if (!tlv->value) {
-- freetlv(tlv);
-- msn_tlvlist_free(list);
-- return NULL;
-- }
-- }
--
-- bs_len -= length;
-- bs += length;
--
-- list = g_slist_prepend(list, tlv);
-- }
--
-- return g_slist_reverse(list);
--}
--
--GSList *
--msn_tlvlist_copy(GSList *orig)
--{
-- GSList *new = NULL;
-- msn_tlv_t *tlv;
--
-- while (orig != NULL) {
-- tlv = orig->data;
-- msn_tlvlist_add_raw(&new, tlv->type, tlv->length, (const char *)tlv->value);
-- orig = orig->next;
-- }
--
-- return new;
--}
--
--gboolean
--msn_tlvlist_equal(GSList *one, GSList *two)
--{
-- while (one && two) {
-- msn_tlv_t *a = one->data;
-- msn_tlv_t *b = two->data;
--
-- if (a->type != b->type)
-- return FALSE;
-- else if (a->length != b->length)
-- return FALSE;
-- else if (!a->value && b->value)
-- return FALSE;
-- else if (a->value && !b->value)
-- return FALSE;
-- else if (a->value && b->value && memcmp(a->value, b->value, a->length) != 0)
-- return FALSE;
--
-- one = one->next;
-- two = two->next;
-- }
--
-- return one == two;
--}
--
--void
--msn_tlvlist_free(GSList *list)
--{
-- while (list != NULL) {
-- freetlv(list->data);
-- list = g_slist_delete_link(list, list);
-- }
--}
--
--int
--msn_tlvlist_count(GSList *list)
--{
-- return g_slist_length(list);
--}
--
--size_t
--msn_tlvlist_size(GSList *list)
--{
-- int size;
--
-- if (list == NULL)
-- return 0;
--
-- for (size = 0; list; list = list->next)
-- size += (2 + ((msn_tlv_t *)list->data)->length);
--
-- return size;
--}
--
--int
--msn_tlvlist_add_raw(GSList **list, const guint8 type, const guint8 length, const char *value)
--{
-- msn_tlv_t *tlv;
--
-- if (list == NULL)
-- return 0;
--
-- tlv = createtlv(type, length, NULL);
-- if (length > 0)
-- tlv->value = g_memdup(value, length);
--
-- *list = g_slist_append(*list, tlv);
--
-- return tlv->length;
--}
--
--int
--msn_tlvlist_add_8(GSList **list, const guint8 type, const guint8 value)
--{
-- char v8[1];
--
-- msn_write8(v8, value);
--
-- return msn_tlvlist_add_raw(list, type, 1, v8);
--}
--
--int
--msn_tlvlist_add_16(GSList **list, const guint8 type, const guint16 value)
--{
-- char v16[2];
--
-- msn_write16be(v16, value);
--
-- return msn_tlvlist_add_raw(list, type, 2, v16);
--}
--
--int
--msn_tlvlist_add_32(GSList **list, const guint8 type, const guint32 value)
--{
-- char v32[4];
--
-- msn_write32be(v32, value);
--
-- return msn_tlvlist_add_raw(list, type, 4, v32);
--}
--
--int
--msn_tlvlist_add_str(GSList **list, const guint8 type, const char *value)
--{
-- return msn_tlvlist_add_raw(list, type, strlen(value), value);
--}
--
--int
--msn_tlvlist_add_empty(GSList **list, const guint8 type)
--{
-- return msn_tlvlist_add_raw(list, type, 0, NULL);
--}
--
--int
--msn_tlvlist_add_tlv(GSList **list, const msn_tlv_t *tlv)
--{
-- return msn_tlvlist_add_raw(list, tlv->type, tlv->length, (const char *)tlv->value);
--}
--
--int
--msn_tlvlist_replace_raw(GSList **list, const guint8 type, const guint8 length, const char *value)
--{
-- GSList *cur;
-- msn_tlv_t *tlv;
--
-- if (list == NULL)
-- return 0;
--
-- for (cur = *list; cur != NULL; cur = cur->next) {
-- tlv = cur->data;
-- if (tlv->type == type)
-- break;
-- }
--
-- if (cur == NULL)
-- /* TLV does not exist, so add a new one */
-- return msn_tlvlist_add_raw(list, type, length, value);
--
-- g_free(tlv->value);
-- tlv->length = length;
-- if (length > 0) {
-- tlv->value = g_memdup(value, length);
-- } else
-- tlv->value = NULL;
--
-- return length;
--}
--
--int
--msn_tlvlist_replace_str(GSList **list, const guint8 type, const char *str)
--{
-- return msn_tlvlist_replace_raw(list, type, strlen(str), str);
--}
--
--int
--msn_tlvlist_replace_empty(GSList **list, const guint8 type)
--{
-- return msn_tlvlist_replace_raw(list, type, 0, NULL);
--}
--
--int
--msn_tlvlist_replace_8(GSList **list, const guint8 type, const guint8 value)
--{
-- char v8[1];
--
-- msn_write8(v8, value);
--
-- return msn_tlvlist_replace_raw(list, type, 1, v8);
--}
--
--int
--msn_tlvlist_replace_32(GSList **list, const guint8 type, const guint32 value)
--{
-- char v32[4];
--
-- msn_write32be(v32, value);
--
-- return msn_tlvlist_replace_raw(list, type, 4, v32);
--}
--
--int
--msn_tlvlist_replace_tlv(GSList **list, const msn_tlv_t *tlv)
--{
-- return msn_tlvlist_replace_raw(list, tlv->type, tlv->length, (const char *)tlv->value);
--}
--
--void
--msn_tlvlist_remove(GSList **list, const guint8 type)
--{
-- GSList *cur, *next;
-- msn_tlv_t *tlv;
--
-- if (list == NULL || *list == NULL)
-- return;
--
-- cur = *list;
-- while (cur != NULL) {
-- tlv = cur->data;
-- next = cur->next;
--
-- if (tlv->type == type) {
-- /* Delete this TLV */
-- *list = g_slist_delete_link(*list, cur);
-- g_free(tlv->value);
-- g_free(tlv);
-- }
--
-- cur = next;
-- }
--}
--
--char *
--msn_tlvlist_write(GSList *list, size_t *out_len)
--{
-- char *buf;
-- char *tmp;
-- size_t bytes_left;
-- size_t total_len;
--
-- tmp = buf = g_malloc(256);
-- bytes_left = total_len = 256;
--
-- for (; list; list = g_slist_next(list)) {
-- msn_tlv_t *tlv = (msn_tlv_t *)list->data;
--
-- if (G_UNLIKELY(tlv->length + 2 > bytes_left)) {
-- buf = g_realloc(buf, total_len + 256);
-- bytes_left += 256;
-- total_len += 256;
-- tmp = buf + (total_len - bytes_left);
-- }
--
-- msn_push8(tmp, tlv->type);
-- msn_push8(tmp, tlv->length);
-- memcpy(tmp, tlv->value, tlv->length);
-- tmp += tlv->length;
--
-- bytes_left -= (tlv->length + 2);
-- }
--
-- /* Align length to multiple of 4 */
-- total_len = total_len - bytes_left;
-- bytes_left = 4 - total_len % 4;
-- if (bytes_left != 4)
-- memset(tmp, 0, bytes_left);
-- else
-- bytes_left = 0;
--
-- *out_len = total_len + bytes_left;
--
-- return buf;
--}
--
--msn_tlv_t *
--msn_tlv_gettlv(GSList *list, const guint8 type, const int nth)
--{
-- msn_tlv_t *tlv;
-- int i;
--
-- for (i = 0; list != NULL; list = list->next) {
-- tlv = list->data;
-- if (tlv->type == type)
-- i++;
-- if (i >= nth)
-- return tlv;
-- }
--
-- return NULL;
--}
--
--int
--msn_tlv_getlength(GSList *list, const guint8 type, const int nth)
--{
-- msn_tlv_t *tlv;
--
-- tlv = msn_tlv_gettlv(list, type, nth);
-- if (tlv == NULL)
-- return -1;
--
-- return tlv->length;
--}
--
--char *
--msn_tlv_getvalue_as_string(msn_tlv_t *tlv)
--{
-- char *ret;
--
-- ret = g_malloc(tlv->length + 1);
-- memcpy(ret, tlv->value, tlv->length);
-- ret[tlv->length] = '\0';
--
-- return ret;
--}
--
--char *
--msn_tlv_getstr(GSList *list, const guint8 type, const int nth)
--{
-- msn_tlv_t *tlv;
--
-- tlv = msn_tlv_gettlv(list, type, nth);
-- if (tlv == NULL)
-- return NULL;
--
-- return msn_tlv_getvalue_as_string(tlv);
--}
--
--guint8
--msn_tlv_get8(GSList *list, const guint8 type, const int nth)
--{
-- msn_tlv_t *tlv;
--
-- tlv = msn_tlv_gettlv(list, type, nth);
-- if (tlv == NULL)
-- return 0; /* erm */
--
-- return msn_read8((const char *)tlv->value);
--}
--
--guint16
--msn_tlv_get16(GSList *list, const guint8 type, const int nth)
--{
-- msn_tlv_t *tlv;
--
-- tlv = msn_tlv_gettlv(list, type, nth);
-- if (tlv == NULL)
-- return 0; /* erm */
--
-- return msn_read16be((const char *)tlv->value);
--}
--
--guint32
--msn_tlv_get32(GSList *list, const guint8 type, const int nth)
--{
-- msn_tlv_t *tlv;
--
-- tlv = msn_tlv_gettlv(list, type, nth);
-- if (tlv == NULL)
-- return 0; /* erm */
--
-- return msn_read32be((const char *)tlv->value);
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/tlv.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/tlv.h
---- pidgin-2.10.7/libpurple/protocols/msn/tlv.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/tlv.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,77 +0,0 @@
--/**
-- * @file tlv.h MSN TLV functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef MSN_TLV_H
--#define MSN_TLV_H
--
--#include "msn.h"
--
--/* TLV structure */
--typedef struct msn_tlv_s
--{
-- guint8 type;
-- guint8 length;
-- guint8 *value;
--} msn_tlv_t;
--
--/* TLV handling functions */
--char *msn_tlv_getvalue_as_string(msn_tlv_t *tlv);
--
--msn_tlv_t *msn_tlv_gettlv(GSList *list, const guint8 type, const int nth);
--int msn_tlv_getlength(GSList *list, const guint8 type, const int nth);
--char *msn_tlv_getstr(GSList *list, const guint8 type, const int nth);
--guint8 msn_tlv_get8(GSList *list, const guint8 type, const int nth);
--guint16 msn_tlv_get16(GSList *list, const guint8 type, const int nth);
--guint32 msn_tlv_get32(GSList *list, const guint8 type, const int nth);
--
--/* TLV list handling functions */
--GSList *msn_tlvlist_read(const char *bs, size_t bs_len);
--GSList *msn_tlvlist_copy(GSList *orig);
--
--int msn_tlvlist_count(GSList *list);
--size_t msn_tlvlist_size(GSList *list);
--gboolean msn_tlvlist_equal(GSList *one, GSList *two);
--char *msn_tlvlist_write(GSList *list, size_t *out_len);
--void msn_tlvlist_free(GSList *list);
--
--int msn_tlvlist_add_raw(GSList **list, const guint8 type, const guint8 length, const char *value);
--int msn_tlvlist_add_empty(GSList **list, const guint8 type);
--int msn_tlvlist_add_8(GSList **list, const guint8 type, const guint8 value);
--int msn_tlvlist_add_16(GSList **list, const guint8 type, const guint16 value);
--int msn_tlvlist_add_32(GSList **list, const guint8 type, const guint32 value);
--int msn_tlvlist_add_str(GSList **list, const guint8 type, const char *value);
--int msn_tlvlist_add_tlv(GSList **list, const msn_tlv_t *tlv);
--
--int msn_tlvlist_replace_raw(GSList **list, const guint8 type, const guint8 lenth, const char *value);
--int msn_tlvlist_replace_str(GSList **list, const guint8 type, const char *str);
--int msn_tlvlist_replace_empty(GSList **list, const guint8 type);
--int msn_tlvlist_replace_8(GSList **list, const guint8 type, const guint8 value);
--int msn_tlvlist_replace_16(GSList **list, const guint8 type, const guint16 value);
--int msn_tlvlist_replace_32(GSList **list, const guint8 type, const guint32 value);
--int msn_tlvlist_replace_tlv(GSList **list, const msn_tlv_t *tlv);
--
--void msn_tlvlist_remove(GSList **list, const guint8 type);
--
--#endif /* MSN_TLV_H */
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/transaction.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/transaction.c
---- pidgin-2.10.7/libpurple/protocols/msn/transaction.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/transaction.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,247 +0,0 @@
--/**
-- * @file transaction.c MSN transaction functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "msn.h"
--#include "transaction.h"
--
--MsnTransaction *
--msn_transaction_new(MsnCmdProc *cmdproc, const char *command,
-- const char *format, ...)
--{
-- MsnTransaction *trans;
-- va_list arg;
--
-- g_return_val_if_fail(command != NULL, NULL);
--
-- trans = g_new0(MsnTransaction, 1);
--
-- trans->cmdproc = cmdproc;
-- trans->command = g_strdup(command);
-- trans->saveable = TRUE;
--
-- if (format != NULL)
-- {
-- va_start(arg, format);
-- trans->params = g_strdup_vprintf(format, arg);
-- va_end(arg);
-- }
--
-- /* trans->queue = g_queue_new(); */
--
-- return trans;
--}
--
--void
--msn_transaction_destroy(MsnTransaction *trans)
--{
-- g_return_if_fail(trans != NULL);
--
-- g_free(trans->command);
-- g_free(trans->params);
-- g_free(trans->payload);
--
-- if (trans->data_free)
-- trans->data_free(trans->data);
--
--#if 0
-- if (trans->pendent_cmd != NULL)
-- msn_message_unref(trans->pendent_msg);
--#endif
--
--#if 0
-- MsnTransaction *elem;
-- if (trans->queue != NULL)
-- {
-- while ((elem = g_queue_pop_head(trans->queue)) != NULL)
-- msn_transaction_destroy(elem);
--
-- g_queue_free(trans->queue);
-- }
--#endif
--
-- if (trans->callbacks != NULL && trans->has_custom_callbacks)
-- g_hash_table_destroy(trans->callbacks);
--
-- if (trans->timer)
-- purple_timeout_remove(trans->timer);
--
-- g_free(trans);
--}
--
--char *
--msn_transaction_to_string(MsnTransaction *trans)
--{
-- char *str;
--
-- g_return_val_if_fail(trans != NULL, FALSE);
--
-- if (trans->params != NULL)
-- str = g_strdup_printf("%s %u %s\r\n", trans->command, trans->trId, trans->params);
-- else if (trans->saveable)
-- str = g_strdup_printf("%s %u\r\n", trans->command, trans->trId);
-- else
-- str = g_strdup_printf("%s\r\n", trans->command);
--
-- return str;
--}
--
--void
--msn_transaction_queue_cmd(MsnTransaction *trans, MsnCommand *cmd)
--{
-- purple_debug_info("msn", "queueing command.\n");
-- trans->pendent_cmd = cmd;
-- msn_command_ref(cmd);
--}
--
--void
--msn_transaction_unqueue_cmd(MsnTransaction *trans, MsnCmdProc *cmdproc)
--{
-- MsnCommand *cmd;
--
-- if (!cmdproc->servconn->connected)
-- return;
--
-- purple_debug_info("msn", "unqueueing command.\n");
-- cmd = trans->pendent_cmd;
--
-- g_return_if_fail(cmd != NULL);
--
-- msn_cmdproc_process_cmd(cmdproc, cmd);
-- msn_command_unref(cmd);
--
-- trans->pendent_cmd = NULL;
--}
--
--#if 0
--void
--msn_transaction_queue(MsnTransaction *trans, MsnTransaction *elem)
--{
-- if (trans->queue == NULL)
-- trans->queue = g_queue_new();
--
-- g_queue_push_tail(trans->queue, elem);
--}
--
--void
--msn_transaction_unqueue(MsnTransaction *trans, MsnCmdProc *cmdproc)
--{
-- MsnTransaction *elem;
--
-- while ((elem = g_queue_pop_head(trans->queue)) != NULL)
-- msn_cmdproc_send_trans(cmdproc, elem);
--}
--#endif
--
--void
--msn_transaction_set_payload(MsnTransaction *trans,
-- const char *payload, int payload_len)
--{
-- g_return_if_fail(trans != NULL);
-- g_return_if_fail(payload != NULL);
--
-- trans->payload = g_strdup(payload);
-- trans->payload_len = payload_len ? payload_len : strlen(trans->payload);
--}
--
--void
--msn_transaction_set_data(MsnTransaction *trans, void *data)
--{
-- g_return_if_fail(trans != NULL);
--
-- trans->data = data;
--}
--
--void msn_transaction_set_data_free(MsnTransaction *trans, GDestroyNotify fn)
--{
-- g_return_if_fail(trans != NULL);
-- trans->data_free = fn;
--}
--
--void
--msn_transaction_set_saveable(MsnTransaction *trans, gboolean saveable)
--{
-- g_return_if_fail(trans != NULL);
--
-- trans->saveable = saveable;
--}
--
--void
--msn_transaction_add_cb(MsnTransaction *trans, char *answer,
-- MsnTransCb cb)
--{
-- g_return_if_fail(trans != NULL);
-- g_return_if_fail(answer != NULL);
--
-- if (trans->callbacks == NULL)
-- {
-- trans->has_custom_callbacks = TRUE;
-- trans->callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
-- NULL);
-- }
-- else if (trans->has_custom_callbacks != TRUE)
-- g_return_if_reached ();
--
-- g_hash_table_insert(trans->callbacks, answer, cb);
--}
--
--static gboolean
--transaction_timeout(gpointer data)
--{
-- MsnTransaction *trans;
--
-- trans = data;
-- g_return_val_if_fail(trans != NULL, FALSE);
--
--#if 0
-- purple_debug_info("msn", "timed out: %s %d %s\n", trans->command, trans->trId, trans->params);
--#endif
--
-- trans->timer = 0;
--
-- if (trans->timeout_cb != NULL)
-- trans->timeout_cb(trans->cmdproc, trans);
--
-- return FALSE;
--}
--
--void
--msn_transaction_set_timeout_cb(MsnTransaction *trans, MsnTimeoutCb cb)
--{
-- if (trans->timer)
-- {
-- purple_debug_error("msn", "This shouldn't be happening\n");
-- purple_timeout_remove(trans->timer);
-- }
-- trans->timeout_cb = cb;
-- trans->timer = purple_timeout_add_seconds(60, transaction_timeout, trans);
--}
--
--void
--msn_transaction_set_error_cb(MsnTransaction *trans, MsnErrorCb cb)
--{
-- trans->error_cb = cb;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/transaction.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/transaction.h
---- pidgin-2.10.7/libpurple/protocols/msn/transaction.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/transaction.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,87 +0,0 @@
--/**
-- * @file transaction.h MSN transaction functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_TRANSACTION_H
--#define MSN_TRANSACTION_H
--
--#include "internal.h"
--
--typedef struct _MsnTransaction MsnTransaction;
--
--#include "cmdproc.h"
--#include "command.h"
--
--typedef void (*MsnTransCb)(MsnCmdProc *cmdproc, MsnCommand *cmd);
--typedef void (*MsnTimeoutCb)(MsnCmdProc *cmdproc, MsnTransaction *trans);
--typedef void (*MsnErrorCb)(MsnCmdProc *cmdproc, MsnTransaction *trans,
-- int error);
--
--/**
-- * A transaction. A sending command that will initiate the transaction.
-- */
--struct _MsnTransaction
--{
-- MsnCmdProc *cmdproc;
--
-- gboolean saveable; /**< Whether to save this transaction in the history */
-- unsigned int trId; /**< The ID of this transaction, if it's being saved */
--
-- char *command;
-- char *params;
--
-- guint timer;
--
-- void *data; /**< The data to be used on the different callbacks. */
-- GDestroyNotify data_free; /**< The function to free 'data', or @c NULL */
--
-- GHashTable *callbacks;
-- gboolean has_custom_callbacks;
-- MsnErrorCb error_cb;
-- MsnTimeoutCb timeout_cb;
--
-- char *payload;
-- size_t payload_len;
--
-- GQueue *queue;
-- MsnCommand *pendent_cmd; /**< The command that is waiting for the result of
-- this transaction. */
--};
--
--MsnTransaction *msn_transaction_new(MsnCmdProc *cmdproc, const char *command,
-- const char *format, ...) G_GNUC_PRINTF(3, 4);
--void msn_transaction_destroy(MsnTransaction *trans);
--
--char *msn_transaction_to_string(MsnTransaction *trans);
--void msn_transaction_queue_cmd(MsnTransaction *trans, MsnCommand *cmd);
--void msn_transaction_unqueue_cmd(MsnTransaction *trans, MsnCmdProc *cmdproc);
--void msn_transaction_set_payload(MsnTransaction *trans,
-- const char *payload, int payload_len);
--void msn_transaction_set_data(MsnTransaction *trans, void *data);
--void msn_transaction_set_data_free(MsnTransaction *trans, GDestroyNotify fn);
--void msn_transaction_set_saveable(MsnTransaction *trans, gboolean saveable);
--void msn_transaction_add_cb(MsnTransaction *trans, char *answer,
-- MsnTransCb cb);
--void msn_transaction_set_error_cb(MsnTransaction *trans, MsnErrorCb cb);
--void msn_transaction_set_timeout_cb(MsnTransaction *trans, MsnTimeoutCb cb);
--
--#endif /* MSN_TRANSACTION_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/user.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/user.c
---- pidgin-2.10.7/libpurple/protocols/msn/user.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/user.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,801 +0,0 @@
--/**
-- * @file user.c User functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--#include "util.h"
--
--#include "user.h"
--#include "slp.h"
--
--static void free_user_endpoint(MsnUserEndpoint *data)
--{
-- g_free(data->id);
-- g_free(data->name);
-- g_free(data);
--}
--
--/*new a user object*/
--MsnUser *
--msn_user_new(MsnUserList *userlist, const char *passport,
-- const char *friendly_name)
--{
-- MsnUser *user;
--
-- user = g_new0(MsnUser, 1);
--
-- user->userlist = userlist;
--
-- msn_user_set_passport(user, passport);
-- msn_user_set_friendly_name(user, friendly_name);
--
-- return msn_user_ref(user);
--}
--
--/*destroy a user object*/
--static void
--msn_user_destroy(MsnUser *user)
--{
-- while (user->endpoints != NULL) {
-- free_user_endpoint(user->endpoints->data);
-- user->endpoints = g_slist_delete_link(user->endpoints, user->endpoints);
-- }
--
-- if (user->clientcaps != NULL)
-- g_hash_table_destroy(user->clientcaps);
--
-- if (user->group_ids != NULL)
-- {
-- GList *l;
-- for (l = user->group_ids; l != NULL; l = l->next)
-- {
-- g_free(l->data);
-- }
-- g_list_free(user->group_ids);
-- }
--
-- if (user->msnobj != NULL)
-- msn_object_destroy(user->msnobj);
--
-- g_free(user->passport);
-- g_free(user->friendly_name);
-- g_free(user->uid);
-- if (user->extinfo) {
-- g_free(user->extinfo->media_album);
-- g_free(user->extinfo->media_artist);
-- g_free(user->extinfo->media_title);
-- g_free(user->extinfo->phone_home);
-- g_free(user->extinfo->phone_mobile);
-- g_free(user->extinfo->phone_work);
-- g_free(user->extinfo);
-- }
-- g_free(user->statusline);
-- g_free(user->invite_message);
--
-- g_free(user);
--}
--
--MsnUser *
--msn_user_ref(MsnUser *user)
--{
-- g_return_val_if_fail(user != NULL, NULL);
--
-- user->refcount++;
--
-- return user;
--}
--
--void
--msn_user_unref(MsnUser *user)
--{
-- g_return_if_fail(user != NULL);
--
-- user->refcount--;
--
-- if(user->refcount == 0)
-- msn_user_destroy(user);
--}
--
--void
--msn_user_update(MsnUser *user)
--{
-- PurpleAccount *account;
-- gboolean offline;
--
-- g_return_if_fail(user != NULL);
--
-- account = user->userlist->session->account;
--
-- offline = (user->status == NULL);
--
-- if (!offline) {
-- purple_prpl_got_user_status(account, user->passport, user->status,
-- "message", user->statusline, NULL);
-- } else {
-- if (user->mobile) {
-- purple_prpl_got_user_status(account, user->passport, "mobile", NULL);
-- purple_prpl_got_user_status(account, user->passport, "available", NULL);
-- } else {
-- purple_prpl_got_user_status(account, user->passport, "offline", NULL);
-- }
-- }
--
-- if (!offline || !user->mobile) {
-- purple_prpl_got_user_status_deactive(account, user->passport, "mobile");
-- }
--
-- if (!offline && user->extinfo && user->extinfo->media_type != CURRENT_MEDIA_UNKNOWN) {
-- if (user->extinfo->media_type == CURRENT_MEDIA_MUSIC) {
-- purple_prpl_got_user_status(account, user->passport, "tune",
-- PURPLE_TUNE_ARTIST, user->extinfo->media_artist,
-- PURPLE_TUNE_ALBUM, user->extinfo->media_album,
-- PURPLE_TUNE_TITLE, user->extinfo->media_title,
-- NULL);
-- } else if (user->extinfo->media_type == CURRENT_MEDIA_GAMES) {
-- purple_prpl_got_user_status(account, user->passport, "tune",
-- "game", user->extinfo->media_title,
-- NULL);
-- } else if (user->extinfo->media_type == CURRENT_MEDIA_OFFICE) {
-- purple_prpl_got_user_status(account, user->passport, "tune",
-- "office", user->extinfo->media_title,
-- NULL);
-- } else {
-- purple_debug_warning("msn", "Got CurrentMedia with unknown type %d.\n",
-- user->extinfo->media_type);
-- }
-- } else {
-- purple_prpl_got_user_status_deactive(account, user->passport, "tune");
-- }
--
-- if (user->idle)
-- purple_prpl_got_user_idle(account, user->passport, TRUE, -1);
-- else
-- purple_prpl_got_user_idle(account, user->passport, FALSE, 0);
--}
--
--void
--msn_user_set_state(MsnUser *user, const char *state)
--{
-- const char *status;
--
-- g_return_if_fail(user != NULL);
--
-- if (state == NULL) {
-- user->status = NULL;
-- return;
-- }
--
-- if (!g_ascii_strcasecmp(state, "BSY"))
-- status = "busy";
-- else if (!g_ascii_strcasecmp(state, "BRB"))
-- status = "brb";
-- else if (!g_ascii_strcasecmp(state, "AWY"))
-- status = "away";
-- else if (!g_ascii_strcasecmp(state, "PHN"))
-- status = "phone";
-- else if (!g_ascii_strcasecmp(state, "LUN"))
-- status = "lunch";
-- else if (!g_ascii_strcasecmp(state, "HDN"))
-- status = NULL;
-- else
-- status = "available";
--
-- if (!g_ascii_strcasecmp(state, "IDL"))
-- user->idle = TRUE;
-- else
-- user->idle = FALSE;
--
-- user->status = status;
--}
--
--void
--msn_user_set_passport(MsnUser *user, const char *passport)
--{
-- g_return_if_fail(user != NULL);
--
-- g_free(user->passport);
-- user->passport = g_strdup(passport);
--}
--
--gboolean
--msn_user_set_friendly_name(MsnUser *user, const char *name)
--{
-- g_return_val_if_fail(user != NULL, FALSE);
--
-- if (!name)
-- return FALSE;
--
-- if (user->friendly_name && (!strcmp(user->friendly_name, name) ||
-- !strcmp(user->passport, name)))
-- return FALSE;
--
-- g_free(user->friendly_name);
-- user->friendly_name = g_strdup(name);
--
-- serv_got_alias(purple_account_get_connection(user->userlist->session->account),
-- user->passport, name);
-- return TRUE;
--}
--
--void
--msn_user_set_statusline(MsnUser *user, const char *statusline)
--{
-- g_return_if_fail(user != NULL);
--
-- g_free(user->statusline);
-- user->statusline = g_strdup(statusline);
--}
--
--void
--msn_user_set_uid(MsnUser *user, const char *uid)
--{
-- g_return_if_fail(user != NULL);
--
-- g_free(user->uid);
-- user->uid = g_strdup(uid);
--}
--
--void
--msn_user_set_endpoint_data(MsnUser *user, const char *input, MsnUserEndpoint *newep)
--{
-- MsnUserEndpoint *ep;
-- char *endpoint;
-- GSList *l;
--
-- g_return_if_fail(user != NULL);
-- g_return_if_fail(input != NULL);
--
-- endpoint = g_ascii_strdown(input, -1);
--
-- for (l = user->endpoints; l; l = l->next) {
-- ep = l->data;
-- if (g_str_equal(ep->id, endpoint)) {
-- /* We have info about this endpoint! */
--
-- g_free(endpoint);
--
-- if (newep == NULL) {
-- /* Delete it and exit */
-- user->endpoints = g_slist_delete_link(user->endpoints, l);
-- free_user_endpoint(ep);
-- return;
-- }
--
-- /* Break out of our loop and update it */
-- break;
-- }
-- }
-- if (l == NULL) {
-- /* Need to add a new endpoint */
-- ep = g_new0(MsnUserEndpoint, 1);
-- ep->id = endpoint;
-- user->endpoints = g_slist_prepend(user->endpoints, ep);
-- }
--
-- ep->clientid = newep->clientid;
-- ep->extcaps = newep->extcaps;
--}
--
--void
--msn_user_clear_endpoints(MsnUser *user)
--{
-- MsnUserEndpoint *ep;
-- GSList *l;
--
-- g_return_if_fail(user != NULL);
--
-- for (l = user->endpoints; l; l = g_slist_delete_link(l, l)) {
-- ep = l->data;
-- free_user_endpoint(ep);
-- }
--
-- user->endpoints = NULL;
--}
--
--void
--msn_user_set_op(MsnUser *user, MsnListOp list_op)
--{
-- g_return_if_fail(user != NULL);
--
-- user->list_op |= list_op;
--}
--
--void
--msn_user_unset_op(MsnUser *user, MsnListOp list_op)
--{
-- g_return_if_fail(user != NULL);
--
-- user->list_op &= ~list_op;
--}
--
--void
--msn_user_set_buddy_icon(MsnUser *user, PurpleStoredImage *img)
--{
-- MsnObject *msnobj;
--
-- g_return_if_fail(user != NULL);
--
-- msnobj = msn_object_new_from_image(img, "TFR2C2.tmp",
-- user->passport, MSN_OBJECT_USERTILE);
--
-- if (!msnobj)
-- purple_debug_error("msn", "Unable to open buddy icon from %s!\n", user->passport);
--
-- msn_user_set_object(user, msnobj);
--}
--
--/*add group id to User object*/
--void
--msn_user_add_group_id(MsnUser *user, const char* group_id)
--{
-- MsnUserList *userlist;
-- PurpleAccount *account;
-- PurpleBuddy *b;
-- PurpleGroup *g;
-- const char *passport;
-- const char *group_name;
--
-- g_return_if_fail(user != NULL);
-- g_return_if_fail(group_id != NULL);
--
-- user->group_ids = g_list_append(user->group_ids, g_strdup(group_id));
--
-- userlist = user->userlist;
-- account = userlist->session->account;
-- passport = msn_user_get_passport(user);
--
-- group_name = msn_userlist_find_group_name(userlist, group_id);
--
-- purple_debug_info("msn", "User: group id:%s,name:%s,user:%s\n", group_id, group_name, passport);
--
-- g = purple_find_group(group_name);
--
-- if ((group_id == NULL) && (g == NULL))
-- {
-- g = purple_group_new(group_name);
-- purple_blist_add_group(g, NULL);
-- }
--
-- b = purple_find_buddy_in_group(account, passport, g);
-- if (b == NULL)
-- {
-- b = purple_buddy_new(account, passport, NULL);
-- purple_blist_add_buddy(b, NULL, g, NULL);
-- }
-- purple_buddy_set_protocol_data(b, user);
-- /*Update the blist Node info*/
--}
--
--/*check if the msn user is online*/
--gboolean
--msn_user_is_online(PurpleAccount *account, const char *name)
--{
-- PurpleBuddy *buddy;
--
-- buddy = purple_find_buddy(account, name);
-- return PURPLE_BUDDY_IS_ONLINE(buddy);
--}
--
--gboolean
--msn_user_is_yahoo(PurpleAccount *account, const char *name)
--{
-- MsnSession *session = NULL;
-- MsnUser *user;
-- PurpleConnection *gc;
--
-- gc = purple_account_get_connection(account);
-- if (gc != NULL)
-- session = gc->proto_data;
--
-- if ((session != NULL) && (user = msn_userlist_find_user(session->userlist, name)) != NULL)
-- {
-- return (user->networkid == MSN_NETWORK_YAHOO);
-- }
-- return (strstr(name,"@yahoo.") != NULL);
--}
--
--void
--msn_user_remove_group_id(MsnUser *user, const char *id)
--{
-- GList *l;
--
-- g_return_if_fail(user != NULL);
-- g_return_if_fail(id != NULL);
--
-- l = g_list_find_custom(user->group_ids, id, (GCompareFunc)strcmp);
--
-- if (l == NULL)
-- return;
--
-- g_free(l->data);
-- user->group_ids = g_list_delete_link(user->group_ids, l);
--}
--
--void
--msn_user_set_pending_group(MsnUser *user, const char *group)
--{
-- user->pending_group = g_strdup(group);
--}
--
--char *
--msn_user_remove_pending_group(MsnUser *user)
--{
-- char *group = user->pending_group;
-- user->pending_group = NULL;
-- return group;
--}
--
--void
--msn_user_set_home_phone(MsnUser *user, const char *number)
--{
-- g_return_if_fail(user != NULL);
--
-- if (!number && !user->extinfo)
-- return;
--
-- if (user->extinfo)
-- g_free(user->extinfo->phone_home);
-- else
-- user->extinfo = g_new0(MsnUserExtendedInfo, 1);
--
-- user->extinfo->phone_home = g_strdup(number);
--}
--
--void
--msn_user_set_work_phone(MsnUser *user, const char *number)
--{
-- g_return_if_fail(user != NULL);
--
-- if (!number && !user->extinfo)
-- return;
--
-- if (user->extinfo)
-- g_free(user->extinfo->phone_work);
-- else
-- user->extinfo = g_new0(MsnUserExtendedInfo, 1);
--
-- user->extinfo->phone_work = g_strdup(number);
--}
--
--void
--msn_user_set_mobile_phone(MsnUser *user, const char *number)
--{
-- g_return_if_fail(user != NULL);
--
-- if (!number && !user->extinfo)
-- return;
--
-- if (user->extinfo)
-- g_free(user->extinfo->phone_mobile);
-- else
-- user->extinfo = g_new0(MsnUserExtendedInfo, 1);
--
-- user->extinfo->phone_mobile = g_strdup(number);
--}
--
--void
--msn_user_set_clientid(MsnUser *user, guint clientid)
--{
-- g_return_if_fail(user != NULL);
--
-- user->clientid = clientid;
--}
--
--void
--msn_user_set_extcaps(MsnUser *user, guint extcaps)
--{
-- g_return_if_fail(user != NULL);
--
-- user->extcaps = extcaps;
--}
--
--void
--msn_user_set_network(MsnUser *user, MsnNetwork network)
--{
-- g_return_if_fail(user != NULL);
--
-- user->networkid = network;
--}
--
--static gboolean
--buddy_icon_cached(PurpleConnection *gc, MsnObject *obj)
--{
-- PurpleAccount *account;
-- PurpleBuddy *buddy;
-- const char *old;
-- const char *new;
--
-- g_return_val_if_fail(obj != NULL, FALSE);
--
-- account = purple_connection_get_account(gc);
--
-- buddy = purple_find_buddy(account, msn_object_get_creator(obj));
-- if (buddy == NULL)
-- return FALSE;
--
-- old = purple_buddy_icons_get_checksum_for_user(buddy);
-- new = msn_object_get_sha1(obj);
--
-- if (new == NULL)
-- return FALSE;
--
-- /* If the old and new checksums are the same, and the file actually exists,
-- * then return TRUE */
-- if (old != NULL && !strcmp(old, new))
-- return TRUE;
--
-- return FALSE;
--}
--
--static void
--queue_buddy_icon_request(MsnUser *user)
--{
-- PurpleAccount *account;
-- MsnObject *obj;
-- GQueue *queue;
--
-- g_return_if_fail(user != NULL);
--
-- account = user->userlist->session->account;
--
-- obj = msn_user_get_object(user);
--
-- if (obj == NULL) {
-- purple_buddy_icons_set_for_user(account, user->passport, NULL, 0, NULL);
-- return;
-- }
--
-- if (!buddy_icon_cached(account->gc, obj)) {
-- MsnUserList *userlist;
--
-- userlist = user->userlist;
-- queue = userlist->buddy_icon_requests;
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "Queueing buddy icon request for %s (buddy_icon_window = %i)\n",
-- user->passport, userlist->buddy_icon_window);
--
-- g_queue_push_tail(queue, user);
--
-- if (userlist->buddy_icon_window > 0)
-- msn_release_buddy_icon_request(userlist);
-- }
--}
--
--void
--msn_user_set_object(MsnUser *user, MsnObject *obj)
--{
-- g_return_if_fail(user != NULL);
--
-- if (user->msnobj != NULL && !msn_object_find_local(msn_object_get_sha1(obj)))
-- msn_object_destroy(user->msnobj);
--
-- user->msnobj = obj;
--
-- if (user->list_op & MSN_LIST_FL_OP)
-- queue_buddy_icon_request(user);
--}
--
--void
--msn_user_set_client_caps(MsnUser *user, GHashTable *info)
--{
-- g_return_if_fail(user != NULL);
-- g_return_if_fail(info != NULL);
--
-- if (user->clientcaps != NULL)
-- g_hash_table_destroy(user->clientcaps);
--
-- user->clientcaps = info;
--}
--
--void
--msn_user_set_invite_message(MsnUser *user, const char *message)
--{
-- g_return_if_fail(user != NULL);
--
-- g_free(user->invite_message);
-- user->invite_message = g_strdup(message);
--}
--
--const char *
--msn_user_get_passport(const MsnUser *user)
--{
-- g_return_val_if_fail(user != NULL, NULL);
--
-- return user->passport;
--}
--
--const char *
--msn_user_get_friendly_name(const MsnUser *user)
--{
-- g_return_val_if_fail(user != NULL, NULL);
--
-- return user->friendly_name;
--}
--
--const char *
--msn_user_get_home_phone(const MsnUser *user)
--{
-- g_return_val_if_fail(user != NULL, NULL);
--
-- return user->extinfo ? user->extinfo->phone_home : NULL;
--}
--
--const char *
--msn_user_get_work_phone(const MsnUser *user)
--{
-- g_return_val_if_fail(user != NULL, NULL);
--
-- return user->extinfo ? user->extinfo->phone_work : NULL;
--}
--
--const char *
--msn_user_get_mobile_phone(const MsnUser *user)
--{
-- g_return_val_if_fail(user != NULL, NULL);
--
-- return user->extinfo ? user->extinfo->phone_mobile : NULL;
--}
--
--guint
--msn_user_get_clientid(const MsnUser *user)
--{
-- g_return_val_if_fail(user != NULL, 0);
--
-- return user->clientid;
--}
--
--guint
--msn_user_get_extcaps(const MsnUser *user)
--{
-- g_return_val_if_fail(user != NULL, 0);
--
-- return user->extcaps;
--}
--
--MsnUserEndpoint *
--msn_user_get_endpoint_data(MsnUser *user, const char *input)
--{
-- char *endpoint;
-- GSList *l;
-- MsnUserEndpoint *ep;
--
-- g_return_val_if_fail(user != NULL, NULL);
-- g_return_val_if_fail(input != NULL, NULL);
--
-- endpoint = g_ascii_strdown(input, -1);
--
-- for (l = user->endpoints; l; l = l->next) {
-- ep = l->data;
-- if (g_str_equal(ep->id, endpoint)) {
-- g_free(endpoint);
-- return ep;
-- }
-- }
--
-- g_free(endpoint);
--
-- return NULL;
--}
--
--MsnNetwork
--msn_user_get_network(const MsnUser *user)
--{
-- g_return_val_if_fail(user != NULL, MSN_NETWORK_UNKNOWN);
--
-- return user->networkid;
--}
--
--MsnObject *
--msn_user_get_object(const MsnUser *user)
--{
-- g_return_val_if_fail(user != NULL, NULL);
--
-- return user->msnobj;
--}
--
--GHashTable *
--msn_user_get_client_caps(const MsnUser *user)
--{
-- g_return_val_if_fail(user != NULL, NULL);
--
-- return user->clientcaps;
--}
--
--const char *
--msn_user_get_invite_message(const MsnUser *user)
--{
-- g_return_val_if_fail(user != NULL, NULL);
--
-- return user->invite_message;
--}
--
--gboolean
--msn_user_is_capable(MsnUser *user, char *endpoint, guint capability, guint extcap)
--{
-- g_return_val_if_fail(user != NULL, FALSE);
--
-- if (endpoint != NULL) {
-- MsnUserEndpoint *ep = msn_user_get_endpoint_data(user, endpoint);
-- if (ep != NULL)
-- return (ep->clientid & capability) && (ep->extcaps & extcap);
-- else
-- return FALSE;
-- }
--
-- return (user->clientid & capability) && (user->extcaps & extcap);
--}
--
--/**************************************************************************
-- * Utility functions
-- **************************************************************************/
--
--int
--msn_user_passport_cmp(MsnUser *user, const char *passport)
--{
-- const char *str;
-- char *pass;
-- int result;
--
-- str = purple_normalize_nocase(NULL, msn_user_get_passport(user));
-- pass = g_strdup(str);
--
--#if GLIB_CHECK_VERSION(2,16,0)
-- result = g_strcmp0(pass, purple_normalize_nocase(NULL, passport));
--#else
-- str = purple_normalize_nocase(NULL, passport);
-- if (!pass)
-- result = -(pass != str);
-- else if (!str)
-- result = pass != str;
-- else
-- result = strcmp(pass, str);
--#endif /* GLIB < 2.16.0 */
--
-- g_free(pass);
--
-- return result;
--}
--
--gboolean
--msn_user_is_in_group(MsnUser *user, const char * group_id)
--{
-- if (user == NULL)
-- return FALSE;
--
-- if (group_id == NULL)
-- return FALSE;
--
-- return (g_list_find_custom(user->group_ids, group_id, (GCompareFunc)strcmp)) != NULL;
--}
--
--gboolean
--msn_user_is_in_list(MsnUser *user, MsnListId list_id)
--{
-- if (user == NULL)
-- return FALSE;
--
-- return (user->list_op & (1 << list_id));
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/user.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/user.h
---- pidgin-2.10.7/libpurple/protocols/msn/user.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/user.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,533 +0,0 @@
--/**
-- * @file user.h User functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_USER_H
--#define MSN_USER_H
--
--typedef struct _MsnUser MsnUser;
--
--typedef enum
--{
-- MSN_NETWORK_UNKNOWN = 0,
-- MSN_NETWORK_PASSPORT = 1,
-- MSN_NETWORK_COMMUNICATOR = 2,
-- MSN_NETWORK_MOBILE = 4,
-- MSN_NETWORK_MNI = 8,
-- MSN_NETWORK_CIRCLE = 9,
-- MSN_NETWORK_TEMP_GROUP = 10,
-- MSN_NETWORK_CID = 11,
-- MSN_NETWORK_CONNECT = 13,
-- MSN_NETWORK_REMOTE = 14,
-- MSN_NETWORK_SMTP = 16,
-- MSN_NETWORK_YAHOO = 32
--} MsnNetwork;
--
--/**
-- * Current media.
-- */
--typedef enum
--{
-- CURRENT_MEDIA_UNKNOWN,
-- CURRENT_MEDIA_MUSIC,
-- CURRENT_MEDIA_GAMES,
-- CURRENT_MEDIA_OFFICE
--} CurrentMediaType;
--
--#include "object.h"
--#include "session.h"
--#include "userlist.h"
--
--/**
-- * Contains optional info about a user that is fairly uncommon. We
-- * put this info in in a separate struct to save memory because we
-- * allocate an MsnUser struct for each buddy, but we generally only
-- * need this information for a small percentage of our buddies
-- * (usually less than 1%). Putting it in a separate struct makes
-- * MsnUser smaller by the size of a few pointers.
-- */
--typedef struct _MsnUserExtendedInfo
--{
-- CurrentMediaType media_type; /**< Type of the user's current media. */
-- char *media_title; /**< Title of the user's current media. */
-- char *media_artist; /**< Artist of the user's current media. */
-- char *media_album; /**< Album of the user's current media. */
--
-- char *phone_home; /**< E.T. uses this. */
-- char *phone_work; /**< Work phone number. */
-- char *phone_mobile; /**< Mobile phone number. */
--} MsnUserExtendedInfo;
--
--/**
-- * A user.
-- */
--struct _MsnUser
--{
-- MsnUserList *userlist;
--
-- guint8 refcount; /**< The reference count of this object */
--
-- char *passport; /**< The passport account. */
-- char *friendly_name; /**< The friendly name. */
--
-- char *uid; /*< User ID */
-- GSList *endpoints; /*< Endpoint-specific data */
--
-- const char *status; /**< The state of the user. */
-- char *statusline; /**< The state of the user. */
--
-- gboolean idle; /**< The idle state of the user. */
--
-- MsnUserExtendedInfo *extinfo; /**< Extended info for the user. */
--
-- gboolean authorized; /**< Authorized to add this user. */
-- gboolean mobile; /**< Signed up with MSN Mobile. */
--
-- GList *group_ids; /**< The group IDs. */
-- char *pending_group; /**< A pending group to add. */
--
-- MsnObject *msnobj; /**< The user's MSN Object. */
--
-- GHashTable *clientcaps; /**< The client's capabilities. */
--
-- guint clientid; /**< The client's ID */
-- guint extcaps; /**< The client's extended capabilities */
--
-- MsnNetwork networkid; /**< The user's network */
--
-- MsnListOp list_op; /**< Which lists the user is in */
--
-- /**
-- * The membershipId for this buddy on our pending list. Sent by
-- * the contact's server
-- */
-- guint member_id_on_pending_list;
--
-- char *invite_message; /**< Invite message of user request */
--};
--
--/**
-- * A specific user endpoint.
-- */
--typedef struct MsnUserEndpoint {
-- char *id; /**< The client's endpoint ID */
-- char *name; /**< The client's endpoint's name */
-- int type; /**< The client's endpoint type */
-- guint clientid; /**< The client's ID */
-- guint extcaps; /**< The client's extended capabilites */
--
--} MsnUserEndpoint;
--
--/**************************************************************************
-- ** @name User API *
-- **************************************************************************/
--/*@{*/
--
--/**
-- * Creates a new user structure.
-- *
-- * @param session The MSN session.
-- * @param passport The initial passport.
-- * @param stored_name The initial stored name.
-- *
-- * @return A new user structure. It will have a reference count of 1.
-- */
--MsnUser *msn_user_new(MsnUserList *userlist, const char *passport,
-- const char *friendly_name);
--
--/**
-- * Increment the reference count.
-- *
-- * @param user The user.
-- *
-- * @return user.
-- */
--MsnUser *msn_user_ref(MsnUser *user);
--
--/**
-- * Decrement the reference count. When the count reaches 0 the object is
-- * automatically freed.
-- *
-- * @param user The user
-- */
--void msn_user_unref(MsnUser *user);
--
--/**
-- * Updates the user.
-- *
-- * Communicates with the core to update the ui, etc.
-- *
-- * @param user The user to update.
-- */
--void msn_user_update(MsnUser *user);
--
-- /**
-- * Sets the new statusline of user.
-- *
-- * @param user The user.
-- * @param state The statusline string.
-- */
--void msn_user_set_statusline(MsnUser *user, const char *statusline);
--
--/**
-- * Sets the new state of user.
-- *
-- * @param user The user.
-- * @param state The state string.
-- */
--void msn_user_set_state(MsnUser *user, const char *state);
--
--/**
-- * Sets the passport account for a user.
-- *
-- * @param user The user.
-- * @param passport The passport account.
-- */
--void msn_user_set_passport(MsnUser *user, const char *passport);
--
--/**
-- * Sets the friendly name for a user.
-- *
-- * @param user The user.
-- * @param name The friendly name.
-- *
-- * @returns TRUE is name actually changed, FALSE otherwise.
-- */
--gboolean msn_user_set_friendly_name(MsnUser *user, const char *name);
--
--/**
-- * Sets the buddy icon for a local user.
-- *
-- * @param user The user.
-- * @param img The buddy icon image
-- */
--void msn_user_set_buddy_icon(MsnUser *user, PurpleStoredImage *img);
--
--/**
-- * Sets the group ID list for a user.
-- *
-- * @param user The user.
-- * @param ids The group ID list.
-- */
--void msn_user_set_group_ids(MsnUser *user, GList *ids);
--
--/**
-- * Adds the group ID for a user.
-- *
-- * @param user The user.
-- * @param id The group ID.
-- */
--void msn_user_add_group_id(MsnUser *user, const char * id);
--
--/**
-- * Removes the group ID from a user.
-- *
-- * @param user The user.
-- * @param id The group ID.
-- */
--void msn_user_remove_group_id(MsnUser *user, const char * id);
--
--/**
-- * Sets the pending group for a user.
-- *
-- * @param user The user.
-- * @param group The group name.
-- */
--void msn_user_set_pending_group(MsnUser *user, const char *group);
--
--/**
-- * Removes the pending group from a user.
-- *
-- * @param user The user.
-- *
-- * @return Returns the pending group name.
-- */
--char *msn_user_remove_pending_group(MsnUser *user);
--
--/**
-- * Sets the home phone number for a user.
-- *
-- * @param user The user.
-- * @param number The home phone number.
-- */
--void msn_user_set_home_phone(MsnUser *user, const char *number);
--
--/**
-- * Sets the work phone number for a user.
-- *
-- * @param user The user.
-- * @param number The work phone number.
-- */
--void msn_user_set_work_phone(MsnUser *user, const char *number);
--
--void msn_user_set_uid(MsnUser *user, const char *uid);
--
--/**
-- * Sets endpoint data for a user.
-- *
-- * @param user The user.
-- * @param endpoint The endpoint.
-- * @param data The endpoint data.
-- */
--void
--msn_user_set_endpoint_data(MsnUser *user, const char *endpoint, MsnUserEndpoint *data);
--
--/**
-- * Clears all endpoint data for a user.
-- *
-- * @param user The user.
-- */
--void
--msn_user_clear_endpoints(MsnUser *user);
--
--/**
-- * Sets the client id for a user.
-- *
-- * @param user The user.
-- * @param clientid The client id.
-- */
--void msn_user_set_clientid(MsnUser *user, guint clientid);
--
--/**
-- * Sets the client id for a user.
-- *
-- * @param user The user.
-- * @param extcaps The client's extended capabilities.
-- */
--void msn_user_set_extcaps(MsnUser *user, guint extcaps);
--
--/**
-- * Sets the network id for a user.
-- *
-- * @param user The user.
-- * @param network The network id.
-- */
--void msn_user_set_network(MsnUser *user, MsnNetwork network);
--
--/**
-- * Sets the mobile phone number for a user.
-- *
-- * @param user The user.
-- * @param number The mobile phone number.
-- */
--void msn_user_set_mobile_phone(MsnUser *user, const char *number);
--
--/**
-- * Sets the MSNObject for a user.
-- *
-- * @param user The user.
-- * @param obj The MSNObject.
-- */
--void msn_user_set_object(MsnUser *user, MsnObject *obj);
--
--/**
-- * Sets the client information for a user.
-- *
-- * @param user The user.
-- * @param info The client information.
-- */
--void msn_user_set_client_caps(MsnUser *user, GHashTable *info);
--
--/**
-- * Sets the invite message for a user.
-- *
-- * @param user The user.
-- * @param message The invite message for a user.
-- */
--void msn_user_set_invite_message(MsnUser *user, const char *message);
--
--
--/**
-- * Returns the passport account for a user.
-- *
-- * @param user The user.
-- *
-- * @return The passport account.
-- */
--const char *msn_user_get_passport(const MsnUser *user);
--
--/**
-- * Returns the friendly name for a user.
-- *
-- * @param user The user.
-- *
-- * @return The friendly name.
-- */
--const char *msn_user_get_friendly_name(const MsnUser *user);
--
--/**
-- * Returns the home phone number for a user.
-- *
-- * @param user The user.
-- *
-- * @return The user's home phone number.
-- */
--const char *msn_user_get_home_phone(const MsnUser *user);
--
--/**
-- * Returns the work phone number for a user.
-- *
-- * @param user The user.
-- *
-- * @return The user's work phone number.
-- */
--const char *msn_user_get_work_phone(const MsnUser *user);
--
--/**
-- * Returns the mobile phone number for a user.
-- *
-- * @param user The user.
-- *
-- * @return The user's mobile phone number.
-- */
--const char *msn_user_get_mobile_phone(const MsnUser *user);
--
--/**
-- * Gets endpoint data for a user.
-- *
-- * @param user The user.
-- * @param endpoint The endpoint.
-- *
-- * @return The user's endpoint data.
-- */
--MsnUserEndpoint *
--msn_user_get_endpoint_data(MsnUser *user, const char *endpoint);
--
--/**
-- * Returns the client id for a user.
-- *
-- * @param user The user.
-- *
-- * @return The user's client id.
-- */
--guint msn_user_get_clientid(const MsnUser *user);
--
--/**
-- * Returns the extended capabilities for a user.
-- *
-- * @param user The user.
-- *
-- * @return The user's extended capabilities.
-- */
--guint msn_user_get_extcaps(const MsnUser *user);
--
--/**************************************************************************
-- * Utility functions
-- **************************************************************************/
--
--
--/**
-- * Check if the user is part of the group.
-- *
-- * @param user The user we are asking group membership.
-- * @param group_id The group where the user may be in.
-- *
-- * @return TRUE if user is part of the group. Otherwise, FALSE.
-- */
--gboolean msn_user_is_in_group(MsnUser *user, const char * group_id);
--
--/**
-- * Check if user is on list.
-- *
-- * @param user The user we are asking list membership.
-- * @param list_id The list where the user may be in.
-- *
-- * @return TRUE if the user is on the list, else FALSE.
-- */
--gboolean msn_user_is_in_list(MsnUser *user, MsnListId list_id);
--/**
-- * Returns the network id for a user.
-- *
-- * @param user The user.
-- *
-- * @return The user's network id.
-- */
--MsnNetwork msn_user_get_network(const MsnUser *user);
--
--/**
-- * Returns the MSNObject for a user.
-- *
-- * @param user The user.
-- *
-- * @return The MSNObject.
-- */
--MsnObject *msn_user_get_object(const MsnUser *user);
--
--/**
-- * Returns the client information for a user.
-- *
-- * @param user The user.
-- *
-- * @return The client information.
-- */
--GHashTable *msn_user_get_client_caps(const MsnUser *user);
--
--/**
-- * Returns the invite message for a user.
-- *
-- * @param user The user.
-- *
-- * @return The user's invite message.
-- */
--const char *msn_user_get_invite_message(const MsnUser *user);
--
--/**
-- * check to see if user is online
-- */
--gboolean msn_user_is_online(PurpleAccount *account, const char *name);
--
--/**
-- * check to see if user is Yahoo User
-- */
--gboolean msn_user_is_yahoo(PurpleAccount *account, const char *name);
--
--void msn_user_set_op(MsnUser *user, MsnListOp list_op);
--void msn_user_unset_op(MsnUser *user, MsnListOp list_op);
--
--/**
-- * Compare the given passport with the one of the user
-- *
-- * @param user User to compare.
-- * @oaran passport Passport to compare.
-- *
-- * @return Zero if the passport match with the one of the user, otherwise
-- * a positive integer if the user passport is greather than the one given
-- * and a negative integer if it is less.
-- */
--int msn_user_passport_cmp(MsnUser *user, const char *passport);
--
--/**
-- * Checks whether a user is capable of some task.
-- *
-- * @param user The user.
-- * @param endpoint The endpoint. Can be @NULL to check overall capabilities.
-- * @param capability The capability (including client version).
-- * @param extcap The extended capability.
-- *
-- * @return Whether the user supports the capability.
-- */
--gboolean
--msn_user_is_capable(MsnUser *user, char *endpoint, guint capability, guint extcap);
--
--/*@}*/
--
--#endif /* MSN_USER_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/userlist.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/userlist.c
---- pidgin-2.10.7/libpurple/protocols/msn/userlist.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/userlist.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,759 +0,0 @@
--/**
-- * @file userlist.c MSN user list support
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--#include "request.h"
--
--#include "msn.h"
--#include "msnutils.h"
--#include "userlist.h"
--
--#include "contact.h"
--
--const char *lists[] = { "FL", "AL", "BL", "RL" };
--
--typedef struct
--{
-- PurpleConnection *gc;
-- char *who;
-- char *friendly;
--
--} MsnPermitAdd;
--
--/**************************************************************************
-- * Callbacks
-- **************************************************************************/
--static void
--msn_accept_add_cb(gpointer data)
--{
-- MsnPermitAdd *pa = data;
--
-- purple_debug_misc("msn", "Accepted the new buddy: %s\n", pa->who);
--
-- if (PURPLE_CONNECTION_IS_VALID(pa->gc))
-- {
-- MsnSession *session = pa->gc->proto_data;
-- MsnUserList *userlist = session->userlist;
-- PurpleAccount *account = purple_connection_get_account(pa->gc);
--
-- msn_userlist_add_buddy_to_list(userlist, pa->who, MSN_LIST_AL);
-- purple_privacy_deny_remove(account, pa->who, TRUE);
-- purple_privacy_permit_add(account, pa->who, TRUE);
--
-- msn_del_contact_from_list(session, NULL, pa->who, MSN_LIST_PL);
-- }
--
-- g_free(pa->who);
-- g_free(pa->friendly);
-- g_free(pa);
--}
--
--static void
--msn_cancel_add_cb(gpointer data)
--{
-- MsnPermitAdd *pa = data;
--
-- purple_debug_misc("msn", "Denied the new buddy: %s\n", pa->who);
--
-- if (PURPLE_CONNECTION_IS_VALID(pa->gc))
-- {
-- MsnSession *session = pa->gc->proto_data;
-- MsnUserList *userlist = session->userlist;
-- MsnCallbackState *state = msn_callback_state_new(session);
--
-- msn_callback_state_set_action(state, MSN_DENIED_BUDDY);
--
-- msn_userlist_add_buddy_to_list(userlist, pa->who, MSN_LIST_BL);
-- msn_del_contact_from_list(session, state, pa->who, MSN_LIST_PL);
-- }
--
-- g_free(pa->who);
-- g_free(pa->friendly);
-- g_free(pa);
--}
--
--static void
--got_new_entry(PurpleConnection *gc, const char *passport, const char *friendly, const char *message)
--{
-- PurpleAccount *acct;
-- MsnPermitAdd *pa;
--
-- pa = g_new0(MsnPermitAdd, 1);
-- pa->who = g_strdup(passport);
-- pa->friendly = g_strdup(friendly);
-- pa->gc = gc;
--
-- acct = purple_connection_get_account(gc);
-- purple_account_request_authorization(acct, passport, NULL, friendly, message,
-- purple_find_buddy(acct, passport) != NULL,
-- msn_accept_add_cb, msn_cancel_add_cb, pa);
--
--}
--
--/**************************************************************************
-- * Server functions
-- **************************************************************************/
--
--void
--msn_got_lst_user(MsnSession *session, MsnUser *user,
-- MsnListOp list_op, GSList *group_ids)
--{
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- const char *passport;
-- const char *store;
-- const char *message;
--
-- account = session->account;
-- gc = purple_account_get_connection(account);
--
-- passport = msn_user_get_passport(user);
-- store = msn_user_get_friendly_name(user);
-- message = msn_user_get_invite_message(user);
--
-- msn_user_set_op(user, list_op);
--
-- if (list_op & MSN_LIST_FL_OP)
-- {
-- GSList *c;
-- for (c = group_ids; c != NULL; c = g_slist_next(c))
-- {
-- char *group_id = c->data;
-- msn_user_add_group_id(user, group_id);
-- }
--
-- /* FIXME: It might be a real alias */
-- /* Umm, what? This might fix bug #1385130 */
-- serv_got_alias(gc, passport, store);
-- }
--
-- if (list_op & MSN_LIST_AL_OP)
-- {
-- /* These are users who are allowed to see our status. */
-- purple_privacy_deny_remove(account, passport, TRUE);
-- purple_privacy_permit_add(account, passport, TRUE);
-- }
--
-- if (list_op & MSN_LIST_BL_OP)
-- {
-- /* These are users who are not allowed to see our status. */
-- purple_privacy_permit_remove(account, passport, TRUE);
-- purple_privacy_deny_add(account, passport, TRUE);
-- }
--
-- if (list_op & MSN_LIST_RL_OP)
-- {
-- /* These are users who have us on their buddy list. */
-- /*
-- * TODO: What is store name set to when this happens?
-- * For one of my accounts "something@hotmail.com"
-- * the store name was "something." Maybe we
-- * should use the friendly name, instead? --KingAnt
-- */
--
-- if (!(list_op & (MSN_LIST_AL_OP | MSN_LIST_BL_OP)))
-- {
--/* got_new_entry(gc, passport, store, NULL); */
-- }
-- }
--
-- if (list_op & MSN_LIST_PL_OP)
-- {
-- user->authorized = TRUE;
-- got_new_entry(gc, passport, store, message);
-- }
--}
--
--/**************************************************************************
-- * UserList functions
-- **************************************************************************/
--
--MsnUserList*
--msn_userlist_new(MsnSession *session)
--{
-- MsnUserList *userlist;
--
-- userlist = g_new0(MsnUserList, 1);
--
-- userlist->session = session;
-- userlist->buddy_icon_requests = g_queue_new();
--
-- /* buddy_icon_window is the number of allowed simultaneous buddy icon requests.
-- * XXX With smarter rate limiting code, we could allow more at once... 5 was the limit set when
-- * we weren't retrieiving any more than 5 per MSN session. */
-- userlist->buddy_icon_window = 1;
--
-- return userlist;
--}
--
--void
--msn_userlist_destroy(MsnUserList *userlist)
--{
-- GList *l;
--
-- /*destroy userlist*/
-- for (l = userlist->users; l != NULL; l = l->next)
-- {
-- msn_user_unref(l->data);
-- }
-- g_list_free(userlist->users);
--
-- /*destroy group list*/
-- for (l = userlist->groups; l != NULL; l = l->next)
-- {
-- msn_group_destroy(l->data);
-- }
-- g_list_free(userlist->groups);
--
-- g_queue_free(userlist->buddy_icon_requests);
--
-- if (userlist->buddy_icon_request_timer)
-- purple_timeout_remove(userlist->buddy_icon_request_timer);
--
-- g_free(userlist);
--}
--
--MsnUser *
--msn_userlist_find_add_user(MsnUserList *userlist, const char *passport, const char *friendly_name)
--{
-- MsnUser *user;
--
-- user = msn_userlist_find_user(userlist, passport);
-- if (user == NULL)
-- {
-- user = msn_user_new(userlist, passport, friendly_name);
-- msn_userlist_add_user(userlist, user);
-- msn_user_unref(user);
-- } else {
-- msn_user_set_friendly_name(user, friendly_name);
-- }
-- return user;
--}
--
--void
--msn_userlist_add_user(MsnUserList *userlist, MsnUser *user)
--{
-- msn_user_ref(user);
-- userlist->users = g_list_prepend(userlist->users, user);
--}
--
--void
--msn_userlist_remove_user(MsnUserList *userlist, MsnUser *user)
--{
-- userlist->users = g_list_remove(userlist->users, user);
-- g_queue_remove(userlist->buddy_icon_requests, user);
-- msn_user_unref(user);
--}
--
--MsnUser *
--msn_userlist_find_user(MsnUserList *userlist, const char *passport)
--{
-- GList *l;
--
-- g_return_val_if_fail(passport != NULL, NULL);
--
-- for (l = userlist->users; l != NULL; l = l->next)
-- {
-- MsnUser *user = (MsnUser *)l->data;
--
-- g_return_val_if_fail(user->passport != NULL, NULL);
--
-- if (!g_ascii_strcasecmp(passport, user->passport)){
-- return user;
-- }
-- }
--
-- return NULL;
--}
--
--MsnUser *
--msn_userlist_find_user_with_id(MsnUserList *userlist, const char *uid)
--{
-- GList *l;
--
-- g_return_val_if_fail(uid != NULL, NULL);
--
-- for (l = userlist->users; l != NULL; l = l->next) {
-- MsnUser *user = (MsnUser *)l->data;
--
-- if (user->uid == NULL) {
-- continue;
-- }
--
-- if ( !g_ascii_strcasecmp(uid, user->uid) ) {
-- return user;
-- }
-- }
--
-- return NULL;
--}
--
--MsnUser *
--msn_userlist_find_user_with_mobile_phone(MsnUserList *userlist, const char *number)
--{
-- GList *l;
--
-- g_return_val_if_fail(number != NULL, NULL);
--
-- for (l = userlist->users; l != NULL; l = l->next) {
-- MsnUser *user = (MsnUser *)l->data;
-- const char *user_number = msn_user_get_mobile_phone(user);
--
-- if (user_number && !g_ascii_strcasecmp(number, user_number))
-- return user;
-- }
--
-- return NULL;
--}
--
--void
--msn_userlist_add_group(MsnUserList *userlist, MsnGroup *group)
--{
-- userlist->groups = g_list_append(userlist->groups, group);
--}
--
--void
--msn_userlist_remove_group(MsnUserList *userlist, MsnGroup *group)
--{
-- userlist->groups = g_list_remove(userlist->groups, group);
--}
--
--MsnGroup *
--msn_userlist_find_group_with_id(MsnUserList *userlist, const char * id)
--{
-- GList *l;
--
-- g_return_val_if_fail(userlist != NULL, NULL);
-- g_return_val_if_fail(id != NULL, NULL);
--
-- for (l = userlist->groups; l != NULL; l = l->next)
-- {
-- MsnGroup *group = l->data;
--
-- if (!g_ascii_strcasecmp(group->id,id))
-- return group;
-- }
--
-- return NULL;
--}
--
--MsnGroup *
--msn_userlist_find_group_with_name(MsnUserList *userlist, const char *name)
--{
-- GList *l;
--
-- g_return_val_if_fail(userlist != NULL, NULL);
-- g_return_val_if_fail(name != NULL, NULL);
--
-- for (l = userlist->groups; l != NULL; l = l->next)
-- {
-- MsnGroup *group = l->data;
--
-- if ((group->name != NULL) && !g_ascii_strcasecmp(name, group->name))
-- return group;
-- }
--
-- return NULL;
--}
--
--const char *
--msn_userlist_find_group_id(MsnUserList *userlist, const char *group_name)
--{
-- MsnGroup *group;
--
-- group = msn_userlist_find_group_with_name(userlist, group_name);
--
-- if (group != NULL)
-- return msn_group_get_id(group);
-- else
-- return NULL;
--}
--
--const char *
--msn_userlist_find_group_name(MsnUserList *userlist, const char * group_id)
--{
-- MsnGroup *group;
--
-- group = msn_userlist_find_group_with_id(userlist, group_id);
--
-- if (group != NULL)
-- return msn_group_get_name(group);
-- else
-- return NULL;
--}
--
--void
--msn_userlist_rename_group_id(MsnUserList *userlist, const char * group_id,
-- const char *new_name)
--{
-- MsnGroup *group;
--
-- group = msn_userlist_find_group_with_id(userlist, group_id);
--
-- if (group != NULL)
-- msn_group_set_name(group, new_name);
--}
--
--void
--msn_userlist_remove_group_id(MsnUserList *userlist, const char * group_id)
--{
-- MsnGroup *group;
--
-- group = msn_userlist_find_group_with_id(userlist, group_id);
--
-- if (group != NULL)
-- {
-- msn_userlist_remove_group(userlist, group);
-- msn_group_destroy(group);
-- }
--}
--
--typedef struct {
-- MsnSession *session;
-- char *uid;
--} MsnUserlistABData;
--
--static void
--userlist_ab_delete_cb(void *data, int choice)
--{
-- MsnUserlistABData *ab = (MsnUserlistABData *)data;
--
-- /* msn_delete_contact(ab->session, ab->uid, (gboolean)choice); */
--
-- g_free(ab->uid);
-- g_free(ab);
--}
--
--void
--msn_userlist_rem_buddy(MsnUserList *userlist, const char *who)
--{
-- MsnUser *user = NULL;
--
-- g_return_if_fail(userlist != NULL);
-- g_return_if_fail(userlist->session != NULL);
-- g_return_if_fail(who != NULL);
--
-- user = msn_userlist_find_user(userlist, who);
--
-- msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_FL);
--
-- /* delete the contact from address book via soap action */
-- if (user != NULL) {
-- if (0 /*not ready yet*/ && userlist->session->passport_info.email_enabled) {
-- MsnUserlistABData *ab = g_new0(MsnUserlistABData, 1);
-- ab->session = userlist->session;
-- ab->uid = g_strdup(user->uid); /* Not necessary? */
-- purple_request_yes_no(userlist->session->account,
-- _("Delete Buddy from Address Book?"),
-- _("Do you want to delete this buddy from your address book as well?"),
-- user->passport, 0, userlist->session->account, user->passport,
-- NULL, ab,
-- G_CALLBACK(userlist_ab_delete_cb), G_CALLBACK(userlist_ab_delete_cb));
-- } else
-- msn_delete_contact(userlist->session, user);
-- }
--}
--
--void
--msn_userlist_rem_buddy_from_list(MsnUserList *userlist, const char *who,
-- MsnListId list_id)
--{
-- MsnUser *user;
-- const gchar *list;
-- MsnListOp list_op = 1 << list_id;
--
-- user = msn_userlist_find_user(userlist, who);
--
-- g_return_if_fail(user != NULL);
--
-- if ( !msn_user_is_in_list(user, list_id)) {
-- list = lists[list_id];
-- purple_debug_info("msn", "User %s is not in list %s, not removing.\n", who, list);
-- return;
-- }
--
-- msn_user_unset_op(user, list_op);
--
-- msn_notification_rem_buddy_from_list(userlist->session->notification, list_id, user);
--}
--
--/*add buddy*/
--void
--msn_userlist_add_buddy(MsnUserList *userlist, const char *who, const char *group_name)
--{
-- MsnUser *user;
-- MsnCallbackState *state = NULL;
-- const char *group_id = NULL, *new_group_name;
--
-- new_group_name = group_name == NULL ? MSN_INDIVIDUALS_GROUP_NAME : group_name;
--
-- g_return_if_fail(userlist != NULL);
-- g_return_if_fail(userlist->session != NULL);
--
-- purple_debug_info("msn", "Add user: %s to group: %s\n", who, new_group_name);
--
-- if (!msn_email_is_valid(who))
-- {
-- /* only notify the user about problems adding to the friends list
-- * maybe we should do something else for other lists, but it probably
-- * won't cause too many problems if we just ignore it */
--
-- char *str = g_strdup_printf(_("Unable to add \"%s\"."), who);
--
-- purple_notify_error(NULL, NULL, str,
-- _("The username specified is invalid."));
-- g_free(str);
--
-- return;
-- }
--
-- state = msn_callback_state_new(userlist->session);
-- msn_callback_state_set_who(state, who);
-- msn_callback_state_set_new_group_name(state, new_group_name);
--
-- group_id = msn_userlist_find_group_id(userlist, new_group_name);
--
-- if (group_id == NULL)
-- {
-- /* Whoa, we must add that group first. */
-- purple_debug_info("msn", "Adding user %s to a new group, creating group %s first\n", who, new_group_name);
--
-- msn_callback_state_set_action(state, MSN_ADD_BUDDY);
--
-- msn_add_group(userlist->session, state, new_group_name);
-- return;
-- } else {
-- msn_callback_state_set_guid(state, group_id);
-- }
--
-- /* XXX: adding user here may not be correct (should add them in the
-- * ACK to the ADL command), but for now we need to make sure they exist
-- * early enough that the ILN command doesn't screw us up */
--
-- user = msn_userlist_find_add_user(userlist, who, who);
--
-- if ( msn_user_is_in_list(user, MSN_LIST_FL) ) {
--
-- purple_debug_info("msn", "User %s already exists\n", who);
--
-- msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_BL);
--
-- if (msn_user_is_in_group(user, group_id)) {
-- purple_debug_info("msn", "User %s is already in group %s, returning\n", who, new_group_name);
-- msn_callback_state_free(state);
-- return;
-- }
-- }
--
-- purple_debug_info("msn", "Adding user: %s to group id: %s\n", who, group_id);
--
-- msn_callback_state_set_action(state, MSN_ADD_BUDDY);
--
-- /* Add contact in the Contact server with a SOAP request and if
-- successful, send ADL with MSN_LIST_AL and MSN_LIST_FL and a FQY */
-- msn_add_contact_to_group(userlist->session, state, who, group_id);
--}
--
--void
--msn_userlist_add_buddy_to_list(MsnUserList *userlist, const char *who,
-- MsnListId list_id)
--{
-- MsnUser *user = NULL;
-- const gchar *list;
-- MsnListOp list_op = 1 << list_id;
--
-- g_return_if_fail(userlist != NULL);
--
-- user = msn_userlist_find_add_user(userlist, who, who);
--
-- /* First we're going to check if it's already there. */
-- if (msn_user_is_in_list(user, list_id))
-- {
-- list = lists[list_id];
-- purple_debug_info("msn", "User '%s' is already in list: %s\n", who, list);
-- return;
-- }
--
-- /* XXX: see XXX above, this should really be done when we get the response from
-- the server */
--
-- msn_user_set_op(user, list_op);
--
-- msn_notification_add_buddy_to_list(userlist->session->notification, list_id, user);
--}
--
--gboolean
--msn_userlist_add_buddy_to_group(MsnUserList *userlist, const char *who,
-- const char *group_name)
--{
-- MsnUser *user;
-- gchar * group_id;
--
-- g_return_val_if_fail(userlist != NULL, FALSE);
-- g_return_val_if_fail(group_name != NULL, FALSE);
-- g_return_val_if_fail(who != NULL, FALSE);
--
-- purple_debug_info("msn", "Adding buddy with passport %s to group %s\n", who, group_name);
--
-- if ( (group_id = (gchar *)msn_userlist_find_group_id(userlist, group_name)) == NULL) {
-- purple_debug_error("msn", "Group %s has no guid!\n", group_name);
-- return FALSE;
-- }
--
-- if ( (user = msn_userlist_find_user(userlist, who)) == NULL) {
-- purple_debug_error("msn", "User %s not found!\n", who);
-- return FALSE;
-- }
--
-- msn_user_add_group_id(user, group_id);
--
-- return TRUE;
--}
--
--
--gboolean
--msn_userlist_rem_buddy_from_group(MsnUserList *userlist, const char *who,
-- const char *group_name)
--{
-- const gchar * group_id;
-- MsnUser *user;
--
-- g_return_val_if_fail(userlist != NULL, FALSE);
-- g_return_val_if_fail(group_name != NULL, FALSE);
-- g_return_val_if_fail(who != NULL, FALSE);
--
-- purple_debug_info("msn", "Removing buddy with passport %s from group %s\n", who, group_name);
--
-- if ( (group_id = msn_userlist_find_group_id(userlist, group_name)) == NULL) {
-- purple_debug_error("msn", "Group %s has no guid!\n", group_name);
-- return FALSE;
-- }
--
-- if ( (user = msn_userlist_find_user(userlist, who)) == NULL) {
-- purple_debug_error("msn", "User %s not found!\n", who);
-- return FALSE;
-- }
--
-- msn_user_remove_group_id(user, group_id);
--
-- return TRUE;
--}
--
--void
--msn_userlist_move_buddy(MsnUserList *userlist, const char *who,
-- const char *old_group_name, const char *new_group_name)
--{
-- const char *new_group_id;
-- MsnCallbackState *state;
--
-- g_return_if_fail(userlist != NULL);
-- g_return_if_fail(userlist->session != NULL);
--
-- state = msn_callback_state_new(userlist->session);
-- msn_callback_state_set_who(state, who);
-- msn_callback_state_set_action(state, MSN_MOVE_BUDDY);
-- msn_callback_state_set_old_group_name(state, old_group_name);
-- msn_callback_state_set_new_group_name(state, new_group_name);
--
-- new_group_id = msn_userlist_find_group_id(userlist, new_group_name);
--
-- if (new_group_id == NULL)
-- {
-- msn_add_group(userlist->session, state, new_group_name);
-- return;
-- }
--
-- /* add the contact to the new group, and remove it from the old one in
-- * the callback
-- */
-- msn_add_contact_to_group(userlist->session, state, who, new_group_id);
--}
--
--void
--msn_release_buddy_icon_request(MsnUserList *userlist)
--{
-- MsnUser *user;
--
-- g_return_if_fail(userlist != NULL);
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn", "Releasing buddy icon request\n");
--
-- if (userlist->buddy_icon_window > 0) {
-- GQueue *queue;
--
-- queue = userlist->buddy_icon_requests;
--
-- if (g_queue_is_empty(userlist->buddy_icon_requests))
-- return;
--
-- user = g_queue_pop_head(queue);
--
-- userlist->buddy_icon_window--;
--
-- msn_request_user_display(user);
--
-- if (purple_debug_is_verbose())
-- purple_debug_info("msn",
-- "msn_release_buddy_icon_request(): buddy_icon_window-- yields =%d\n",
-- userlist->buddy_icon_window);
-- }
--}
--
--/*load userlist from the Blist file cache*/
--void
--msn_userlist_load(MsnSession *session)
--{
-- PurpleAccount *account = session->account;
-- PurpleConnection *gc = purple_account_get_connection(account);
-- GSList *l;
-- MsnUser * user;
--
-- g_return_if_fail(gc != NULL);
--
-- for (l = purple_find_buddies(account, NULL); l != NULL;
-- l = g_slist_delete_link(l, l)) {
-- PurpleBuddy *buddy = l->data;
--
-- user = msn_userlist_find_add_user(session->userlist,
-- purple_buddy_get_name(buddy), NULL);
-- purple_buddy_set_protocol_data(buddy, user);
-- msn_user_set_op(user, MSN_LIST_FL_OP);
-- }
-- for (l = session->account->permit; l != NULL; l = l->next)
-- {
-- user = msn_userlist_find_add_user(session->userlist,
-- (char *)l->data,NULL);
-- msn_user_set_op(user, MSN_LIST_AL_OP);
-- }
-- for (l = session->account->deny; l != NULL; l = l->next)
-- {
-- user = msn_userlist_find_add_user(session->userlist,
-- (char *)l->data,NULL);
-- msn_user_set_op(user, MSN_LIST_BL_OP);
-- }
--
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/userlist.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/userlist.h
---- pidgin-2.10.7/libpurple/protocols/msn/userlist.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/userlist.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,112 +0,0 @@
--/**
-- * @file userlist.h MSN user list support
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef MSN_USERLIST_H
--#define MSN_USERLIST_H
--
--typedef struct _MsnUserList MsnUserList;
--
--typedef enum
--{
-- MSN_LIST_FL, /**< Forward list */
-- MSN_LIST_AL, /**< Allow list */
-- MSN_LIST_BL, /**< Block list */
-- MSN_LIST_RL, /**< Reverse list */
-- MSN_LIST_PL /**< Pending list */
--} MsnListId;
--
--typedef enum
--{
-- MSN_LIST_FL_OP = 0x01,
-- MSN_LIST_AL_OP = 0x02,
-- MSN_LIST_BL_OP = 0x04,
-- MSN_LIST_RL_OP = 0x08,
-- MSN_LIST_PL_OP = 0x10
--} MsnListOp;
--#define MSN_LIST_OP_MASK 0x07
--
--#include "group.h"
--#include "msn.h"
--#include "user.h"
--
--struct _MsnUserList
--{
-- MsnSession *session;
--
-- GList *users; /* Contains MsnUsers */
-- GList *groups; /* Contains MsnGroups */
--
-- GQueue *buddy_icon_requests;
-- int buddy_icon_window;
-- guint buddy_icon_request_timer;
--
--};
--
--void msn_got_lst_user(MsnSession *session, MsnUser *user,
-- MsnListOp list_op, GSList *group_ids);
--
--MsnUserList *msn_userlist_new(MsnSession *session);
--void msn_userlist_destroy(MsnUserList *userlist);
--
--void msn_userlist_add_user(MsnUserList *userlist, MsnUser *user);
--void msn_userlist_remove_user(MsnUserList *userlist, MsnUser *user);
--
--MsnUser * msn_userlist_find_user(MsnUserList *userlist, const char *passport);
--MsnUser * msn_userlist_find_add_user(MsnUserList *userlist,
-- const char *passport, const char *friendly_name);
--MsnUser * msn_userlist_find_user_with_id(MsnUserList *userlist, const char *uid);
--MsnUser * msn_userlist_find_user_with_mobile_phone(MsnUserList *userlist, const char *number);
--
--void msn_userlist_add_group(MsnUserList *userlist, MsnGroup *group);
--void msn_userlist_remove_group(MsnUserList *userlist, MsnGroup *group);
--MsnGroup *msn_userlist_find_group_with_id(MsnUserList *userlist, const char *id);
--MsnGroup *msn_userlist_find_group_with_name(MsnUserList *userlist, const char *name);
--const char * msn_userlist_find_group_id(MsnUserList *userlist,
-- const char *group_name);
--const char *msn_userlist_find_group_name(MsnUserList *userlist, const char *group_id);
--void msn_userlist_rename_group_id(MsnUserList *userlist, const char *group_id,
-- const char *new_name);
--void msn_userlist_remove_group_id(MsnUserList *userlist, const char *group_id);
--
--void msn_userlist_rem_buddy(MsnUserList *userlist, const char *who);
--void msn_userlist_add_buddy(MsnUserList *userlist,
-- const char *who, const char *group_name);
--void msn_userlist_move_buddy(MsnUserList *userlist, const char *who,
-- const char *old_group_name,
-- const char *new_group_name);
--
--gboolean msn_userlist_add_buddy_to_group(MsnUserList *userlist, const char *who,
-- const char *group_name);
--gboolean msn_userlist_rem_buddy_from_group(MsnUserList *userlist,
-- const char *who,
-- const char *group_name);
--
--void msn_userlist_add_buddy_to_list(MsnUserList *userlist, const char *who,
-- MsnListId list_id);
--void msn_userlist_rem_buddy_from_list(MsnUserList *userlist, const char *who,
-- MsnListId list_id);
--void msn_release_buddy_icon_request(MsnUserList *userlist);
--
--void msn_userlist_load(MsnSession *session);
--
--#endif /* MSN_USERLIST_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/xfer.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/xfer.c
---- pidgin-2.10.7/libpurple/protocols/msn/xfer.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/xfer.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,235 +0,0 @@
--/**
-- * @file xfer.c MSN File Transfer functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "msnutils.h"
--#include "sbconn.h"
--#include "xfer.h"
--
--/**************************************************************************
-- * Xfer
-- **************************************************************************/
--
--void
--msn_xfer_init(PurpleXfer *xfer)
--{
-- MsnSlpCall *slpcall;
-- /* MsnSlpLink *slplink; */
-- char *content;
--
-- purple_debug_info("msn", "xfer_init\n");
--
-- slpcall = xfer->data;
--
-- /* Send Ok */
-- content = g_strdup_printf("SessionID: %lu\r\n\r\n",
-- slpcall->session_id);
--
-- msn_slp_send_ok(slpcall, slpcall->branch, "application/x-msnmsgr-sessionreqbody",
-- content);
--
-- g_free(content);
-- msn_slplink_send_queued_slpmsgs(slpcall->slplink);
--}
--
--void
--msn_xfer_cancel(PurpleXfer *xfer)
--{
-- MsnSlpCall *slpcall;
-- char *content;
--
-- g_return_if_fail(xfer != NULL);
-- g_return_if_fail(xfer->data != NULL);
--
-- slpcall = xfer->data;
--
-- if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL)
-- {
-- if (slpcall->started)
-- {
-- msn_slpcall_close(slpcall);
-- }
-- else
-- {
-- content = g_strdup_printf("SessionID: %lu\r\n\r\n",
-- slpcall->session_id);
--
-- msn_slp_send_decline(slpcall, slpcall->branch, "application/x-msnmsgr-sessionreqbody",
-- content);
--
-- g_free(content);
-- msn_slplink_send_queued_slpmsgs(slpcall->slplink);
--
-- if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND)
-- slpcall->wasted = TRUE;
-- else
-- msn_slpcall_destroy(slpcall);
-- }
-- }
--}
--
--gssize
--msn_xfer_write(const guchar *data, gsize len, PurpleXfer *xfer)
--{
-- MsnSlpCall *slpcall;
--
-- g_return_val_if_fail(xfer != NULL, -1);
-- g_return_val_if_fail(data != NULL, -1);
-- g_return_val_if_fail(len > 0, -1);
--
-- g_return_val_if_fail(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND, -1);
--
-- slpcall = xfer->data;
-- /* Not sure I trust it'll be there */
-- g_return_val_if_fail(slpcall != NULL, -1);
--
-- g_return_val_if_fail(slpcall->xfer_msg != NULL, -1);
--
-- slpcall->u.outgoing.len = len;
-- slpcall->u.outgoing.data = data;
-- msn_slplink_send_msgpart(slpcall->slplink, slpcall->xfer_msg);
--
-- return MIN(MSN_SBCONN_MAX_SIZE, len);
--}
--
--gssize
--msn_xfer_read(guchar **data, PurpleXfer *xfer)
--{
-- MsnSlpCall *slpcall;
-- gsize len;
--
-- g_return_val_if_fail(xfer != NULL, -1);
-- g_return_val_if_fail(data != NULL, -1);
--
-- g_return_val_if_fail(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE, -1);
--
-- slpcall = xfer->data;
-- /* Not sure I trust it'll be there */
-- g_return_val_if_fail(slpcall != NULL, -1);
--
-- /* Just pass up the whole GByteArray. We'll make another. */
-- *data = slpcall->u.incoming_data->data;
-- len = slpcall->u.incoming_data->len;
--
-- g_byte_array_free(slpcall->u.incoming_data, FALSE);
-- slpcall->u.incoming_data = g_byte_array_new();
--
-- return len;
--}
--
--void
--msn_xfer_end_cb(MsnSlpCall *slpcall, MsnSession *session)
--{
-- if ((purple_xfer_get_status(slpcall->xfer) != PURPLE_XFER_STATUS_DONE) &&
-- (purple_xfer_get_status(slpcall->xfer) != PURPLE_XFER_STATUS_CANCEL_REMOTE) &&
-- (purple_xfer_get_status(slpcall->xfer) != PURPLE_XFER_STATUS_CANCEL_LOCAL))
-- {
-- purple_xfer_cancel_remote(slpcall->xfer);
-- }
--}
--
--void
--msn_xfer_completed_cb(MsnSlpCall *slpcall, const guchar *body,
-- gsize size)
--{
-- PurpleXfer *xfer = slpcall->xfer;
--
-- purple_xfer_set_completed(xfer, TRUE);
-- purple_xfer_end(xfer);
--}
--
--gchar *
--msn_file_context_to_wire(MsnFileContext *context)
--{
-- gchar *ret, *tmp;
--
-- tmp = ret = g_new(gchar, MSN_FILE_CONTEXT_SIZE + context->preview_len + 1);
--
-- msn_push32le(tmp, context->length);
-- msn_push32le(tmp, context->version);
-- msn_push64le(tmp, context->file_size);
-- msn_push32le(tmp, context->type);
-- memcpy(tmp, context->file_name, MAX_FILE_NAME_LEN * 2);
-- tmp += MAX_FILE_NAME_LEN * 2;
-- memcpy(tmp, context->unknown1, sizeof(context->unknown1));
-- tmp += sizeof(context->unknown1);
-- msn_push32le(tmp, context->unknown2);
-- if (context->preview) {
-- memcpy(tmp, context->preview, context->preview_len);
-- }
-- tmp[context->preview_len] = '\0';
--
-- return ret;
--}
--
--MsnFileContext *
--msn_file_context_from_wire(const char *buf, gsize len)
--{
-- MsnFileContext *context;
--
-- if (!buf || len < MSN_FILE_CONTEXT_SIZE)
-- return NULL;
--
-- context = g_new(MsnFileContext, 1);
--
-- context->length = msn_pop32le(buf);
-- context->version = msn_pop32le(buf);
-- if (context->version == 2) {
-- /* The length field is broken for this version. No check. */
-- context->length = MSN_FILE_CONTEXT_SIZE;
-- } else if (context->version == 3) {
-- if (context->length != MSN_FILE_CONTEXT_SIZE + 63) {
-- g_free(context);
-- return NULL;
-- } else if (len < MSN_FILE_CONTEXT_SIZE + 63) {
-- g_free(context);
-- return NULL;
-- }
-- } else {
-- purple_debug_warning("msn", "Received MsnFileContext with unknown version: %d\n", context->version);
-- g_free(context);
-- return NULL;
-- }
--
-- context->file_size = msn_pop64le(buf);
-- context->type = msn_pop32le(buf);
-- memcpy(context->file_name, buf, MAX_FILE_NAME_LEN * 2);
-- buf += MAX_FILE_NAME_LEN * 2;
-- memcpy(context->unknown1, buf, sizeof(context->unknown1));
-- buf += sizeof(context->unknown1);
-- context->unknown2 = msn_pop32le(buf);
--
-- if (context->type == 0 && len > context->length) {
-- context->preview_len = len - context->length;
-- context->preview = g_memdup(buf, context->preview_len);
-- } else {
-- context->preview_len = 0;
-- context->preview = NULL;
-- }
--
-- return context;
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/msn/xfer.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/xfer.h
---- pidgin-2.10.7/libpurple/protocols/msn/xfer.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/xfer.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,67 +0,0 @@
--/**
-- * @file xfer.h MSN File Transfer functions
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef MSN_XFER_H
--#define MSN_XFER_H
--
--#include "slpcall.h"
--
--#define MAX_FILE_NAME_LEN 260 /* MAX_PATH in Windows */
--
--/**
-- * The context data for a file transfer request
-- */
--typedef struct
--{
-- guint32 length; /*< Length of header */
-- guint32 version; /*< MSN version */
-- guint64 file_size; /*< Size of file */
-- guint32 type; /*< Transfer type */
-- gunichar2 file_name[MAX_FILE_NAME_LEN]; /*< Self-explanatory */
-- gchar unknown1[30]; /*< Used somehow for background sharing */
-- guint32 unknown2; /*< Possibly for background sharing as well */
-- gchar *preview; /*< File preview data, 96x96 PNG */
-- gsize preview_len;
--} MsnFileContext;
--
--#define MSN_FILE_CONTEXT_SIZE (4*4 + 1*8 + 2*MAX_FILE_NAME_LEN + 30)
--
--void msn_xfer_init(PurpleXfer *xfer);
--void msn_xfer_cancel(PurpleXfer *xfer);
--
--gssize msn_xfer_write(const guchar *data, gsize len, PurpleXfer *xfer);
--gssize msn_xfer_read(guchar **data, PurpleXfer *xfer);
--
--void msn_xfer_completed_cb(MsnSlpCall *slpcall,
-- const guchar *body, gsize size);
--void msn_xfer_end_cb(MsnSlpCall *slpcall, MsnSession *session);
--
--gchar *
--msn_file_context_to_wire(MsnFileContext *context);
--
--MsnFileContext *
--msn_file_context_from_wire(const char *buf, gsize len);
--
--#endif /* MSN_XFER_H */
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/actions.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/actions.c
---- pidgin-2.10.7/libpurple/protocols/mxit/actions.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/actions.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,544 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- handle MXit plugin actions --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "purple.h"
--
--#include "protocol.h"
--#include "mxit.h"
--#include "roster.h"
--#include "actions.h"
--#include "splashscreen.h"
--#include "cipher.h"
--#include "profile.h"
--
--
--/*------------------------------------------------------------------------
-- * The user has selected to change their profile.
-- *
-- * @param gc The connection object
-- * @param fields The fields from the request pop-up
-- */
--static void mxit_profile_cb( PurpleConnection* gc, PurpleRequestFields* fields )
--{
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
-- PurpleRequestField* field = NULL;
-- const char* name = NULL;
-- const char* bday = NULL;
-- const char* err = NULL;
-- GList* entry = NULL;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_profile_cb\n" );
--
-- if ( !PURPLE_CONNECTION_IS_VALID( gc ) ) {
-- purple_debug_error( MXIT_PLUGIN_ID, "Unable to update profile; account offline.\n" );
-- return;
-- }
--
-- /* validate name */
-- name = purple_request_fields_get_string( fields, "name" );
-- if ( ( !name ) || ( strlen( name ) < 3 ) ) {
-- err = _( "The Display Name you entered is invalid." );
-- goto out;
-- }
--
-- /* validate birthdate */
-- bday = purple_request_fields_get_string( fields, "bday" );
-- if ( ( !bday ) || ( strlen( bday ) < 10 ) || ( !validateDate( bday ) ) ) {
-- err = _( "The birthday you entered is invalid. The correct format is: 'YYYY-MM-DD'." );
-- goto out;
-- }
--
--out:
-- if ( !err ) {
-- struct MXitProfile* profile = session->profile;
-- GString* attributes = g_string_sized_new( 128 );
-- char attrib[512];
-- unsigned int acount = 0;
--
--
-- /* update name */
-- g_strlcpy( profile->nickname, name, sizeof( profile->nickname ) );
-- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_FULLNAME, CP_PROFILE_TYPE_UTF8, profile->nickname );
-- g_string_append( attributes, attrib );
-- acount++;
--
-- /* update birthday */
-- g_strlcpy( profile->birthday, bday, sizeof( profile->birthday ) );
-- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_BIRTHDATE, CP_PROFILE_TYPE_UTF8, profile->birthday );
-- g_string_append( attributes, attrib );
-- acount++;
--
-- /* update gender */
-- profile->male = ( purple_request_fields_get_choice( fields, "male" ) != 0 );
-- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_GENDER, CP_PROFILE_TYPE_BOOL, ( profile->male ) ? "1" : "0" );
-- g_string_append( attributes, attrib );
-- acount++;
--
-- /* update title */
-- name = purple_request_fields_get_string( fields, "title" );
-- if ( !name )
-- profile->title[0] = '\0';
-- else
-- g_strlcpy( profile->title, name, sizeof( profile->title ) );
-- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_TITLE, CP_PROFILE_TYPE_UTF8, profile->title );
-- g_string_append( attributes, attrib );
-- acount++;
--
-- /* update firstname */
-- name = purple_request_fields_get_string( fields, "firstname" );
-- if ( !name )
-- profile->firstname[0] = '\0';
-- else
-- g_strlcpy( profile->firstname, name, sizeof( profile->firstname ) );
-- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_FIRSTNAME, CP_PROFILE_TYPE_UTF8, profile->firstname );
-- g_string_append( attributes, attrib );
-- acount++;
--
-- /* update lastname */
-- name = purple_request_fields_get_string( fields, "lastname" );
-- if ( !name )
-- profile->lastname[0] = '\0';
-- else
-- g_strlcpy( profile->lastname, name, sizeof( profile->lastname ) );
-- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_LASTNAME, CP_PROFILE_TYPE_UTF8, profile->lastname );
-- g_string_append( attributes, attrib );
-- acount++;
--
-- /* update email address */
-- name = purple_request_fields_get_string( fields, "email" );
-- if ( !name )
-- profile->email[0] = '\0';
-- else
-- g_strlcpy( profile->email, name, sizeof( profile->email ) );
-- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_EMAIL, CP_PROFILE_TYPE_UTF8, profile->email );
-- g_string_append( attributes, attrib );
-- acount++;
--
-- /* update mobile number */
-- name = purple_request_fields_get_string( fields, "mobilenumber" );
-- if ( !name )
-- profile->mobilenr[0] = '\0';
-- else
-- g_strlcpy( profile->mobilenr, name, sizeof( profile->mobilenr ) );
-- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_MOBILENR, CP_PROFILE_TYPE_UTF8, profile->mobilenr );
-- g_string_append( attributes, attrib );
-- acount++;
--
-- /* update about me */
-- name = purple_request_fields_get_string( fields, "aboutme" );
-- if ( !name )
-- profile->aboutme[0] = '\0';
-- else
-- g_strlcpy( profile->aboutme, name, sizeof( profile->aboutme ) );
-- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_ABOUTME, CP_PROFILE_TYPE_UTF8, profile->aboutme );
-- g_string_append( attributes, attrib );
-- acount++;
--
-- /* update where am i */
-- name = purple_request_fields_get_string( fields, "whereami" );
-- if ( !name)
-- profile->whereami[0] = '\0';
-- else
-- g_strlcpy( profile->whereami, name, sizeof( profile->whereami ) );
-- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_WHEREAMI, CP_PROFILE_TYPE_UTF8, profile->whereami );
-- g_string_append( attributes, attrib );
-- acount++;
--
-- /* relationship status */
-- field = purple_request_fields_get_field( fields, "relationship" );
-- entry = g_list_first( purple_request_field_list_get_selected( field ) );
-- profile->relationship = atoi( purple_request_field_list_get_data( field, entry->data ) );
-- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%i", CP_PROFILE_RELATIONSHIP, CP_PROFILE_TYPE_SHORT, profile->relationship );
-- g_string_append( attributes, attrib );
-- acount++;
--
-- /* update flags */
-- field = purple_request_fields_get_field( fields, "searchable" );
-- if ( purple_request_field_bool_get_value( field ) ) /* is searchable -> clear not-searchable flag */
-- profile->flags &= ~CP_PROF_NOT_SEARCHABLE;
-- else
-- profile->flags |= CP_PROF_NOT_SEARCHABLE;
-- field = purple_request_fields_get_field( fields, "suggestable" );
-- if ( purple_request_field_bool_get_value( field ) ) /* is suggestable -> clear not-suggestable flag */
-- profile->flags &= ~CP_PROF_NOT_SUGGESTABLE;
-- else
-- profile->flags |= CP_PROF_NOT_SUGGESTABLE;
-- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%i", CP_PROFILE_FLAGS, CP_PROFILE_TYPE_LONG, profile->flags);
-- g_string_append( attributes, attrib );
-- acount++;
--
-- /* send the profile update to MXit */
-- mxit_send_extprofile_update( session, NULL, acount, attributes->str );
-- g_string_free( attributes, TRUE );
-- }
-- else {
-- /* show error to user */
-- mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Profile Update Error" ), err );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Display and update the user's profile.
-- *
-- * @param action The action object
-- */
--static void mxit_profile_action( PurplePluginAction* action )
--{
-- PurpleConnection* gc = (PurpleConnection*) action->context;
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
-- struct MXitProfile* profile = session->profile;
--
-- PurpleRequestFields* fields = NULL;
-- PurpleRequestField* field = NULL;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_profile_action\n" );
--
-- /* ensure that we actually have the user's profile information */
-- if ( !profile ) {
-- /* no profile information yet, so we cannot update */
-- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Profile" ), _( "Your profile information is not yet retrieved. Please try again later." ) );
-- return;
-- }
--
-- fields = purple_request_fields_new();
--
-- /* Public information - what other users can see */
-- {
-- PurpleRequestFieldGroup* public_group = purple_request_field_group_new( "Public information" );
--
-- /* display name */
-- field = purple_request_field_string_new( "name", _( "Display Name" ), profile->nickname, FALSE );
-- purple_request_field_group_add_field( public_group, field );
--
-- /* birthday */
-- field = purple_request_field_string_new( "bday", _( "Birthday" ), profile->birthday, FALSE );
-- purple_request_field_group_add_field( public_group, field );
-- if ( profile->flags & CP_PROF_DOBLOCKED )
-- purple_request_field_string_set_editable( field, FALSE );
--
-- /* gender */
-- field = purple_request_field_choice_new( "male", _( "Gender" ), ( profile->male ) ? 1 : 0 );
-- purple_request_field_choice_add( field, _( "Female" ) ); /* 0 */
-- purple_request_field_choice_add( field, _( "Male" ) ); /* 1 */
-- purple_request_field_group_add_field( public_group, field );
--
-- /* first name */
-- field = purple_request_field_string_new( "firstname", _( "First Name" ), profile->firstname, FALSE );
-- purple_request_field_group_add_field( public_group, field );
--
-- /* last name */
-- field = purple_request_field_string_new( "lastname", _( "Last Name" ), profile->lastname, FALSE );
-- purple_request_field_group_add_field( public_group, field );
--
-- /* about me */
-- field = purple_request_field_string_new( "aboutme", _( "About Me" ), profile->aboutme, FALSE);
-- purple_request_field_group_add_field( public_group, field );
--
-- /* where I live */
-- field = purple_request_field_string_new( "whereami", _( "Where I Live" ), profile->whereami, FALSE);
-- purple_request_field_group_add_field( public_group, field );
--
-- /* relationship status */
-- field = purple_request_field_list_new( "relationship", _( "Relationship Status" ) );
-- purple_request_field_list_set_multi_select( field, FALSE );
-- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_UNKNOWN ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_UNKNOWN ) );
-- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_DONTSAY ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_DONTSAY ) );
-- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_SINGLE ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_SINGLE ) );
-- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_INVOLVED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_INVOLVED ) );
-- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_ENGAGED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_ENGAGED ) );
-- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_MARRIED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_MARRIED ) );
-- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_COMPLICATED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_COMPLICATED ) );
-- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_WIDOWED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_WIDOWED ) );
-- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_SEPARATED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_SEPARATED ) );
-- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_DIVORCED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_DIVORCED ) );
-- purple_request_field_list_add_selected( field, mxit_relationship_to_name( profile->relationship ) );
-- purple_request_field_group_add_field( public_group, field );
--
-- purple_request_fields_add_group( fields, public_group );
-- }
--
-- /* Private information - what only MXit can see */
-- {
-- PurpleRequestFieldGroup* private_group = purple_request_field_group_new( "Private information" );
--
-- /* title */
-- field = purple_request_field_string_new( "title", _( "Title" ), profile->title, FALSE );
-- purple_request_field_group_add_field( private_group, field );
--
-- /* email */
-- field = purple_request_field_string_new( "email", _( "Email" ), profile->email, FALSE );
-- purple_request_field_group_add_field( private_group, field );
--
-- /* mobile number */
-- field = purple_request_field_string_new( "mobilenumber", _( "Mobile Number" ), profile->mobilenr, FALSE );
-- purple_request_field_group_add_field( private_group, field );
--
-- /* is searchable */
-- field = purple_request_field_bool_new( "searchable", _( "Can be searched" ), ( ( profile->flags & CP_PROF_NOT_SEARCHABLE ) == 0) );
-- purple_request_field_group_add_field( private_group, field );
--
-- /* is suggestable */
-- field = purple_request_field_bool_new( "suggestable", _( "Can be suggested" ), ( ( profile->flags & CP_PROF_NOT_SUGGESTABLE ) == 0 ) );
-- purple_request_field_group_add_field( private_group, field );
--
-- purple_request_fields_add_group( fields, private_group );
-- }
--
-- /* (reference: "libpurple/request.h") */
-- purple_request_fields( gc, _( "Profile" ), _( "Update your MXit Profile" ), NULL, fields, _( "Set" ),
-- G_CALLBACK( mxit_profile_cb ), _( "Cancel" ), NULL, purple_connection_get_account( gc ), NULL, NULL, gc );
--}
--
--
--/*------------------------------------------------------------------------
-- * The user has selected to change their PIN.
-- *
-- * @param gc The connection object
-- * @param fields The fields from the request pop-up
-- */
--static void mxit_change_pin_cb( PurpleConnection* gc, PurpleRequestFields* fields )
--{
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
-- const char* pin = NULL;
-- const char* pin2 = NULL;
-- const char* err = NULL;
-- int len;
-- int i;
--
-- if ( !PURPLE_CONNECTION_IS_VALID( gc ) ) {
-- purple_debug_error( MXIT_PLUGIN_ID, "Unable to update PIN; account offline.\n" );
-- return;
-- }
--
-- /* validate pin */
-- pin = purple_request_fields_get_string( fields, "pin" );
-- if ( !pin ) {
-- err = _( "The PIN you entered is invalid." );
-- goto out;
-- }
-- len = strlen( pin );
-- if ( ( len < 4 ) || ( len > 10 ) ) {
-- err = _( "The PIN you entered has an invalid length [4-10]." );
-- goto out;
-- }
-- for ( i = 0; i < len; i++ ) {
-- if ( !g_ascii_isdigit( pin[i] ) ) {
-- err = _( "The PIN is invalid. It should only consist of digits [0-9]." );
-- goto out;
-- }
-- }
-- pin2 = purple_request_fields_get_string( fields, "pin2" );
-- if ( ( !pin2 ) || ( strcmp( pin, pin2 ) != 0 ) ) {
-- err = _( "The two PINs you entered do not match." );
-- goto out;
-- }
--
--out:
-- if ( !err ) {
-- /* update PIN in account */
-- purple_account_set_password( session->acc, pin );
--
-- /* update session object */
-- g_free( session->encpwd );
-- session->encpwd = mxit_encrypt_password( session );
--
-- /* send the update request to MXit */
-- mxit_send_extprofile_update( session, session->encpwd, 0, NULL );
-- }
-- else {
-- /* show error to user */
-- mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "PIN Update Error" ), err );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Enable the user to change their PIN.
-- *
-- * @param action The action object
-- */
--static void mxit_change_pin_action( PurplePluginAction* action )
--{
-- PurpleConnection* gc = (PurpleConnection*) action->context;
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
--
-- PurpleRequestFields* fields = NULL;
-- PurpleRequestFieldGroup* group = NULL;
-- PurpleRequestField* field = NULL;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_change_pin_action\n" );
--
-- fields = purple_request_fields_new();
-- group = purple_request_field_group_new(NULL);
-- purple_request_fields_add_group(fields, group);
--
-- /* pin */
-- field = purple_request_field_string_new( "pin", _( "PIN" ), session->acc->password, FALSE );
-- purple_request_field_string_set_masked( field, TRUE );
-- purple_request_field_group_add_field( group, field );
--
-- /* verify pin */
-- field = purple_request_field_string_new( "pin2", _( "Verify PIN" ), session->acc->password, FALSE );
-- purple_request_field_string_set_masked( field, TRUE );
-- purple_request_field_group_add_field( group, field );
--
-- /* (reference: "libpurple/request.h") */
-- purple_request_fields( gc, _( "Change PIN" ), _( "Change MXit PIN" ), NULL, fields, _( "Set" ),
-- G_CALLBACK( mxit_change_pin_cb ), _( "Cancel" ), NULL, purple_connection_get_account( gc ), NULL, NULL, gc );
--}
--
--
--/*------------------------------------------------------------------------
-- * Display the current splash-screen, or a notification pop-up if one is not available.
-- *
-- * @param action The action object
-- */
--static void mxit_splash_action( PurplePluginAction* action )
--{
-- PurpleConnection* gc = (PurpleConnection*) action->context;
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
--
-- if ( splash_current( session ) != NULL )
-- splash_display( session );
-- else
-- mxit_popup( PURPLE_NOTIFY_MSG_INFO, _( "View Splash" ), _( "There is no splash-screen currently available" ) );
--}
--
--
--/*------------------------------------------------------------------------
-- * Display info about the plugin.
-- *
-- * @param action The action object
-- */
--static void mxit_about_action( PurplePluginAction* action )
--{
-- char version[256];
--
-- g_snprintf( version, sizeof( version ),
-- "MXit Client Protocol v%i.%i\n\n"
-- "Author:\nPieter Loubser\n\n"
-- "Contributors:\nAndrew Victor\n\n"
-- "Testers:\nBraeme Le Roux\n\n",
-- ( MXIT_CP_PROTO_VESION / 10 ), ( MXIT_CP_PROTO_VESION % 10 ) );
--
-- mxit_popup( PURPLE_NOTIFY_MSG_INFO, _( "About" ), version );
--}
--
--
--/*------------------------------------------------------------------------
-- * Request list of suggested friends.
-- *
-- * @param action The action object
-- */
--static void mxit_suggested_friends_action( PurplePluginAction* action )
--{
-- PurpleConnection* gc = (PurpleConnection*) action->context;
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
-- const char* profilelist[] = {
-- CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME,
-- CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_STATUS, CP_PROFILE_AVATAR,
-- CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME };
--
-- mxit_send_suggest_friends( session, MXIT_SEARCHRESULTS_MAX, ARRAY_SIZE( profilelist ), profilelist );
--}
--
--
--/*------------------------------------------------------------------------
-- * Perform contact search.
-- *
-- * @param action The action object
-- */
--static void mxit_user_search_cb( PurpleConnection *gc, const char *input )
--{
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
-- const char* profilelist[] = {
-- CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME,
-- CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_STATUS, CP_PROFILE_AVATAR,
-- CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME };
--
-- mxit_send_suggest_search( session, MXIT_SEARCHRESULTS_MAX, input, ARRAY_SIZE( profilelist ), profilelist );
--}
--
--
--/*------------------------------------------------------------------------
-- * Display the search input form.
-- *
-- * @param action The action object
-- */
--static void mxit_user_search_action( PurplePluginAction* action )
--{
-- PurpleConnection* gc = (PurpleConnection*) action->context;
--
-- purple_request_input( gc, _( "Search for user" ),
-- _( "Search for a MXit contact" ),
-- _( "Type search information" ),
-- NULL, FALSE, FALSE, NULL,
-- _("_Search"), G_CALLBACK( mxit_user_search_cb ),
-- _("_Cancel"), NULL,
-- purple_connection_get_account( gc ), NULL, NULL,
-- gc);
--}
--
--
--/*------------------------------------------------------------------------
-- * Associate actions with the MXit plugin.
-- *
-- * @param plugin The MXit protocol plugin
-- * @param context The connection context (if available)
-- * @return The list of plugin actions
-- */
--GList* mxit_actions( PurplePlugin* plugin, gpointer context )
--{
-- PurplePluginAction* action = NULL;
-- GList* m = NULL;
--
-- /* display / change profile */
-- action = purple_plugin_action_new( _( "Change Profile..." ), mxit_profile_action );
-- m = g_list_append( m, action );
--
-- /* change PIN */
-- action = purple_plugin_action_new( _( "Change PIN..." ), mxit_change_pin_action );
-- m = g_list_append( m, action );
--
-- /* suggested friends */
-- action = purple_plugin_action_new( _( "Suggested friends..." ), mxit_suggested_friends_action );
-- m = g_list_append( m, action );
--
-- /* search for contacts */
-- action = purple_plugin_action_new( _( "Search for contacts..." ), mxit_user_search_action );
-- m = g_list_append( m, action );
--
-- /* display splash-screen */
-- action = purple_plugin_action_new( _( "View Splash..." ), mxit_splash_action );
-- m = g_list_append( m, action );
--
-- /* display plugin version */
-- action = purple_plugin_action_new( _( "About..." ), mxit_about_action );
-- m = g_list_append( m, action );
--
-- return m;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/actions.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/actions.h
---- pidgin-2.10.7/libpurple/protocols/mxit/actions.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/actions.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,34 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- handle MXit plugin actions --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MXIT_ACTIONS_H_
--#define _MXIT_ACTIONS_H_
--
--
--/* callbacks */
--GList* mxit_actions( PurplePlugin* plugin, gpointer context );
--
--
--#endif /* _MXIT_ACTIONS_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/aes.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/aes.c
---- pidgin-2.10.7/libpurple/protocols/mxit/aes.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/aes.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,405 +0,0 @@
--
--// advanced encryption standard
--// author: karl malbrain, malbrain@yahoo.com
--
--/*
--This work, including the source code, documentation
--and related data, is placed into the public domain.
--
--The orginal author is Karl Malbrain.
--
--THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
--OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
--MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
--ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
--RESULTING FROM THE USE, MODIFICATION, OR
--REDISTRIBUTION OF THIS SOFTWARE.
--*/
--
--#include <string.h>
--#include <memory.h>
--
--#include "aes.h"
--
--// AES only supports Nb=4
--#define Nb 4 // number of columns in the state & expanded key
--
--#define Nk 4 // number of columns in a key
--#define Nr 10 // number of rounds in encryption
--
--static uchar Sbox[256] = { // forward s-box
--0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
--0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
--0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
--0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
--0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
--0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
--0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
--0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
--0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
--0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
--0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
--0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
--0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
--0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
--0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
--0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};
--
--static uchar InvSbox[256] = { // inverse s-box
--0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
--0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
--0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
--0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
--0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
--0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
--0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
--0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
--0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
--0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
--0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
--0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
--0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
--0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
--0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
--0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d};
--
--// combined Xtimes2[Sbox[]]
--static uchar Xtime2Sbox[256] = {
--0xc6, 0xf8, 0xee, 0xf6, 0xff, 0xd6, 0xde, 0x91, 0x60, 0x02, 0xce, 0x56, 0xe7, 0xb5, 0x4d, 0xec,
--0x8f, 0x1f, 0x89, 0xfa, 0xef, 0xb2, 0x8e, 0xfb, 0x41, 0xb3, 0x5f, 0x45, 0x23, 0x53, 0xe4, 0x9b,
--0x75, 0xe1, 0x3d, 0x4c, 0x6c, 0x7e, 0xf5, 0x83, 0x68, 0x51, 0xd1, 0xf9, 0xe2, 0xab, 0x62, 0x2a,
--0x08, 0x95, 0x46, 0x9d, 0x30, 0x37, 0x0a, 0x2f, 0x0e, 0x24, 0x1b, 0xdf, 0xcd, 0x4e, 0x7f, 0xea,
--0x12, 0x1d, 0x58, 0x34, 0x36, 0xdc, 0xb4, 0x5b, 0xa4, 0x76, 0xb7, 0x7d, 0x52, 0xdd, 0x5e, 0x13,
--0xa6, 0xb9, 0x00, 0xc1, 0x40, 0xe3, 0x79, 0xb6, 0xd4, 0x8d, 0x67, 0x72, 0x94, 0x98, 0xb0, 0x85,
--0xbb, 0xc5, 0x4f, 0xed, 0x86, 0x9a, 0x66, 0x11, 0x8a, 0xe9, 0x04, 0xfe, 0xa0, 0x78, 0x25, 0x4b,
--0xa2, 0x5d, 0x80, 0x05, 0x3f, 0x21, 0x70, 0xf1, 0x63, 0x77, 0xaf, 0x42, 0x20, 0xe5, 0xfd, 0xbf,
--0x81, 0x18, 0x26, 0xc3, 0xbe, 0x35, 0x88, 0x2e, 0x93, 0x55, 0xfc, 0x7a, 0xc8, 0xba, 0x32, 0xe6,
--0xc0, 0x19, 0x9e, 0xa3, 0x44, 0x54, 0x3b, 0x0b, 0x8c, 0xc7, 0x6b, 0x28, 0xa7, 0xbc, 0x16, 0xad,
--0xdb, 0x64, 0x74, 0x14, 0x92, 0x0c, 0x48, 0xb8, 0x9f, 0xbd, 0x43, 0xc4, 0x39, 0x31, 0xd3, 0xf2,
--0xd5, 0x8b, 0x6e, 0xda, 0x01, 0xb1, 0x9c, 0x49, 0xd8, 0xac, 0xf3, 0xcf, 0xca, 0xf4, 0x47, 0x10,
--0x6f, 0xf0, 0x4a, 0x5c, 0x38, 0x57, 0x73, 0x97, 0xcb, 0xa1, 0xe8, 0x3e, 0x96, 0x61, 0x0d, 0x0f,
--0xe0, 0x7c, 0x71, 0xcc, 0x90, 0x06, 0xf7, 0x1c, 0xc2, 0x6a, 0xae, 0x69, 0x17, 0x99, 0x3a, 0x27,
--0xd9, 0xeb, 0x2b, 0x22, 0xd2, 0xa9, 0x07, 0x33, 0x2d, 0x3c, 0x15, 0xc9, 0x87, 0xaa, 0x50, 0xa5,
--0x03, 0x59, 0x09, 0x1a, 0x65, 0xd7, 0x84, 0xd0, 0x82, 0x29, 0x5a, 0x1e, 0x7b, 0xa8, 0x6d, 0x2c
--};
--
--// combined Xtimes3[Sbox[]]
--static uchar Xtime3Sbox[256] = {
--0xa5, 0x84, 0x99, 0x8d, 0x0d, 0xbd, 0xb1, 0x54, 0x50, 0x03, 0xa9, 0x7d, 0x19, 0x62, 0xe6, 0x9a,
--0x45, 0x9d, 0x40, 0x87, 0x15, 0xeb, 0xc9, 0x0b, 0xec, 0x67, 0xfd, 0xea, 0xbf, 0xf7, 0x96, 0x5b,
--0xc2, 0x1c, 0xae, 0x6a, 0x5a, 0x41, 0x02, 0x4f, 0x5c, 0xf4, 0x34, 0x08, 0x93, 0x73, 0x53, 0x3f,
--0x0c, 0x52, 0x65, 0x5e, 0x28, 0xa1, 0x0f, 0xb5, 0x09, 0x36, 0x9b, 0x3d, 0x26, 0x69, 0xcd, 0x9f,
--0x1b, 0x9e, 0x74, 0x2e, 0x2d, 0xb2, 0xee, 0xfb, 0xf6, 0x4d, 0x61, 0xce, 0x7b, 0x3e, 0x71, 0x97,
--0xf5, 0x68, 0x00, 0x2c, 0x60, 0x1f, 0xc8, 0xed, 0xbe, 0x46, 0xd9, 0x4b, 0xde, 0xd4, 0xe8, 0x4a,
--0x6b, 0x2a, 0xe5, 0x16, 0xc5, 0xd7, 0x55, 0x94, 0xcf, 0x10, 0x06, 0x81, 0xf0, 0x44, 0xba, 0xe3,
--0xf3, 0xfe, 0xc0, 0x8a, 0xad, 0xbc, 0x48, 0x04, 0xdf, 0xc1, 0x75, 0x63, 0x30, 0x1a, 0x0e, 0x6d,
--0x4c, 0x14, 0x35, 0x2f, 0xe1, 0xa2, 0xcc, 0x39, 0x57, 0xf2, 0x82, 0x47, 0xac, 0xe7, 0x2b, 0x95,
--0xa0, 0x98, 0xd1, 0x7f, 0x66, 0x7e, 0xab, 0x83, 0xca, 0x29, 0xd3, 0x3c, 0x79, 0xe2, 0x1d, 0x76,
--0x3b, 0x56, 0x4e, 0x1e, 0xdb, 0x0a, 0x6c, 0xe4, 0x5d, 0x6e, 0xef, 0xa6, 0xa8, 0xa4, 0x37, 0x8b,
--0x32, 0x43, 0x59, 0xb7, 0x8c, 0x64, 0xd2, 0xe0, 0xb4, 0xfa, 0x07, 0x25, 0xaf, 0x8e, 0xe9, 0x18,
--0xd5, 0x88, 0x6f, 0x72, 0x24, 0xf1, 0xc7, 0x51, 0x23, 0x7c, 0x9c, 0x21, 0xdd, 0xdc, 0x86, 0x85,
--0x90, 0x42, 0xc4, 0xaa, 0xd8, 0x05, 0x01, 0x12, 0xa3, 0x5f, 0xf9, 0xd0, 0x91, 0x58, 0x27, 0xb9,
--0x38, 0x13, 0xb3, 0x33, 0xbb, 0x70, 0x89, 0xa7, 0xb6, 0x22, 0x92, 0x20, 0x49, 0xff, 0x78, 0x7a,
--0x8f, 0xf8, 0x80, 0x17, 0xda, 0x31, 0xc6, 0xb8, 0xc3, 0xb0, 0x77, 0x11, 0xcb, 0xfc, 0xd6, 0x3a
--};
--
--// modular multiplication tables
--// based on:
--
--// Xtime2[x] = (x & 0x80 ? 0x1b : 0) ^ (x + x)
--// Xtime3[x] = x^Xtime2[x];
--
--#if 0
--static uchar Xtime2[256] = {
--0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
--0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
--0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
--0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
--0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
--0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
--0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
--0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
--0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
--0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25,
--0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45,
--0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
--0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
--0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
--0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
--0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5};
--#endif
--
--static uchar Xtime9[256] = {
--0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
--0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,
--0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
--0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc,
--0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01,
--0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91,
--0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a,
--0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa,
--0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b,
--0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b,
--0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0,
--0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30,
--0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
--0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
--0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
--0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46};
--
--static uchar XtimeB[256] = {
--0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69,
--0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9,
--0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
--0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2,
--0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f,
--0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f,
--0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4,
--0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54,
--0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e,
--0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e,
--0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5,
--0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55,
--0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
--0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
--0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
--0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3};
--
--static uchar XtimeD[256] = {
--0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b,
--0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b,
--0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
--0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20,
--0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26,
--0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6,
--0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d,
--0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d,
--0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91,
--0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41,
--0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a,
--0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa,
--0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
--0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
--0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
--0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97};
--
--static uchar XtimeE[256] = {
--0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a,
--0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba,
--0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
--0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61,
--0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7,
--0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17,
--0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c,
--0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc,
--0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b,
--0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb,
--0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0,
--0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20,
--0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
--0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
--0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
--0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d};
--
--// exchanges columns in each of 4 rows
--// row0 - unchanged, row1- shifted left 1,
--// row2 - shifted left 2 and row3 - shifted left 3
--static void ShiftRows (uchar *state)
--{
--uchar tmp;
--
-- // just substitute row 0
-- state[0] = Sbox[state[0]], state[4] = Sbox[state[4]];
-- state[8] = Sbox[state[8]], state[12] = Sbox[state[12]];
--
-- // rotate row 1
-- tmp = Sbox[state[1]], state[1] = Sbox[state[5]];
-- state[5] = Sbox[state[9]], state[9] = Sbox[state[13]], state[13] = tmp;
--
-- // rotate row 2
-- tmp = Sbox[state[2]], state[2] = Sbox[state[10]], state[10] = tmp;
-- tmp = Sbox[state[6]], state[6] = Sbox[state[14]], state[14] = tmp;
--
-- // rotate row 3
-- tmp = Sbox[state[15]], state[15] = Sbox[state[11]];
-- state[11] = Sbox[state[7]], state[7] = Sbox[state[3]], state[3] = tmp;
--}
--
--// restores columns in each of 4 rows
--// row0 - unchanged, row1- shifted right 1,
--// row2 - shifted right 2 and row3 - shifted right 3
--static void InvShiftRows (uchar *state)
--{
--uchar tmp;
--
-- // restore row 0
-- state[0] = InvSbox[state[0]], state[4] = InvSbox[state[4]];
-- state[8] = InvSbox[state[8]], state[12] = InvSbox[state[12]];
--
-- // restore row 1
-- tmp = InvSbox[state[13]], state[13] = InvSbox[state[9]];
-- state[9] = InvSbox[state[5]], state[5] = InvSbox[state[1]], state[1] = tmp;
--
-- // restore row 2
-- tmp = InvSbox[state[2]], state[2] = InvSbox[state[10]], state[10] = tmp;
-- tmp = InvSbox[state[6]], state[6] = InvSbox[state[14]], state[14] = tmp;
--
-- // restore row 3
-- tmp = InvSbox[state[3]], state[3] = InvSbox[state[7]];
-- state[7] = InvSbox[state[11]], state[11] = InvSbox[state[15]], state[15] = tmp;
--}
--
--// recombine and mix each row in a column
--static void MixSubColumns (uchar *state)
--{
--uchar tmp[4 * Nb];
--
-- // mixing column 0
-- tmp[0] = Xtime2Sbox[state[0]] ^ Xtime3Sbox[state[5]] ^ Sbox[state[10]] ^ Sbox[state[15]];
-- tmp[1] = Sbox[state[0]] ^ Xtime2Sbox[state[5]] ^ Xtime3Sbox[state[10]] ^ Sbox[state[15]];
-- tmp[2] = Sbox[state[0]] ^ Sbox[state[5]] ^ Xtime2Sbox[state[10]] ^ Xtime3Sbox[state[15]];
-- tmp[3] = Xtime3Sbox[state[0]] ^ Sbox[state[5]] ^ Sbox[state[10]] ^ Xtime2Sbox[state[15]];
--
-- // mixing column 1
-- tmp[4] = Xtime2Sbox[state[4]] ^ Xtime3Sbox[state[9]] ^ Sbox[state[14]] ^ Sbox[state[3]];
-- tmp[5] = Sbox[state[4]] ^ Xtime2Sbox[state[9]] ^ Xtime3Sbox[state[14]] ^ Sbox[state[3]];
-- tmp[6] = Sbox[state[4]] ^ Sbox[state[9]] ^ Xtime2Sbox[state[14]] ^ Xtime3Sbox[state[3]];
-- tmp[7] = Xtime3Sbox[state[4]] ^ Sbox[state[9]] ^ Sbox[state[14]] ^ Xtime2Sbox[state[3]];
--
-- // mixing column 2
-- tmp[8] = Xtime2Sbox[state[8]] ^ Xtime3Sbox[state[13]] ^ Sbox[state[2]] ^ Sbox[state[7]];
-- tmp[9] = Sbox[state[8]] ^ Xtime2Sbox[state[13]] ^ Xtime3Sbox[state[2]] ^ Sbox[state[7]];
-- tmp[10] = Sbox[state[8]] ^ Sbox[state[13]] ^ Xtime2Sbox[state[2]] ^ Xtime3Sbox[state[7]];
-- tmp[11] = Xtime3Sbox[state[8]] ^ Sbox[state[13]] ^ Sbox[state[2]] ^ Xtime2Sbox[state[7]];
--
-- // mixing column 3
-- tmp[12] = Xtime2Sbox[state[12]] ^ Xtime3Sbox[state[1]] ^ Sbox[state[6]] ^ Sbox[state[11]];
-- tmp[13] = Sbox[state[12]] ^ Xtime2Sbox[state[1]] ^ Xtime3Sbox[state[6]] ^ Sbox[state[11]];
-- tmp[14] = Sbox[state[12]] ^ Sbox[state[1]] ^ Xtime2Sbox[state[6]] ^ Xtime3Sbox[state[11]];
-- tmp[15] = Xtime3Sbox[state[12]] ^ Sbox[state[1]] ^ Sbox[state[6]] ^ Xtime2Sbox[state[11]];
--
-- memcpy (state, tmp, sizeof(tmp));
--}
--
--// restore and un-mix each row in a column
--static void InvMixSubColumns (uchar *state)
--{
--uchar tmp[4 * Nb];
--int i;
--
-- // restore column 0
-- tmp[0] = XtimeE[state[0]] ^ XtimeB[state[1]] ^ XtimeD[state[2]] ^ Xtime9[state[3]];
-- tmp[5] = Xtime9[state[0]] ^ XtimeE[state[1]] ^ XtimeB[state[2]] ^ XtimeD[state[3]];
-- tmp[10] = XtimeD[state[0]] ^ Xtime9[state[1]] ^ XtimeE[state[2]] ^ XtimeB[state[3]];
-- tmp[15] = XtimeB[state[0]] ^ XtimeD[state[1]] ^ Xtime9[state[2]] ^ XtimeE[state[3]];
--
-- // restore column 1
-- tmp[4] = XtimeE[state[4]] ^ XtimeB[state[5]] ^ XtimeD[state[6]] ^ Xtime9[state[7]];
-- tmp[9] = Xtime9[state[4]] ^ XtimeE[state[5]] ^ XtimeB[state[6]] ^ XtimeD[state[7]];
-- tmp[14] = XtimeD[state[4]] ^ Xtime9[state[5]] ^ XtimeE[state[6]] ^ XtimeB[state[7]];
-- tmp[3] = XtimeB[state[4]] ^ XtimeD[state[5]] ^ Xtime9[state[6]] ^ XtimeE[state[7]];
--
-- // restore column 2
-- tmp[8] = XtimeE[state[8]] ^ XtimeB[state[9]] ^ XtimeD[state[10]] ^ Xtime9[state[11]];
-- tmp[13] = Xtime9[state[8]] ^ XtimeE[state[9]] ^ XtimeB[state[10]] ^ XtimeD[state[11]];
-- tmp[2] = XtimeD[state[8]] ^ Xtime9[state[9]] ^ XtimeE[state[10]] ^ XtimeB[state[11]];
-- tmp[7] = XtimeB[state[8]] ^ XtimeD[state[9]] ^ Xtime9[state[10]] ^ XtimeE[state[11]];
--
-- // restore column 3
-- tmp[12] = XtimeE[state[12]] ^ XtimeB[state[13]] ^ XtimeD[state[14]] ^ Xtime9[state[15]];
-- tmp[1] = Xtime9[state[12]] ^ XtimeE[state[13]] ^ XtimeB[state[14]] ^ XtimeD[state[15]];
-- tmp[6] = XtimeD[state[12]] ^ Xtime9[state[13]] ^ XtimeE[state[14]] ^ XtimeB[state[15]];
-- tmp[11] = XtimeB[state[12]] ^ XtimeD[state[13]] ^ Xtime9[state[14]] ^ XtimeE[state[15]];
--
-- for( i=0; i < 4 * Nb; i++ )
-- state[i] = InvSbox[tmp[i]];
--}
--
--// encrypt/decrypt columns of the key
--// n.b. you can replace this with
--// byte-wise xor if you wish.
--
--static void AddRoundKey (unsigned *state, unsigned *key)
--{
--int idx;
--
-- for( idx = 0; idx < 4; idx++ )
-- state[idx] ^= key[idx];
--}
--
--static uchar Rcon[11] = {
--0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
--
--// produce Nb bytes for each round
--void ExpandKey (uchar *key, uchar *expkey)
--{
--uchar tmp0, tmp1, tmp2, tmp3, tmp4;
--unsigned idx;
--
-- memcpy (expkey, key, Nk * 4);
--
-- for( idx = Nk; idx < Nb * (Nr + 1); idx++ ) {
-- tmp0 = expkey[4*idx - 4];
-- tmp1 = expkey[4*idx - 3];
-- tmp2 = expkey[4*idx - 2];
-- tmp3 = expkey[4*idx - 1];
-- if( !(idx % Nk) ) {
-- tmp4 = tmp3;
-- tmp3 = Sbox[tmp0];
-- tmp0 = Sbox[tmp1] ^ Rcon[idx/Nk];
-- tmp1 = Sbox[tmp2];
-- tmp2 = Sbox[tmp4];
-- } else if( Nk > 6 && idx % Nk == 4 ) {
-- tmp0 = Sbox[tmp0];
-- tmp1 = Sbox[tmp1];
-- tmp2 = Sbox[tmp2];
-- tmp3 = Sbox[tmp3];
-- }
--
-- expkey[4*idx+0] = expkey[4*idx - 4*Nk + 0] ^ tmp0;
-- expkey[4*idx+1] = expkey[4*idx - 4*Nk + 1] ^ tmp1;
-- expkey[4*idx+2] = expkey[4*idx - 4*Nk + 2] ^ tmp2;
-- expkey[4*idx+3] = expkey[4*idx - 4*Nk + 3] ^ tmp3;
-- }
--}
--
--// encrypt one 128 bit block
--void Encrypt (uchar *in, uchar *expkey, uchar *out)
--{
--uchar state[Nb * 4];
--unsigned round;
--
-- memcpy (state, in, Nb * 4);
-- AddRoundKey ((unsigned *)state, (unsigned *)expkey);
--
-- for( round = 1; round < Nr + 1; round++ ) {
-- if( round < Nr )
-- MixSubColumns (state);
-- else
-- ShiftRows (state);
--
-- AddRoundKey ((unsigned *)state, (unsigned *)expkey + round * Nb);
-- }
--
-- memcpy (out, state, sizeof(state));
--}
--
--void Decrypt (uchar *in, uchar *expkey, uchar *out)
--{
--uchar state[Nb * 4];
--unsigned round;
--
-- memcpy (state, in, sizeof(state));
--
-- AddRoundKey ((unsigned *)state, (unsigned *)expkey + Nr * Nb);
-- InvShiftRows(state);
--
-- for( round = Nr; round--; )
-- {
-- AddRoundKey ((unsigned *)state, (unsigned *)expkey + round * Nb);
-- if( round )
-- InvMixSubColumns (state);
-- }
--
-- memcpy (out, state, sizeof(state));
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/aes.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/aes.h
---- pidgin-2.10.7/libpurple/protocols/mxit/aes.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/aes.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,39 +0,0 @@
--// advanced encryption standard
--// author: karl malbrain, malbrain@yahoo.com
--
--/*
--This work, including the source code, documentation
--and related data, is placed into the public domain.
--
--The orginal author is Karl Malbrain.
--
--THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
--OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
--MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
--ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
--RESULTING FROM THE USE, MODIFICATION, OR
--REDISTRIBUTION OF THIS SOFTWARE.
--*/
--
--
--#ifndef AES_MALBRAIN
--#define AES_MALBRAIN
--
--
--// AES only supports Nb=4
--#define Nb 4 // number of columns in the state & expanded key
--
--#define Nk 4 // number of columns in a key
--#define Nr 10 // number of rounds in encryption
--
--
--typedef unsigned char uchar;
--
--
--void ExpandKey (uchar *key, uchar *expkey);
--void Encrypt (uchar *in, uchar *expkey, uchar *out);
--void Decrypt (uchar *in, uchar *expkey, uchar *out);
--
--
--#endif /* AES_MALBRAIN */
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/chunk.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/chunk.c
---- pidgin-2.10.7/libpurple/protocols/mxit/chunk.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/chunk.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,686 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- handle chunked data (multimedia messages) --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "purple.h"
--#include "protocol.h"
--#include "mxit.h"
--#include "chunk.h"
--#include "filexfer.h"
--
--
--/*========================================================================================================================
-- * Data-Type encoding
-- */
--
--#if 0
--#include <byteswap.h>
--#if (__BYTE_ORDER == __BIG_ENDIAN)
--#define SWAP_64(x) (x)
--#else
--#define SWAP_64(x) bswap_64(x)
--#endif
--#endif
--
--/*------------------------------------------------------------------------
-- * Encode a single byte in the chunked data.
-- *
-- * @param chunkdata The chunked-data buffer
-- * @param value The byte
-- * @return The number of bytes added.
-- */
--static int add_int8( char* chunkdata, char value )
--{
-- *chunkdata = value;
--
-- return sizeof( char );
--}
--
--/*------------------------------------------------------------------------
-- * Encode a 16-bit value in the chunked data.
-- *
-- * @param chunkdata The chunked-data buffer
-- * @param value The 16-bit value
-- * @return The number of bytes added.
-- */
--static int add_int16( char* chunkdata, short value )
--{
-- value = htons( value ); /* network byte-order */
-- memcpy( chunkdata, &value, sizeof( short ) );
--
-- return sizeof( short );
--}
--
--/*------------------------------------------------------------------------
-- * Encode a 32-bit value in the chunked data.
-- *
-- * @param chunkdata The chunked-data buffer
-- * @param value The 32-bit value
-- * @return The number of bytes added.
-- */
--static int add_int32( char* chunkdata, int value )
--{
-- value = htonl( value ); /* network byte-order */
-- memcpy( chunkdata, &value, sizeof( int ) );
--
-- return sizeof( int );
--}
--
--#if 0
--/*------------------------------------------------------------------------
-- * Encode a 64-bit value in the chunked data.
-- *
-- * @param chunkdata The chunked-data buffer
-- * @param value The 64-bit value
-- * @return The number of bytes added.
-- */
--static int add_int64( char* chunkdata, int64_t value )
--{
-- value = SWAP_64( value ); /* network byte-order */
-- memcpy( chunkdata, &value, sizeof( int64_t ) );
--
-- return sizeof( int64_t );
--}
--#endif
--
--/*------------------------------------------------------------------------
-- * Encode a block of data in the chunked data.
-- *
-- * @param chunkdata The chunked-data buffer
-- * @param data The data to add
-- * @param datalen The length of the data to add
-- * @return The number of bytes added.
-- */
--static int add_data( char* chunkdata, const char* data, int datalen )
--{
-- memcpy( chunkdata, data, datalen );
--
-- return datalen;
--}
--
--/*------------------------------------------------------------------------
-- * Encode a string as UTF-8 in the chunked data.
-- *
-- * @param chunkdata The chunked-data buffer
-- * @param str The string to encode
-- * @return The number of bytes in the string
-- */
--static int add_utf8_string( char* chunkdata, const char* str )
--{
-- int pos = 0;
-- size_t len = strlen( str );
--
-- /* utf8 string length [2 bytes] */
-- pos += add_int16( &chunkdata[pos], len );
--
-- /* utf8 string */
-- pos += add_data( &chunkdata[pos], str, len );
--
-- return pos;
--}
--
--
--/*========================================================================================================================
-- * Data-Type decoding
-- */
--
--/*------------------------------------------------------------------------
-- * Extract a single byte from the chunked data.
-- *
-- * @param chunkdata The chunked-data buffer
-- * @param value The byte
-- * @return The number of bytes extracted.
-- */
--static int get_int8( const char* chunkdata, char* value )
--{
-- *value = *chunkdata;
--
-- return sizeof( char );
--}
--
--/*------------------------------------------------------------------------
-- * Extract a 16-bit value from the chunked data.
-- *
-- * @param chunkdata The chunked-data buffer
-- * @param value The 16-bit value
-- * @return The number of bytes extracted
-- */
--static int get_int16( const char* chunkdata, short* value )
--{
-- *value = ntohs( *( (const short*) chunkdata ) ); /* host byte-order */
--
-- return sizeof( short );
--}
--
--/*------------------------------------------------------------------------
-- * Extract a 32-bit value from the chunked data.
-- *
-- * @param chunkdata The chunked-data buffer
-- * @param value The 32-bit value
-- * @return The number of bytes extracted
-- */
--static int get_int32( const char* chunkdata, int* value )
--{
-- *value = ntohl( *( (const int*) chunkdata ) ); /* host byte-order */
--
-- return sizeof( int );
--}
--
--#if 0
--/*------------------------------------------------------------------------
-- * Extract a 64-bit value from the chunked data.
-- *
-- * @param chunkdata The chunked-data buffer
-- * @param value The 64-bit value
-- * @return The number of bytes extracted
-- */
--static int get_int64( const char* chunkdata, int64_t* value )
--{
-- *value = SWAP_64( *( (const int64_t*) chunkdata ) ); /* host byte-order */
--
-- return sizeof( int64_t );
--}
--#endif
--
--/*------------------------------------------------------------------------
-- * Copy a block of data from the chunked data.
-- *
-- * @param chunkdata The chunked-data buffer
-- * @param dest Where to store the extract data
-- * @param datalen The length of the data to extract
-- * @return The number of bytes extracted
-- */
--static int get_data( const char* chunkdata, char* dest, int datalen )
--{
-- memcpy( dest, chunkdata, datalen );
--
-- return datalen;
--}
--
--/*------------------------------------------------------------------------
-- * Extract a UTF-8 encoded string from the chunked data.
-- *
-- * @param chunkdata The chunked-data buffer
-- * @param str A pointer to extracted string. Must be g_free()'d.
-- * @param maxstrlen Maximum size of destination buffer.
-- * @return The number of bytes consumed
-- */
--static int get_utf8_string( const char* chunkdata, char* str, int maxstrlen )
--{
-- int pos = 0;
-- short len;
-- int skip = 0;
--
-- /* string length [2 bytes] */
-- pos += get_int16( &chunkdata[pos], &len );
--
-- if ( len > maxstrlen ) {
-- /* possible buffer overflow */
-- purple_debug_error( MXIT_PLUGIN_ID, "Buffer overflow detected (get_utf8_string)\n" );
-- skip = len - maxstrlen;
-- len = maxstrlen;
-- }
--
-- /* string data */
-- pos += get_data( &chunkdata[pos], str, len );
-- str[len] = '\0'; /* terminate string */
--
-- return pos + skip;
--}
--
--
--/*========================================================================================================================
-- * Chunked Data encoding
-- */
--
--/*------------------------------------------------------------------------
-- * Encode a "reject file" chunk. (Chunk type 7)
-- *
-- * @param chunkdata Chunked-data buffer
-- * @param fileid A unique ID that identifies this file
-- * @return The number of bytes encoded in the buffer
-- */
--int mxit_chunk_create_reject( char* chunkdata, const char* fileid )
--{
-- int pos = 0;
--
-- /* file id [8 bytes] */
-- pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
--
-- /* rejection reason [1 byte] */
-- pos += add_int8( &chunkdata[pos], REJECT_BY_USER );
--
-- /* rejection description [UTF-8 (optional)] */
-- pos += add_utf8_string( &chunkdata[pos], "" );
--
-- return pos;
--}
--
--
--/*------------------------------------------------------------------------
-- * Encode a "get file" request chunk. (Chunk type 8)
-- *
-- * @param chunkdata Chunked-data buffer
-- * @param fileid A unique ID that identifies this file
-- * @param filesize The number of bytes to retrieve
-- * @param offset The start offset in the file
-- * @return The number of bytes encoded in the buffer
-- */
--int mxit_chunk_create_get( char* chunkdata, const char* fileid, int filesize, int offset )
--{
-- int pos = 0;
--
-- /* file id [8 bytes] */
-- pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
--
-- /* offset [4 bytes] */
-- pos += add_int32( &chunkdata[pos], offset );
--
-- /* length [4 bytes] */
-- pos += add_int32( &chunkdata[pos], filesize );
--
-- return pos;
--}
--
--
--/*------------------------------------------------------------------------
-- * Encode a "received file" chunk. (Chunk type 9)
-- *
-- * @param chunkdata Chunked-data buffer
-- * @param fileid A unique ID that identifies this file
-- * @param status The status of the file transfer (see chunk.h)
-- * @return The number of bytes encoded in the buffer
-- */
--int mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status )
--{
-- int pos = 0;
--
-- /* file id [8 bytes] */
-- pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
--
-- /* status [1 byte] */
-- pos += add_int8( &chunkdata[pos], status );
--
-- return pos;
--}
--
--
--/*------------------------------------------------------------------------
-- * Encode a "send file direct" chunk. (Chunk type 10)
-- *
-- * @param chunkdata Chunked-data buffer
-- * @param username The username of the recipient
-- * @param filename The name of the file being sent
-- * @param data The file contents
-- * @param datalen The size of the file contents
-- * @return The number of bytes encoded in the buffer
-- */
--int mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, int datalen )
--{
-- int pos = 0;
-- const char* mime = NULL;
--
-- /* data length [4 bytes] */
-- pos += add_int32( &chunkdata[pos], datalen );
--
-- /* number of username(s) [2 bytes] */
-- pos += add_int16( &chunkdata[pos], 1 );
--
-- /* username(s) [UTF-8] */
-- pos += add_utf8_string( &chunkdata[pos], username );
--
-- /* filename [UTF-8] */
-- pos += add_utf8_string( &chunkdata[pos], filename );
--
-- /* file mime type [UTF-8] */
-- mime = file_mime_type( filename, (const char*) data, datalen );
-- pos += add_utf8_string( &chunkdata[pos], mime );
--
-- /* human readable description [UTF-8 (optional)] */
-- pos += add_utf8_string( &chunkdata[pos], "" );
--
-- /* crc [4 bytes] (0 = optional) */
-- pos += add_int32( &chunkdata[pos], 0 );
--
-- /* the actual file data */
-- pos += add_data( &chunkdata[pos], (const char *) data, datalen );
--
-- return pos;
--}
--
--
--/*------------------------------------------------------------------------
-- * Encode a "set avatar" chunk. (Chunk type 13)
-- *
-- * @param chunkdata Chunked-data buffer
-- * @param data The avatar data
-- * @param datalen The size of the avatar data
-- * @return The number of bytes encoded in the buffer
-- */
--int mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, int datalen )
--{
-- const char fileid[MXIT_CHUNK_FILEID_LEN];
-- int pos = 0;
--
-- /* id [8 bytes] */
-- memset( &fileid, 0, sizeof( fileid ) ); /* set to 0 for file upload */
-- pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
--
-- /* size [4 bytes] */
-- pos += add_int32( &chunkdata[pos], datalen );
--
-- /* crc [4 bytes] (0 = optional) */
-- pos += add_int32( &chunkdata[pos], 0 );
--
-- /* the actual file data */
-- pos += add_data( &chunkdata[pos], (const char *) data, datalen );
--
-- return pos;
--}
--
--
--/*------------------------------------------------------------------------
-- * Encode a "get avatar" chunk. (Chunk type 14)
-- *
-- * @param chunkdata Chunked-data buffer
-- * @param mxitId The username who's avatar to download
-- * @param avatarId The Id of the avatar image (as string)
-- * @return The number of bytes encoded in the buffer
-- */
--int mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId )
--{
-- int pos = 0;
--
-- /* number of avatars [4 bytes] */
-- pos += add_int32( &chunkdata[pos], 1 );
--
-- /* username [UTF-8] */
-- pos += add_utf8_string( &chunkdata[pos], mxitId );
--
-- /* avatar id [UTF-8] */
-- pos += add_utf8_string( &chunkdata[pos], avatarId );
--
-- /* avatar format [UTF-8] */
-- pos += add_utf8_string( &chunkdata[pos], MXIT_AVATAR_TYPE );
--
-- /* avatar bit depth [1 byte] */
-- pos += add_int8( &chunkdata[pos], MXIT_AVATAR_BITDEPT );
--
-- /* number of sizes [2 bytes] */
-- pos += add_int16( &chunkdata[pos], 1 );
--
-- /* image size [4 bytes] */
-- pos += add_int32( &chunkdata[pos], MXIT_AVATAR_SIZE );
--
-- return pos;
--}
--
--
--/*========================================================================================================================
-- * Chunked Data decoding
-- */
--
--/*------------------------------------------------------------------------
-- * Parse a received "offer file" chunk. (Chunk 6)
-- *
-- * @param chunkdata Chunked data buffer
-- * @param datalen The length of the chunked data
-- * @param offer Decoded offerfile information
-- */
--void mxit_chunk_parse_offer( char* chunkdata, int datalen, struct offerfile_chunk* offer )
--{
-- int pos = 0;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_offer (%i bytes)\n", datalen );
--
-- /* id [8 bytes] */
-- pos += get_data( &chunkdata[pos], offer->fileid, 8);
--
-- /* from username [UTF-8] */
-- pos += get_utf8_string( &chunkdata[pos], offer->username, sizeof( offer->username ) );
-- mxit_strip_domain( offer->username );
--
-- /* file size [4 bytes] */
-- pos += get_int32( &chunkdata[pos], &(offer->filesize) );
--
-- /* filename [UTF-8] */
-- pos += get_utf8_string( &chunkdata[pos], offer->filename, sizeof( offer->filename ) );
--
-- /* mime type [UTF-8] */
-- pos += get_utf8_string( &chunkdata[pos], offer->mimetype, sizeof( offer->mimetype ) );
--
-- /* timestamp [8 bytes] */
-- /* not used by libPurple */
--
-- /* file description [UTF-8] */
-- /* not used by libPurple */
--
-- /* file alternative [UTF-8] */
-- /* not used by libPurple */
--
-- /* flags [4 bytes] */
-- /* not used by libPurple */
--}
--
--
--/*------------------------------------------------------------------------
-- * Parse a received "get file" response chunk. (Chunk 8)
-- *
-- * @param chunkdata Chunked data buffer
-- * @param datalen The length of the chunked data
-- * @param offer Decoded getfile information
-- */
--void mxit_chunk_parse_get( char* chunkdata, int datalen, struct getfile_chunk* getfile )
--{
-- int pos = 0;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_file (%i bytes)\n", datalen );
--
-- /* id [8 bytes] */
-- pos += get_data( &chunkdata[pos], getfile->fileid, 8 );
--
-- /* offset [4 bytes] */
-- pos += get_int32( &chunkdata[pos], &(getfile->offset) );
--
-- /* file length [4 bytes] */
-- pos += get_int32( &chunkdata[pos], &(getfile->length) );
--
-- /* crc [4 bytes] */
-- pos += get_int32( &chunkdata[pos], &(getfile->crc) );
--
-- /* file data */
-- getfile->data = &chunkdata[pos];
--}
--
--
--/*------------------------------------------------------------------------
-- * Parse a received splash screen chunk. (Chunk 2)
-- *
-- * @param chunkdata Chunked data buffer
-- * @param datalen The length of the chunked data
-- * @param splash Decoded splash image information
-- */
--static void mxit_chunk_parse_splash( char* chunkdata, int datalen, struct splash_chunk* splash )
--{
-- int pos = 0;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_splash (%i bytes)\n", datalen );
--
-- /* anchor [1 byte] */
-- pos += get_int8( &chunkdata[pos], &(splash->anchor) );
--
-- /* time to show [1 byte] */
-- pos += get_int8( &chunkdata[pos], &(splash->showtime) );
--
-- /* background color [4 bytes] */
-- pos += get_int32( &chunkdata[pos], &(splash->bgcolor) );
--
-- /* file data */
-- splash->data = &chunkdata[pos];
--
-- /* data length */
-- splash->datalen = datalen - pos;
--}
--
--
--/*------------------------------------------------------------------------
-- * Parse a received "custom resource" chunk. (Chunk 1)
-- *
-- * @param chunkdata Chunked data buffer
-- * @param datalen The length of the chunked data
-- * @param offer Decoded custom resource
-- */
--void mxit_chunk_parse_cr( char* chunkdata, int datalen, struct cr_chunk* cr )
--{
-- int pos = 0;
-- int chunklen = 0;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_cr (%i bytes)\n", datalen );
--
-- /* id [UTF-8] */
-- pos += get_utf8_string( &chunkdata[pos], cr->id, sizeof( cr->id ) );
--
-- /* handle [UTF-8] */
-- pos += get_utf8_string( &chunkdata[pos], cr->handle, sizeof( cr->handle ) );
--
-- /* operation [1 byte] */
-- pos += get_int8( &chunkdata[pos], &(cr->operation) );
--
-- /* chunk size [4 bytes] */
-- pos += get_int32( &chunkdata[pos], &chunklen );
--
-- /* parse the resource chunks */
-- while ( chunklen > 0 ) {
-- gchar* chunk = &chunkdata[pos];
--
-- /* start of chunk data */
-- pos += MXIT_CHUNK_HEADER_SIZE;
--
-- switch ( chunk_type( chunk ) ) {
-- case CP_CHUNK_SPLASH : /* splash image */
-- {
-- struct splash_chunk* splash = g_new0( struct splash_chunk, 1 );
--
-- mxit_chunk_parse_splash( &chunkdata[pos], chunk_length( chunk ), splash );
--
-- cr->resources = g_list_append( cr->resources, splash );
-- break;
-- }
-- case CP_CHUNK_CLICK : /* splash click */
-- {
-- struct splash_click_chunk* click = g_new0( struct splash_click_chunk, 1 );
--
-- cr->resources = g_list_append( cr->resources, click );
-- break;
-- }
-- default:
-- purple_debug_info( MXIT_PLUGIN_ID, "Unsupported custom resource chunk received (%i)\n", chunk_type( chunk) );
-- }
--
-- /* skip over data to next resource chunk */
-- pos += chunk_length( chunk );
-- chunklen -= ( MXIT_CHUNK_HEADER_SIZE + chunk_length( chunk ) );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Parse a received "send file direct" response chunk. (Chunk 10)
-- *
-- * @param chunkdata Chunked data buffer
-- * @param datalen The length of the chunked data
-- * @param sendfile Decoded sendfile information
-- */
--void mxit_chunk_parse_sendfile( char* chunkdata, int datalen, struct sendfile_chunk* sendfile )
--{
-- int pos = 0;
-- short entries = 0;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_sendfile (%i bytes)\n", datalen );
--
-- /* number of entries [2 bytes] */
-- pos += get_int16( &chunkdata[pos], &entries );
--
-- if ( entries < 1 ) /* no data */
-- return;
--
-- /* contactAddress [UTF-8 string] */
-- pos += get_utf8_string( &chunkdata[pos], sendfile->username, sizeof( sendfile->username ) );
--
-- /* status [4 bytes] */
-- pos += get_int32( &chunkdata[pos], &(sendfile->status) );
--
-- /* status message [UTF-8 string] */
-- pos += get_utf8_string( &chunkdata[pos], sendfile->statusmsg, sizeof( sendfile->statusmsg ) );
--}
--
--
--/*------------------------------------------------------------------------
-- * Parse a received "get avatar" response chunk. (Chunk 14)
-- *
-- * @param chunkdata Chunked data buffer
-- * @param datalen The length of the chunked data
-- * @param avatar Decoded avatar information
-- */
--void mxit_chunk_parse_get_avatar( char* chunkdata, int datalen, struct getavatar_chunk* avatar )
--{
-- int pos = 0;
-- int numfiles = 0;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_get_avatar (%i bytes)\n", datalen );
--
-- /* number of files [4 bytes] */
-- pos += get_int32( &chunkdata[pos], &numfiles );
--
-- if ( numfiles < 1 ) /* no data */
-- return;
--
-- /* mxitId [UTF-8 string] */
-- pos += get_utf8_string( &chunkdata[pos], avatar->mxitid, sizeof( avatar->mxitid ) );
--
-- /* avatar id [UTF-8 string] */
-- pos += get_utf8_string( &chunkdata[pos], avatar->avatarid, sizeof( avatar->avatarid ) );
--
-- /* format [UTF-8 string] */
-- pos += get_utf8_string( &chunkdata[pos], avatar->format, sizeof( avatar->format ) );
--
-- /* bit depth [1 byte] */
-- pos += get_int8( &chunkdata[pos], &(avatar->bitdepth) );
--
-- /* crc [4 bytes] */
-- pos += get_int32( &chunkdata[pos], &(avatar->crc) );
--
-- /* width [4 bytes] */
-- pos += get_int32( &chunkdata[pos], &(avatar->width) );
--
-- /* height [4 bytes] */
-- pos += get_int32( &chunkdata[pos], &(avatar->height) );
--
-- /* file length [4 bytes] */
-- pos += get_int32( &chunkdata[pos], &(avatar->length) );
--
-- /* file data */
-- avatar->data = &chunkdata[pos];
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/chunk.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/chunk.h
---- pidgin-2.10.7/libpurple/protocols/mxit/chunk.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/chunk.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,192 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- handle chunked data (multimedia messages) --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MXIT_CHUNK_H_
--#define _MXIT_CHUNK_H_
--
--
--#include "roster.h"
--
--
--#define MXIT_CHUNK_FILEID_LEN 8 /* bytes */
--#define MXIT_CHUNK_HEADER_SIZE 5 /* type (1 byte) + length (4 bytes) */
--
--
--/* Multimedia chunk types */
--#define CP_CHUNK_NONE 0x00 /* (0) no chunk */
--#define CP_CHUNK_CUSTOM 0x01 /* (1) custom resource */
--#define CP_CHUNK_SPLASH 0x02 /* (2) splash image */
--#define CP_CHUNK_CLICK 0x03 /* (3) splash click through */
--#define CP_CHUNK_OFFER 0x06 /* (6) offer file */
--#define CP_CHUNK_REJECT 0x07 /* (7) reject file */
--#define CP_CHUNK_GET 0x08 /* (8) get file */
--#define CP_CHUNK_RECEIVED 0x09 /* (9) received file */
--#define CP_CHUNK_DIRECT_SND 0x0A /* (10) send file direct */
--#define CP_CHUNK_DIRECT_FWD 0x0B /* (11) forward file direct */
--#define CP_CHUNK_SKIN 0x0C /* (12) MXit client skin */
--#define CP_CHUNK_SET_AVATAR 0x0D /* (13) set avatar */
--#define CP_CHUNK_GET_AVATAR 0x0E /* (14) get avatar */
--#define CP_CHUNK_END 0x7E /* (126) end */
--#define CP_CHUNK_EXT 0x7F /* (127) extended type */
--
--
--/* Custom Resource operations */
--#define CR_OP_UPDATE 0
--#define CR_OP_REMOVE 1
--
--/* File Received status */
--#define RECV_STATUS_SUCCESS 0
--#define RECV_STATUS_PARSE_FAIL 1
--#define RECV_STATUS_CANNOT_OPEN 8
--#define RECV_STATUS_BAD_CRC 9
--#define RECV_STATUS_BAD_ID 10
--
--/* File Reject status */
--#define REJECT_BY_USER 1
--#define REJECT_FILETYPE 2
--#define REJECT_NO_RESOURCES 3
--#define REJECT_BAD_RECIPIENT 4
--
--/*
-- * Chunk header manipulation functions
-- */
--static inline guint chunk_type( gchar* chunkheader )
--{
-- return *chunkheader;
--}
--
--static inline void set_chunk_type( gchar* chunkheader, guint type )
--{
-- *chunkheader = type;
--}
--
--static inline guint32 chunk_length( gchar* chunkheader )
--{
-- guint32 length = *( (const guint32*) &chunkheader[1] );
-- return htonl( length );
--}
--
--static inline void set_chunk_length( gchar* chunkheader, guint32 size )
--{
-- size = htonl( size );
-- memcpy( &chunkheader[1], &size, sizeof( guint32 ) );
--}
--
--static inline gchar* chunk_data( gchar* chunkheader )
--{
-- return &chunkheader[MXIT_CHUNK_HEADER_SIZE];
--}
--
--/*
-- * Offer File chunk (6).
-- */
--struct offerfile_chunk {
-- char fileid[MXIT_CHUNK_FILEID_LEN];
-- char username[MXIT_CP_MAX_JID_LEN + 1];
-- int filesize;
-- char filename[FILENAME_MAX];
-- char mimetype[64];
--};
--
--/*
-- * Get File chunk (8) response.
-- */
--struct getfile_chunk {
-- char fileid[MXIT_CHUNK_FILEID_LEN];
-- int offset;
-- int length;
-- int crc;
-- char* data;
--};
--
--/*
-- * Custom Resource chunk (1).
-- */
--struct cr_chunk {
-- char id[64];
-- char handle[64];
-- char operation;
-- GList* resources;
--};
--
--/*
-- * Splash Image chunk (2)
-- */
--struct splash_chunk {
-- char anchor;
-- char showtime;
-- int bgcolor;
-- char* data;
-- int datalen;
--};
--
--/*
-- * Splash Click Through chunk (3)
-- */
--struct splash_click_chunk {
-- char reserved[1];
--};
--
--/*
-- * Get Avatar chunk (14) response.
-- */
--struct getavatar_chunk {
-- char mxitid[50];
-- char avatarid[64];
-- char format[16];
-- char bitdepth;
-- int crc;
-- int width;
-- int height;
-- int length;
-- char* data;
--};
--
--/*
-- * Send File Direct chunk (10) response.
-- */
--struct sendfile_chunk {
-- char username[MXIT_CP_MAX_JID_LEN + 1];
-- int status;
-- char statusmsg[1024];
--};
--
--/* Encode chunk */
--int mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, int datalen );
--int mxit_chunk_create_reject( char* chunkdata, const char* fileid );
--int mxit_chunk_create_get( char* chunkdata, const char* fileid, int filesize, int offset );
--int mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status );
--int mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, int datalen );
--int mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId );
--
--/* Decode chunk */
--void mxit_chunk_parse_offer( char* chunkdata, int datalen, struct offerfile_chunk* offer );
--void mxit_chunk_parse_get( char* chunkdata, int datalen, struct getfile_chunk* getfile );
--void mxit_chunk_parse_cr( char* chunkdata, int datalen, struct cr_chunk* cr );
--void mxit_chunk_parse_sendfile( char* chunkdata, int datalen, struct sendfile_chunk* sendfile );
--void mxit_chunk_parse_get_avatar( char* chunkdata, int datalen, struct getavatar_chunk* avatar );
--
--#endif /* _MXIT_CHUNK_H_ */
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/cipher.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/cipher.c
---- pidgin-2.10.7/libpurple/protocols/mxit/cipher.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/cipher.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,245 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- encryption --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "purple.h"
--
--#include "mxit.h"
--#include "cipher.h"
--#include "aes.h"
--
--
--/* encryption */
--#define INITIAL_KEY "6170383452343567"
--#define SECRET_HEADER "<mxit/>"
--#define ENCRYPT_HEADER "<mxitencrypted ver=\"5.2\"/>"
--
--
--/*------------------------------------------------------------------------
-- * Add ISO10126 Padding to the data.
-- *
-- * @param data The data to pad.
-- */
--static void padding_add( GString* data )
--{
-- unsigned int blocks = ( data->len / 16 ) + 1;
-- unsigned int padding = ( blocks * 16 ) - data->len;
--
-- g_string_set_size( data, blocks * 16 );
-- data->str[data->len - 1] = padding;
--}
--
--
--/*------------------------------------------------------------------------
-- * Remove ISO10126 Padding from the data.
-- *
-- * @param data The data from which to remove padding.
-- */
--static void padding_remove( GString* data )
--{
-- unsigned int padding;
--
-- if ( data->len == 0 )
-- return;
--
-- padding = data->str[data->len - 1];
-- g_string_truncate( data, data->len - padding );
--}
--
--
--/*------------------------------------------------------------------------
-- * Generate the Transport-Layer crypto key.
-- * (Note: this function is not-thread safe)
-- *
-- * @param session The MXit Session object
-- * @return The transport-layer crypto key.
-- */
--static char* transport_layer_key( struct MXitSession* session )
--{
-- static char key[16 + 1];
-- const char* password = purple_account_get_password( session->acc );
-- int passlen = strlen( password );
--
-- /* initialize with initial key */
-- g_strlcpy( key, INITIAL_KEY, sizeof( key ) );
--
-- /* client key (8 bytes) */
-- memcpy( key, session->clientkey, strlen( session->clientkey ) );
--
-- /* add last 8 characters of the PIN (no padding if less characters) */
-- if ( passlen <= 8 )
-- memcpy( key + 8, password, passlen );
-- else
-- memcpy( key + 8, password + ( passlen - 8 ), 8 );
--
-- return key;
--}
--
--
--/*------------------------------------------------------------------------
-- * Encrypt the user's cleartext password using the AES 128-bit (ECB)
-- * encryption algorithm.
-- *
-- * @param session The MXit session object
-- * @return The encrypted & encoded password. Must be g_free'd when no longer needed.
-- */
--char* mxit_encrypt_password( struct MXitSession* session )
--{
-- char key[16 + 1];
-- char exkey[512];
-- GString* pass = NULL;
-- GString* encrypted = NULL;
-- char* base64;
-- int i;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_encrypt_password\n" );
--
-- /* build the AES encryption key */
-- g_strlcpy( key, INITIAL_KEY, sizeof( key ) );
-- memcpy( key, session->clientkey, strlen( session->clientkey ) );
-- ExpandKey( (unsigned char*) key, (unsigned char*) exkey );
--
-- /* build the secret data to be encrypted: SECRET_HEADER + password */
-- pass = g_string_new( SECRET_HEADER );
-- g_string_append( pass, purple_account_get_password( session->acc) );
-- padding_add( pass ); /* add ISO10126 padding */
--
-- /* now encrypt the secret. we encrypt each block separately (ECB mode) */
-- encrypted = g_string_sized_new( pass->len );
-- for ( i = 0; i < pass->len; i += 16 ) {
-- char block[16];
--
-- Encrypt( (unsigned char*) pass->str + i, (unsigned char*) exkey, (unsigned char*) block );
-- g_string_append_len( encrypted, block, 16 );
-- }
--
-- /* now base64 encode the encrypted password */
-- base64 = purple_base64_encode( (unsigned char*) encrypted->str, encrypted->len );
-- g_string_free( encrypted, TRUE );
--
-- g_string_free( pass, TRUE );
--
-- return base64;
--}
--
--
--/*------------------------------------------------------------------------
-- * Decrypt a message using transport-layer encryption.
-- *
-- * @param session The MXit session object
-- * @param message The encrypted message data (is base64-encoded).
-- * @return The decrypted message. Must be g_free'd when no longer needed.
-- */
--char* mxit_decrypt_message( struct MXitSession* session, char* message )
--{
-- guchar* raw_message;
-- gsize raw_len;
-- char exkey[512];
-- GString* decoded = NULL;
-- int i;
--
-- /* remove optional header: <mxitencrypted ver="5.2"/> */
-- if ( strncmp( message, ENCRYPT_HEADER, strlen( ENCRYPT_HEADER ) ) == 0 )
-- message += strlen( ENCRYPT_HEADER );
--
-- /* base64 decode the message */
-- raw_message = purple_base64_decode( message, &raw_len );
--
-- /* AES-encrypted data is always blocks of 16 bytes */
-- if ( ( raw_len == 0 ) || ( raw_len % 16 != 0 ) )
-- return NULL;
--
-- /* build the AES key */
-- ExpandKey( (unsigned char*) transport_layer_key( session ), (unsigned char*) exkey );
--
-- /* AES decrypt each block */
-- decoded = g_string_sized_new( raw_len );
-- for ( i = 0; i < raw_len; i += 16 ) {
-- char block[16];
--
-- Decrypt( (unsigned char*) raw_message + i, (unsigned char*) exkey, (unsigned char*) block );
-- g_string_append_len( decoded, block, 16 );
-- }
-- g_free( raw_message );
--
-- /* check that the decrypted message starts with header: <mxit/> */
-- if ( strncmp( decoded->str, SECRET_HEADER, strlen( SECRET_HEADER ) != 0 ) ) {
-- g_string_free( decoded, TRUE );
-- return NULL; /* message could not be decrypted */
-- }
--
-- /* remove ISO10126 padding */
-- padding_remove( decoded );
--
-- /* remove encryption header */
-- g_string_erase( decoded, 0, strlen( SECRET_HEADER ) );
--
-- return g_string_free( decoded, FALSE );
--}
--
--
--/*------------------------------------------------------------------------
-- * Encrypt a message using transport-layer encryption.
-- *
-- * @param session The MXit session object
-- * @param message The message data.
-- * @return The encrypted message. Must be g_free'd when no longer needed.
-- */
--char* mxit_encrypt_message( struct MXitSession* session, char* message )
--{
-- GString* raw_message = NULL;
-- char exkey[512];
-- GString* encoded = NULL;
-- gchar* base64;
-- int i;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "encrypt message: '%s'\n", message );
--
-- /* append encryption header to message data */
-- raw_message = g_string_new( SECRET_HEADER );
-- g_string_append( raw_message, message );
-- padding_add( raw_message ); /* add ISO10126 padding */
--
-- /* build the AES key */
-- ExpandKey( (unsigned char*) transport_layer_key( session ), (unsigned char*) exkey );
--
-- /* AES encrypt each block */
-- encoded = g_string_sized_new( raw_message->len );
-- for ( i = 0; i < raw_message->len; i += 16 ) {
-- char block[16];
--
-- Encrypt( (unsigned char*) raw_message->str + i, (unsigned char*) exkey, (unsigned char*) block );
-- g_string_append_len( encoded, block, 16 );
-- }
-- g_string_free( raw_message, TRUE );
--
-- /* base64 encode the encrypted message */
-- base64 = purple_base64_encode( (unsigned char *) encoded->str, encoded->len );
-- g_string_free( encoded, TRUE );
--
-- purple_debug_info( MXIT_PLUGIN_ID, "encrypted message: '%s'\n", base64 );
--
-- return base64;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/cipher.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/cipher.h
---- pidgin-2.10.7/libpurple/protocols/mxit/cipher.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/cipher.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,38 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- encryption --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MXIT_CIPHER_H_
--#define _MXIT_CIPHER_H_
--
--
--struct MXitSession;
--
--
--char* mxit_encrypt_password( struct MXitSession* session );
--
--char* mxit_decrypt_message( struct MXitSession* session, char* message );
--char* mxit_encrypt_message( struct MXitSession* session, char* message );
--
--#endif /* _MXIT_CIPHER_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/filexfer.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/filexfer.c
---- pidgin-2.10.7/libpurple/protocols/mxit/filexfer.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/filexfer.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,451 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- file transfers (sending and receiving) --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "purple.h"
--#include "protocol.h"
--#include "mxit.h"
--#include "chunk.h"
--#include "filexfer.h"
--
--
--#define MIME_TYPE_OCTETSTREAM "application/octet-stream"
--
--
--/* supported file mime types */
--static struct mime_type {
-- const char* magic;
-- const short magic_len;
-- const char* mime;
--} const mime_types[] = {
-- /* magic length mime */
-- /* images */ { "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8, "image/png" }, /* image png */
-- { "\xFF\xD8", 2, "image/jpeg" }, /* image jpeg */
-- { "\x3C\x3F\x78\x6D\x6C", 5, "image/svg+xml" }, /* image SVGansi */
-- { "\xEF\xBB\xBF", 3, "image/svg+xml" }, /* image SVGutf */
-- { "\xEF\xBB\xBF", 3, "image/svg+xml" }, /* image SVGZ */
-- /* mxit */ { "\x4d\x58\x4d", 3, "application/mxit-msgs" }, /* mxit message */
-- { "\x4d\x58\x44\x01", 4, "application/mxit-mood" }, /* mxit mood */
-- { "\x4d\x58\x45\x01", 4, "application/mxit-emo" }, /* mxit emoticon */
-- { "\x4d\x58\x46\x01", 4, "application/mxit-emof" }, /* mxit emoticon frame */
-- { "\x4d\x58\x53\x01", 4, "application/mxit-skin" }, /* mxit skin */
-- /* audio */ { "\x4d\x54\x68\x64", 4, "audio/midi" }, /* audio midi */
-- { "\x52\x49\x46\x46", 4, "audio/wav" }, /* audio wav */
-- { "\xFF\xF1", 2, "audio/aac" }, /* audio aac1 */
-- { "\xFF\xF9", 2, "audio/aac" }, /* audio aac2 */
-- { "\xFF", 1, "audio/mp3" }, /* audio mp3 */
-- { "\x23\x21\x41\x4D\x52\x0A", 6, "audio/amr" }, /* audio AMR */
-- { "\x23\x21\x41\x4D\x52\x2D\x57\x42", 8, "audio/amr-wb" }, /* audio AMR WB */
-- { "\x00\x00\x00", 3, "audio/mp4" }, /* audio mp4 */
-- { "\x2E\x73\x6E\x64", 4, "audio/au" } /* audio AU */
--};
--
--
--/*------------------------------------------------------------------------
-- * Return the MIME type matching the data file.
-- *
-- * @param filename The name of file
-- * @param buf The data
-- * @param buflen The length of the data
-- * @return A MIME type string
-- */
--const char* file_mime_type( const char* filename, const char* buf, int buflen )
--{
-- unsigned int i;
--
-- /* check for matching magic headers */
-- for ( i = 0; i < ARRAY_SIZE( mime_types ); i++ ) {
--
-- if ( buflen < mime_types[i].magic_len ) /* data is shorter than size of magic */
-- continue;
--
-- if ( memcmp( buf, mime_types[i].magic, mime_types[i].magic_len ) == 0 )
-- return mime_types[i].mime;
-- }
--
-- /* we did not find the MIME type, so return the default (application/octet-stream) */
-- return MIME_TYPE_OCTETSTREAM;
--}
--
--
--/*------------------------------------------------------------------------
-- * Cleanup and deallocate a MXit file transfer object
-- *
-- * @param xfer The file transfer object
-- */
--static void mxit_xfer_free( PurpleXfer* xfer )
--{
-- struct mxitxfer* mx = (struct mxitxfer*) xfer->data;;
--
-- if ( mx ) {
-- g_free( mx );
-- xfer->data = NULL;
-- }
--}
--
--
--/*========================================================================================================================
-- * File Transfer callbacks
-- */
--
--/*------------------------------------------------------------------------
-- * Initialise a new file transfer.
-- *
-- * @param xfer The file transfer object
-- */
--static void mxit_xfer_init( PurpleXfer* xfer )
--{
-- struct mxitxfer* mx = (struct mxitxfer*) xfer->data;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_init\n" );
--
-- if ( purple_xfer_get_type( xfer ) == PURPLE_XFER_SEND ) {
-- /* we are trying to send a file to MXit */
--
-- if ( purple_xfer_get_size( xfer ) > CP_MAX_FILESIZE ) {
-- /* the file is too big */
-- purple_xfer_error( xfer->type, xfer->account, xfer->who, _( "The file you are trying to send is too large!" ) );
-- purple_xfer_cancel_local( xfer );
-- return;
-- }
--
-- /* start the file transfer */
-- purple_xfer_start( xfer, -1, NULL, 0 );
-- }
-- else {
-- /*
-- * we have just accepted a file transfer request from MXit. send a confirmation
-- * to the MXit server so that can send us the file
-- */
-- mxit_send_file_accept( mx->session, mx->fileid, purple_xfer_get_size( xfer ), 0 );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Start the file transfer.
-- *
-- * @param xfer The file transfer object
-- */
--static void mxit_xfer_start( PurpleXfer* xfer )
--{
-- unsigned char* buffer;
-- int size;
-- int wrote;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_start\n" );
--
-- if ( purple_xfer_get_type( xfer ) == PURPLE_XFER_SEND ) {
-- /*
-- * the user wants to send a file to one of his contacts. we need to create
-- * a buffer and copy the file data into memory and then we can send it to
-- * the contact. we will send the whole file with one go.
-- */
-- buffer = g_malloc( xfer->bytes_remaining );
-- size = fread( buffer, xfer->bytes_remaining, 1, xfer->dest_fp );
--
-- wrote = purple_xfer_write( xfer, buffer, xfer->bytes_remaining );
-- if ( wrote > 0 )
-- purple_xfer_set_bytes_sent( xfer, wrote );
--
-- /* free the buffer */
-- g_free( buffer );
-- buffer = NULL;
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * The file transfer has ended.
-- *
-- * @param xfer The file transfer object
-- */
--static void mxit_xfer_end( PurpleXfer* xfer )
--{
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_end\n" );
--
-- /* deallocate object */
-- mxit_xfer_free( xfer );
--}
--
--
--/*------------------------------------------------------------------------
-- * The file transfer (to a user) has been cancelled.
-- *
-- * @param xfer The file transfer object
-- */
--static void mxit_xfer_cancel_send( PurpleXfer* xfer )
--{
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_cancel_send\n" );
--
-- /* deallocate object */
-- mxit_xfer_free( xfer );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send the file data.
-- *
-- * @param buffer The data to sent
-- * @param size The length of the data to send
-- * @param xfer The file transfer object
-- * @return The amount of data actually sent
-- */
--static gssize mxit_xfer_write( const guchar* buffer, size_t size, PurpleXfer* xfer )
--{
-- struct mxitxfer* mx = (struct mxitxfer*) xfer->data;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_write\n" );
--
-- if ( !mx ) {
-- purple_debug_warning( MXIT_PLUGIN_ID, "mxit_xfer_write: invalid internal mxit xfer data\n" );
-- return -1;
-- }
-- else if ( purple_xfer_get_type( xfer ) != PURPLE_XFER_SEND ) {
-- purple_debug_warning( MXIT_PLUGIN_ID, "mxit_xfer_write: wrong xfer type received\n" );
-- return -1;
-- }
--
-- /* create and send the packet to MXit */
-- mxit_send_file( mx->session, purple_xfer_get_remote_user( xfer ), purple_xfer_get_filename( xfer ), buffer, size );
--
-- /* the transfer is complete */
-- purple_xfer_set_completed( xfer, TRUE );
--
-- return size;
--}
--
--
--/*------------------------------------------------------------------------
-- * The user has rejected a file offer from MXit.
-- *
-- * @param xfer The file transfer object
-- */
--static void mxit_xfer_request_denied( PurpleXfer* xfer )
--{
-- struct mxitxfer* mx = (struct mxitxfer*) xfer->data;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_request_denied\n" );
--
-- /* send file reject packet to MXit server */
-- mxit_send_file_reject( mx->session, mx->fileid );
--
-- /* deallocate object */
-- mxit_xfer_free( xfer );
--}
--
--
--/*------------------------------------------------------------------------
-- * The file transfer (from MXit) has been cancelled.
-- */
--static void mxit_xfer_cancel_recv( PurpleXfer* xfer )
--{
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_cancel_recv\n" );
--
-- /* deallocate object */
-- mxit_xfer_free( xfer );
--}
--
--
--/*========================================================================================================================
-- * Callbacks from libPurple
-- */
--
--/*------------------------------------------------------------------------
-- * Indicate if file transfers are supported to this contact.
-- * For MXit file transfers are always supported.
-- *
-- * @param gc The connection object
-- * @param who The username of the contact
-- * @return TRUE if file transfers are supported
-- */
--gboolean mxit_xfer_enabled( PurpleConnection* gc, const char* who )
--{
-- return TRUE;
--}
--
--
--/*------------------------------------------------------------------------
-- * Create and initialize a new file transfer to a contact.
-- *
-- * @param gc The connection object
-- * @param who The username of the recipient
-- */
--PurpleXfer* mxit_xfer_new( PurpleConnection* gc, const char* who )
--{
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
-- PurpleXfer* xfer = NULL;
-- struct mxitxfer* mx = NULL;
--
-- /* (reference: "libpurple/ft.h") */
-- xfer = purple_xfer_new( session->acc, PURPLE_XFER_SEND, who );
--
-- /* create file info and attach it to the file transfer */
-- mx = g_new0( struct mxitxfer, 1 );
-- mx->session = session;
-- xfer->data = mx;
--
-- /* configure callbacks (reference: "libpurple/ft.h") */
-- purple_xfer_set_init_fnc( xfer, mxit_xfer_init );
-- purple_xfer_set_start_fnc( xfer, mxit_xfer_start );
-- purple_xfer_set_end_fnc( xfer, mxit_xfer_end );
-- purple_xfer_set_cancel_send_fnc( xfer, mxit_xfer_cancel_send );
-- purple_xfer_set_write_fnc( xfer, mxit_xfer_write );
--
-- return xfer;
--}
--
--
--/*------------------------------------------------------------------------
-- * The user has initiated a file transfer to a contact.
-- *
-- * @param gc The connection object
-- * @param who The username of the contact
-- * @param filename The filename (is NULL if request has not been accepted yet)
-- */
--void mxit_xfer_tx( PurpleConnection* gc, const char* who, const char* filename )
--{
-- PurpleXfer *xfer = mxit_xfer_new( gc, who );
--
-- if ( filename )
-- purple_xfer_request_accepted( xfer, filename );
-- else
-- purple_xfer_request( xfer );
--}
--
--
--/*========================================================================================================================
-- * Calls from the MXit Protocol layer
-- */
--
--/*------------------------------------------------------------------------
-- * A file transfer offer has been received from the MXit server.
-- *
-- * @param session The MXit session object
-- * @param usermame The username of the sender
-- * @param filename The name of the file being offered
-- * @param filesize The size of the file being offered
-- * @param fileid A unique ID that identifies this file
-- */
--void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, int filesize, const char* fileid )
--{
-- PurpleXfer* xfer = NULL;
-- struct mxitxfer* mx = NULL;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "File Offer: file=%s, from=%s, size=%i\n", filename, username, filesize );
--
-- xfer = purple_xfer_new( session->acc, PURPLE_XFER_RECEIVE, username );
-- if ( xfer ) {
-- /* create a new mxit xfer struct for internal use */
-- mx = g_new0( struct mxitxfer, 1 );
-- mx->session = session;
-- memcpy( mx->fileid, fileid, MXIT_CHUNK_FILEID_LEN );
-- xfer->data = mx;
--
-- purple_xfer_set_filename( xfer, filename );
-- if( filesize > 0 )
-- purple_xfer_set_size( xfer, filesize );
--
-- /* register file transfer callback functions */
-- purple_xfer_set_init_fnc( xfer, mxit_xfer_init );
-- purple_xfer_set_request_denied_fnc( xfer, mxit_xfer_request_denied );
-- purple_xfer_set_cancel_recv_fnc( xfer, mxit_xfer_cancel_recv );
-- purple_xfer_set_end_fnc( xfer, mxit_xfer_end );
--
-- /* give the request to the user to accept/deny */
-- purple_xfer_request( xfer );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Return the libPurple file-transfer object associated with a MXit transfer
-- *
-- * @param session The MXit session object
-- * @param fileid A unique ID that identifies this file
-- */
--static PurpleXfer* find_mxit_xfer( struct MXitSession* session, const char* fileid )
--{
-- GList* item = NULL;
-- PurpleXfer* xfer = NULL;
--
-- item = purple_xfers_get_all(); /* list of all active transfers */
-- while ( item ) {
-- xfer = item->data;
--
-- if ( xfer->account == session->acc ) {
-- /* transfer is associated with this MXit account */
-- struct mxitxfer* mx = xfer->data;
--
-- /* does the fileid match? */
-- if ( ( mx ) && ( memcmp( mx->fileid, fileid, MXIT_CHUNK_FILEID_LEN ) == 0 ) )
-- break;
-- }
--
-- item = g_list_next( item );
-- }
--
-- if ( item )
-- return item->data;
-- else
-- return NULL;
--}
--
--/*------------------------------------------------------------------------
-- * A file has been received from the MXit server.
-- *
-- * @param session The MXit session object
-- * @param fileid A unique ID that identifies this file
-- * @param data The file data
-- * @param datalen The size of the data
-- */
--void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, int datalen )
--{
-- PurpleXfer* xfer = NULL;
-- struct mxitxfer* mx = NULL;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_rx_file: (size=%i)\n", datalen );
--
-- /* find the file-transfer object */
-- xfer = find_mxit_xfer( session, fileid );
-- if ( xfer ) {
-- mx = xfer->data;
--
-- /* this is the transfer we have been looking for */
-- purple_xfer_ref( xfer );
-- purple_xfer_start( xfer, -1, NULL, 0 );
-- fwrite( data, datalen, 1, xfer->dest_fp );
-- purple_xfer_unref( xfer );
-- purple_xfer_set_completed( xfer, TRUE );
-- purple_xfer_end( xfer );
--
-- /* inform MXit that file was successfully received */
-- mxit_send_file_received( session, fileid, RECV_STATUS_SUCCESS );
-- }
-- else {
-- /* file transfer not found */
-- mxit_send_file_received( session, fileid, RECV_STATUS_BAD_ID );
-- }
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/filexfer.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/filexfer.h
---- pidgin-2.10.7/libpurple/protocols/mxit/filexfer.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/filexfer.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,50 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- file transfers (sending and receiving) --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MXIT_FILEXFER_H_
--#define _MXIT_FILEXFER_H_
--
--
--/*
-- * a MXit file transfer
-- */
--struct mxitxfer {
-- struct MXitSession* session;
-- char fileid[MXIT_CHUNK_FILEID_LEN];
--};
--
--const char* file_mime_type( const char* filename, const char* buf, int buflen );
--
--/* libPurple callbacks */
--gboolean mxit_xfer_enabled( PurpleConnection* gc, const char* who );
--void mxit_xfer_tx( PurpleConnection* gc, const char* who, const char* filename );
--PurpleXfer* mxit_xfer_new( PurpleConnection* gc, const char* who );
--
--/* MXit Protocol callbacks */
--void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, int filesize, const char* fileid );
--void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, int datalen );
--
--
--#endif /* _MXIT_FILEXFER_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/formcmds.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/formcmds.c
---- pidgin-2.10.7/libpurple/protocols/mxit/formcmds.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/formcmds.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,624 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- MXit Forms & Commands --
-- *
-- * Andrew Victor <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--
--#include "internal.h"
--#include <glib.h>
--
--#include "purple.h"
--
--#include "protocol.h"
--#include "mxit.h"
--#include "markup.h"
--#include "formcmds.h"
--
--#undef MXIT_DEBUG_COMMANDS
--
--/*
-- * the MXit Command identifiers
-- */
--typedef enum
--{
-- MXIT_CMD_UNKNOWN = 0, /* Unknown command */
-- MXIT_CMD_CLEAR, /* Clear (clear) */
-- MXIT_CMD_SENDSMS, /* Send SMS (sendsms) */
-- MXIT_CMD_REPLY, /* Reply (reply) */
-- MXIT_CMD_PLATREQ, /* Platform Request (platreq) */
-- MXIT_CMD_SELECTCONTACT, /* Select Contact (selc) */
-- MXIT_CMD_IMAGE, /* Inline image (img) */
-- MXIT_CMD_SCREENCONFIG, /* Chat-screen config (csc) */
-- MXIT_CMD_SCREENINFO, /* Chat-screen info (csi) */
-- MXIT_CMD_IMAGESTRIP, /* Image Strip (is) */
-- MXIT_CMD_TABLE /* Table (tbl) */
--} MXitCommandType;
--
--/* Chat-screen behaviours (bhvr) */
--#define SCREEN_NO_HEADINGS 0x01
--#define SCREEN_FULLSCREEN 0x02
--#define SCREEN_AUTOCLEAR 0x04
--#define SCREEN_NO_AUDIO 0x08
--#define SCREEN_NO_MSGPREFIX 0x10
--#define SCREEN_NOTIFY 0x20
--#define SCREEN_PROGRESSBAR 0x40
--
--
--/*
-- * object for an inline image request with an URL
-- */
--struct ii_url_request
--{
-- struct RXMsgData* mx;
-- char* url;
--};
--
--
--/*------------------------------------------------------------------------
-- * Callback function invoked when an inline image request to a web site completes.
-- *
-- * @param url_data
-- * @param user_data The Markup message object
-- * @param url_text The data returned from the WAP site
-- * @param len The length of the data returned
-- * @param error_message Descriptive error message
-- */
--static void mxit_cb_ii_returned(PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message)
--{
-- struct ii_url_request* iireq = (struct ii_url_request*) user_data;
-- int* intptr = NULL;
-- int id;
--
--#ifdef MXIT_DEBUG_COMMANDS
-- purple_debug_info(MXIT_PLUGIN_ID, "Inline Image returned from %s\n", iireq->url);
--#endif
--
-- if (!url_text) {
-- /* no reply from the WAP site */
-- purple_debug_error(MXIT_PLUGIN_ID, "Error downloading Inline Image from %s.\n", iireq->url);
-- goto done;
-- }
--
-- /* lets first see if we don't have the inline image already in cache */
-- if (g_hash_table_lookup(iireq->mx->session->iimages, iireq->url)) {
-- /* inline image found in the cache, so we just ignore this reply */
-- goto done;
-- }
--
-- /* we now have the inline image, store a copy in the imagestore */
-- id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL);
--
-- /* map the inline image id to purple image id */
-- intptr = g_malloc(sizeof(int));
-- *intptr = id;
-- g_hash_table_insert(iireq->mx->session->iimages, iireq->url, intptr);
--
-- iireq->mx->flags |= PURPLE_MESSAGE_IMAGES;
--
--done:
-- iireq->mx->img_count--;
-- if ((iireq->mx->img_count == 0) && (iireq->mx->converted)) {
-- /*
-- * this was the last outstanding emoticon for this message,
-- * so we can now display it to the user.
-- */
-- mxit_show_message(iireq->mx);
-- }
--
-- g_free(iireq);
--}
--
--
--/*------------------------------------------------------------------------
-- * Return the command identifier of this MXit Command.
-- *
-- * @param cmd The MXit command <key,value> map
-- * @return The MXit command identifier
-- */
--static MXitCommandType command_type(GHashTable* hash)
--{
-- char* op;
-- char* type;
--
-- op = g_hash_table_lookup(hash, "op");
-- if (op) {
-- if ( strcmp(op, "cmd") == 0 ) {
-- type = g_hash_table_lookup(hash, "type");
-- if (type == NULL) /* no command provided */
-- return MXIT_CMD_UNKNOWN;
-- else if (strcmp(type, "clear") == 0) /* clear */
-- return MXIT_CMD_CLEAR;
-- else if (strcmp(type, "sendsms") == 0) /* send an SMS */
-- return MXIT_CMD_SENDSMS;
-- else if (strcmp(type, "reply") == 0) /* list of options */
-- return MXIT_CMD_REPLY;
-- else if (strcmp(type, "platreq") == 0) /* platform request */
-- return MXIT_CMD_PLATREQ;
-- else if (strcmp(type, "selc") == 0) /* select contact */
-- return MXIT_CMD_SELECTCONTACT;
-- }
-- else if (strcmp(op, "img") == 0) /* inline image */
-- return MXIT_CMD_IMAGE;
-- else if (strcmp(op, "csc") == 0) /* chat-screen config */
-- return MXIT_CMD_SCREENCONFIG;
-- else if (strcmp(op, "csi") == 0) /* chat-screen info */
-- return MXIT_CMD_SCREENINFO;
-- else if (strcmp(op, "is") == 0) /* image-strip */
-- return MXIT_CMD_IMAGESTRIP;
-- else if (strcmp(op, "tbl") == 0) /* table */
-- return MXIT_CMD_TABLE;
-- }
--
-- return MXIT_CMD_UNKNOWN;
--}
--
--
--/*------------------------------------------------------------------------
-- * Tokenize a MXit Command string into a <key,value> map.
-- *
-- * @param cmd The MXit command string
-- * @return The <key,value> hash-map, or NULL on error.
-- */
--static GHashTable* command_tokenize(char* cmd)
--{
-- GHashTable* hash = NULL;
-- gchar** parts;
-- int i = 0;
--
--#ifdef MXIT_DEBUG_COMMANDS
-- purple_debug_info(MXIT_PLUGIN_ID, "command: '%s'\n", cmd);
--#endif
--
-- /* explode the command into parts */
-- parts = g_strsplit(cmd, "|", 0);
--
-- hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
--
-- /* now break part into a key & value */
-- while (parts[i] != NULL) {
-- char* value;
--
-- value = strchr(parts[i], '='); /* find start of value */
-- if (value != NULL) {
-- *value = '\0';
-- value++;
-- }
--
--#ifdef MXIT_DEBUG_COMMANDS
-- purple_debug_info(MXIT_PLUGIN_ID, " key='%s' value='%s'\n", parts[i], value);
--#endif
--
-- g_hash_table_insert(hash, g_strdup(parts[i]), g_strdup(value));
--
-- i++;
-- }
--
-- g_strfreev(parts);
--
-- return hash;
--}
--
--
--/*------------------------------------------------------------------------
-- * Process a Clear MXit command.
-- * [::op=cmd|type=clear|clearmsgscreen=true|auto=true|id=12345:]
-- *
-- * @param session The MXit session object
-- * @param from The sender of the message.
-- * @param hash The MXit command <key,value> map
-- */
--static void command_clear(struct MXitSession* session, const char* from, GHashTable* hash)
--{
-- PurpleConversation *conv;
-- char* clearmsgscreen;
--
-- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, session->acc);
-- if (conv == NULL) {
-- purple_debug_error(MXIT_PLUGIN_ID, _( "Conversation with '%s' not found\n" ), from);
-- return;
-- }
--
-- clearmsgscreen = g_hash_table_lookup(hash, "clearmsgscreen");
-- if ( (clearmsgscreen) && (strcmp(clearmsgscreen, "true") == 0) ) {
-- /* this is a command to clear the chat screen */
-- purple_conversation_clear_message_history(conv);
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Process a Reply MXit command.
-- * [::op=cmd|type=reply|replymsg=back|selmsg=b) Back|displaymsg=Processing|id=12345:]
-- * [::op=cmd|nm=rep|type=reply|replymsg=back|selmsg=b) Back|displaymsg=Processing|id=12345:]
-- *
-- * @param mx The received message data object
-- * @param hash The MXit command <key,value> map
-- */
--static void command_reply(struct RXMsgData* mx, GHashTable* hash)
--{
-- char* replymsg;
-- char* selmsg;
-- char* nm;
--
-- selmsg = g_hash_table_lookup(hash, "selmsg"); /* selection message */
-- replymsg = g_hash_table_lookup(hash, "replymsg"); /* reply message */
-- nm = g_hash_table_lookup(hash, "nm"); /* name parameter */
--
-- if ((selmsg == NULL) || (replymsg == NULL))
-- return; /* these parameters are required */
--
-- if (nm) { /* indicates response must be a structured response */
-- gchar* seltext = g_markup_escape_text(purple_url_decode(selmsg), -1);
-- gchar* replycmd = g_strdup_printf("type=reply|nm=%s|res=%s|err=0", nm, replymsg);
--
-- mxit_add_html_link( mx, replycmd, TRUE, seltext );
--
-- g_free(seltext);
-- g_free(replycmd);
-- }
-- else {
-- gchar* seltext = g_markup_escape_text(purple_url_decode(selmsg), -1);
--
-- mxit_add_html_link( mx, purple_url_decode(replymsg), FALSE, seltext );
--
-- g_free(seltext);
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Process a PlatformRequest MXit command.
-- * [::op=cmd|type=platreq|selmsg=Upgrade MXit|dest=http%3a//m.mxit.com|id=12345:]
-- *
-- * @param hash The MXit command <key,value> map
-- * @param msg The message to display (as generated so far)
-- */
--static void command_platformreq(GHashTable* hash, GString* msg)
--{
-- gchar* text = NULL;
-- char* selmsg;
-- char* dest;
--
-- selmsg = g_hash_table_lookup(hash, "selmsg"); /* find the selection message */
-- if (selmsg) {
-- text = g_markup_escape_text(purple_url_decode(selmsg), -1);
-- }
--
-- dest = g_hash_table_lookup(hash, "dest"); /* find the destination */
-- if (dest) {
-- g_string_append_printf(msg, "<a href=\"%s\">%s</a>", purple_url_decode(dest), (text) ? text : _( "Download" )); /* add link to display message */
-- }
--
-- if (text)
-- g_free(text);
--}
--
--
--/*------------------------------------------------------------------------
-- * Process an inline image MXit command.
-- * [::op=img|dat=ASDF23408asdflkj2309flkjsadf%3d%3d|algn=1|w=120|h=12|t=100|replymsg=text:]
-- *
-- * @param mx The received message data object
-- * @param hash The MXit command <key,value> map
-- * @param msg The message to display (as generated so far)
-- */
--static void command_image(struct RXMsgData* mx, GHashTable* hash, GString* msg)
--{
-- const char* img;
-- const char* reply;
-- guchar* rawimg;
-- char link[256];
-- gsize rawimglen;
-- int imgid;
--
-- img = g_hash_table_lookup(hash, "dat");
-- if (img) {
-- rawimg = purple_base64_decode(img, &rawimglen);
-- //purple_util_write_data_to_file_absolute("/tmp/mxitinline.png", (char*) rawimg, rawimglen);
-- imgid = purple_imgstore_add_with_id(rawimg, rawimglen, NULL);
-- g_snprintf(link, sizeof(link), "<img id=\"%i\">", imgid);
-- g_string_append_printf(msg, "%s", link);
-- mx->flags |= PURPLE_MESSAGE_IMAGES;
-- }
-- else {
-- img = g_hash_table_lookup(hash, "src");
-- if (img) {
-- struct ii_url_request* iireq;
--
-- iireq = g_new0(struct ii_url_request,1);
-- iireq->url = g_strdup(purple_url_decode(img));
-- iireq->mx = mx;
--
-- g_string_append_printf(msg, "%s%s>", MXIT_II_TAG, iireq->url);
-- mx->got_img = TRUE;
--
-- /* lets first see if we don't have the inline image already in cache */
-- if (g_hash_table_lookup(mx->session->iimages, iireq->url)) {
-- /* inline image found in the cache, so we do not have to request it from the web */
-- g_free(iireq);
-- }
-- else {
-- /* send the request for the inline image */
-- purple_debug_info(MXIT_PLUGIN_ID, "sending request for inline image '%s'\n", iireq->url);
--
-- /* request the image (reference: "libpurple/util.h") */
-- purple_util_fetch_url_request(iireq->url, TRUE, NULL, TRUE, NULL, FALSE, mxit_cb_ii_returned, iireq);
-- mx->img_count++;
-- }
-- }
-- }
--
-- /* if this is a clickable image, show a click link */
-- reply = g_hash_table_lookup(hash, "replymsg");
-- if (reply) {
-- g_string_append_printf(msg, "\n");
-- mxit_add_html_link(mx, purple_url_decode(reply), FALSE, _( "click here" ));
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Process an Imagestrip MXit command.
-- * [::op=is|nm=status|dat=iVBORw0KGgoAAAA%3d%3d|v=63398792426788|fw=8|fh=8|layer=0:]
-- *
-- * @param from The sender of the message.
-- * @param hash The MXit command <key,value> map
-- */
--static void command_imagestrip(struct MXitSession* session, const char* from, GHashTable* hash)
--{
-- const char* name;
-- const char* validator;
-- const char* tmp;
-- int width, height, layer;
--
-- purple_debug_info(MXIT_PLUGIN_ID, "ImageStrip received from %s\n", from);
--
-- /* image strip name */
-- name = g_hash_table_lookup(hash, "nm");
--
-- /* validator */
-- validator = g_hash_table_lookup(hash, "v");
--
-- /* image data */
-- tmp = g_hash_table_lookup(hash, "dat");
-- if (tmp) {
-- guchar* rawimg;
-- gsize rawimglen;
-- char* dir;
-- char* escfrom;
-- char* escname;
-- char* escvalidator;
-- char* filename;
--
-- /* base64 decode the image data */
-- rawimg = purple_base64_decode(tmp, &rawimglen);
--
-- /* save it to a file */
-- dir = g_build_filename(purple_user_dir(), "mxit", "imagestrips", NULL);
-- purple_build_dir(dir, S_IRUSR | S_IWUSR | S_IXUSR); /* ensure directory exists */
--
-- escfrom = g_strdup(purple_escape_filename(from));
-- escname = g_strdup(purple_escape_filename(name));
-- escvalidator = g_strdup(purple_escape_filename(validator));
-- filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s-%s-%s.png", dir, escfrom, escname, escvalidator);
--
-- purple_util_write_data_to_file_absolute(filename, (char*) rawimg, rawimglen);
--
-- g_free(dir);
-- g_free(escfrom);
-- g_free(escname);
-- g_free(escvalidator);
-- g_free(filename);
-- }
--
-- tmp = g_hash_table_lookup(hash, "fw");
-- width = atoi(tmp);
--
-- tmp = g_hash_table_lookup(hash, "fh");
-- height = atoi(tmp);
--
-- tmp = g_hash_table_lookup(hash, "layer");
-- layer = atoi(tmp);
--
-- purple_debug_info(MXIT_PLUGIN_ID, "ImageStrip %s from %s: [w=%i h=%i l=%i validator=%s]\n", name, from, width, height, layer, validator);
--}
--
--
--/*------------------------------------------------------------------------
-- * Process a Chat-Screen-Info MXit command.
-- * [::op=csi:]
-- *
-- * @param session The MXit session object
-- * @param from The sender of the message.
-- */
--static void command_screeninfo(struct MXitSession* session, const char* from)
--{
-- char* response;
--
-- purple_debug_info(MXIT_PLUGIN_ID, "Chat Screen Info received from %s\n", from);
--
-- // TODO: Determine width, height, colors of chat-screen.
--
-- response = g_strdup_printf("::type=csi|res=bhvr,0;w,%i;h,%i;col,0.ffffffff,29.ff000000:", 300, 400);
--
-- /* send response back to MXit */
-- mxit_send_message( session, from, response, FALSE, TRUE );
--
-- g_free(response);
--}
--
--
--/*------------------------------------------------------------------------
-- * Process a Chat-Screen-Configure MXit command.
-- * [::op=csc|bhvr=|menu=<menu>|col=<colors>:]
-- * where:
-- * menu ::= <menuitem> { ";" <menuitem> }
-- * menuitem ::= { type "," <text> "," <name> "," <meta> }
-- * colors ::= <color> { ";" <color> }
-- * color ::= <colorid> "," <ARGB hex color>
-- *
-- * @param session The MXit session object
-- * @param from The sender of the message.
-- * @param hash The MXit command <key,value> map
-- */
--static void command_screenconfig(struct MXitSession* session, const char* from, GHashTable* hash)
--{
-- const char* tmp;
--
-- purple_debug_info(MXIT_PLUGIN_ID, "Chat Screen Configure received from %s\n", from);
--
-- /* Behaviour */
-- tmp = g_hash_table_lookup(hash, "bhvr");
-- if (tmp) {
-- purple_debug_info(MXIT_PLUGIN_ID, " behaviour = %s\n", tmp);
-- // TODO: Re-configure conversation screen.
-- }
--
-- /* Menu */
-- tmp = g_hash_table_lookup(hash, "menu");
-- if (tmp) {
-- purple_debug_info(MXIT_PLUGIN_ID, " menu = %s\n", tmp);
-- // TODO: Implement conversation-specific sub-menu.
-- }
--
-- /* Colours */
-- tmp = g_hash_table_lookup(hash, "col");
-- if (tmp) {
-- purple_debug_info(MXIT_PLUGIN_ID, " colours = %s\n", tmp);
-- // TODO: Re-configuration conversation colors.
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Process a Table Markup MXit command.
-- *
-- * @param mx The received message data object
-- * @param hash The MXit command <key,value> map
-- */
--static void command_table(struct RXMsgData* mx, GHashTable* hash)
--{
-- const char* tmp;
-- const char* name;
-- int mode;
-- int nr_columns = 0, nr_rows = 0;
-- gchar** coldata;
-- int i, j;
--
-- /* table name */
-- name = g_hash_table_lookup(hash, "nm");
--
-- /* number of columns */
-- tmp = g_hash_table_lookup(hash, "col");
-- nr_columns = atoi(tmp);
--
-- /* number of rows */
-- tmp = g_hash_table_lookup(hash, "row");
-- nr_rows = atoi(tmp);
--
-- /* mode */
-- tmp = g_hash_table_lookup(hash, "mode");
-- mode = atoi(tmp);
--
-- /* table data */
-- tmp = g_hash_table_lookup(hash, "d");
-- coldata = g_strsplit(tmp, "~", 0); /* split into entries for each row & column */
--
-- purple_debug_info(MXIT_PLUGIN_ID, "Table %s from %s: [cols=%i rows=%i mode=%i]\n", name, mx->from, nr_columns, nr_rows, mode);
--
-- for (i = 0; i < nr_rows; i++) {
-- for (j = 0; j < nr_columns; j++) {
-- purple_debug_info(MXIT_PLUGIN_ID, " Row %i Column %i = %s\n", i, j, coldata[i*nr_columns + j]);
-- }
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Process a received MXit Command message.
-- *
-- * @param mx The received message data object
-- * @param message The message text
-- * @return The length of the command
-- */
--int mxit_parse_command(struct RXMsgData* mx, char* message)
--{
-- GHashTable* hash = NULL;
-- char* start;
-- char* end;
--
-- /* ensure that this is really a command */
-- if ( ( message[0] != ':' ) || ( message[1] != ':' ) ) {
-- /* this is not a command */
-- return 0;
-- }
--
-- start = message + 2;
-- end = strstr(start, ":");
-- if (end) {
-- /* end of a command found */
-- *end = '\0'; /* terminate command string */
--
-- hash = command_tokenize(start); /* break into <key,value> pairs */
-- if (hash) {
-- MXitCommandType type = command_type(hash);
--
-- switch (type) {
-- case MXIT_CMD_CLEAR :
-- command_clear(mx->session, mx->from, hash);
-- break;
-- case MXIT_CMD_REPLY :
-- command_reply(mx, hash);
-- break;
-- case MXIT_CMD_PLATREQ :
-- command_platformreq(hash, mx->msg);
-- break;
-- case MXIT_CMD_IMAGE :
-- command_image(mx, hash, mx->msg);
-- break;
-- case MXIT_CMD_SCREENCONFIG :
-- command_screenconfig(mx->session, mx->from, hash);
-- break;
-- case MXIT_CMD_SCREENINFO :
-- command_screeninfo(mx->session, mx->from);
-- break;
-- case MXIT_CMD_IMAGESTRIP :
-- command_imagestrip(mx->session, mx->from, hash);
-- break;
-- case MXIT_CMD_TABLE :
-- command_table(mx, hash);
-- break;
-- default :
-- /* command unknown, or not currently supported */
-- break;
-- }
-- g_hash_table_destroy(hash);
-- }
-- *end = ':';
--
-- return end - message;
-- }
-- else {
-- return 0;
-- }
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/formcmds.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/formcmds.h
---- pidgin-2.10.7/libpurple/protocols/mxit/formcmds.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/formcmds.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,35 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- MXit Forms & Commands --
-- *
-- * Andrew Victor <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MXIT_FORMCMDS_H_
--#define _MXIT_FORMCMDS_H_
--
--#include "mxit.h"
--
--
--int mxit_parse_command(struct RXMsgData* mx, char* message);
--
--
--#endif /* _MXIT_FORMCMDS_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/http.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/http.c
---- pidgin-2.10.7/libpurple/protocols/mxit/http.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/http.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,332 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- MXit client protocol implementation --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "purple.h"
--
--#include "mxit.h"
--#include "protocol.h"
--#include "http.h"
--
--
--/* HTTP constants */
--#define HTTP_11_200_OK "HTTP/1.1 200 OK\r\n"
--#define HTTP_11_100_CONT "HTTP/1.1 100 Continue\r\n"
--#define HTTP_11_SEPERATOR "\r\n\r\n"
--#define HTTP_CONTENT_LEN "Content-Length: "
--
--
--/* define to enable HTTP debugging */
--#define DEBUG_HTTP
--
--
--/*------------------------------------------------------------------------
-- * This will freeup the memory used by a HTTP request structure
-- *
-- * @param req The HTTP structure's resources should be freed up
-- */
--static void free_http_request( struct http_request* req )
--{
-- g_free( req->host );
-- g_free( req->data );
-- g_free( req );
--}
--
--
--/*------------------------------------------------------------------------
-- * Write the request to the HTTP server.
-- *
-- * @param fd The file descriptor
-- * @param pktdata The packet data
-- * @param pktlen The length of the packet data
-- * @return Return -1 on error, otherwise 0
-- */
--static int mxit_http_raw_write( int fd, const char* pktdata, int pktlen )
--{
-- int written;
-- int res;
--
-- written = 0;
-- while ( written < pktlen ) {
-- res = write( fd, &pktdata[written], pktlen - written );
-- if ( res <= 0 ) {
-- /* error on socket */
-- if ( errno == EAGAIN )
-- continue;
--
-- purple_debug_error( MXIT_PLUGIN_ID, "Error while writing packet to HTTP server (%i)\n", res );
-- return -1;
-- }
-- written += res;
-- }
--
-- return 0;
--}
--
--
--/*------------------------------------------------------------------------
-- * Callback when data is received from the HTTP server.
-- *
-- * @param user_data The MXit session object
-- * @param source The file-descriptor on which data was received
-- * @param cond Condition which caused the callback (PURPLE_INPUT_READ)
-- */
--static void mxit_cb_http_read( gpointer user_data, gint source, PurpleInputCondition cond )
--{
-- struct MXitSession* session = (struct MXitSession*) user_data;
-- char buf[256];
-- int buflen;
-- char* body;
-- int bodylen;
-- char* ch;
-- int len;
-- char* tmp;
-- int res;
-- char* next;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_http_read\n" );
--
-- if ( session->rx_state == RX_STATE_RLEN ) {
-- /* we are reading in the HTTP headers */
--
-- /* copy partial headers if we have any part saved */
-- memcpy( buf, session->rx_dbuf, session->rx_i );
-- buflen = session->rx_i;
--
-- /* read bytes from the socket */
-- len = read( session->fd, buf + buflen, sizeof( buf ) - ( buflen + 1 ) );
-- if ( len <= 0 ) {
-- /* connection has been terminated, or error occurred */
-- goto done;
-- }
-- buf[buflen+len] = '\0';
--
--//nextpacket:
--
--#ifdef DEBUG_HTTP
-- purple_debug_info( MXIT_PLUGIN_ID, "HTTP POST READ 1: (%i)\n", len );
-- dump_bytes( session, buf + buflen, len );
--#endif
--
-- /* see if we have all the HTTP headers yet */
-- ch = strstr( buf, HTTP_11_SEPERATOR );
-- if ( !ch ) {
-- /* we need to wait for more input, so save what we have */
-- session->rx_i = buflen + len;
-- memcpy( session->rx_dbuf, buf, session->rx_i );
-- return;
-- }
-- buflen += len;
--
-- /* we have the header's end now skip over the http separator to get the body offset */
-- ch += strlen( HTTP_11_SEPERATOR );
-- *(ch - 1) = '\0';
-- body = ch;
--
-- res = buflen - ( ch - buf );
-- if ( res > 0 ) {
-- /* we read more bytes than just the header so copy it over */
-- memcpy( session->rx_dbuf, ch, res );
-- session->rx_i = res;
-- }
-- else {
-- session->rx_i = 0;
-- }
--
-- /* test for a good response */
-- if ( ( strncmp( buf, HTTP_11_200_OK, strlen( HTTP_11_200_OK ) ) != 0 ) && ( strncmp( buf, HTTP_11_100_CONT, strlen( HTTP_11_100_CONT ) ) != 0 ) ) {
-- /* bad result */
-- purple_debug_error( MXIT_PLUGIN_ID, "HTTP error: %s\n", ch );
-- goto done;
-- }
--
-- /* find the content-length */
-- ch = (char*) purple_strcasestr( buf, HTTP_CONTENT_LEN );
-- if ( !ch ) {
-- /* bad request. it does not contain a content-length header */
-- purple_debug_error( MXIT_PLUGIN_ID, "HTTP reply received without content-length header (ignoring packet)\n" );
-- goto done;
-- }
--
-- /* parse the content-length */
-- ch += strlen( HTTP_CONTENT_LEN );
-- tmp = strchr( ch, '\r' );
-- if ( !tmp ) {
-- purple_debug_error( MXIT_PLUGIN_ID, "Received bad HTTP reply packet (ignoring packet)\n" );
-- goto done;
-- }
-- tmp = g_strndup( ch, tmp - ch );
-- bodylen = atoi( tmp );
-- g_free( tmp );
-- tmp = NULL;
--
-- if ( buflen + bodylen >= CP_MAX_PACKET ) {
-- /* this packet is way to big */
-- goto done;
-- }
-- else if ( buflen > ( ( body - buf ) + bodylen ) ) {
-- /* we have a second packet here */
-- next = body + bodylen;
-- session->rx_res = 0;
-- }
-- else {
-- session->rx_res = bodylen - session->rx_i;
-- }
--
-- if ( session->rx_res == 0 ) {
-- /* we have read all the data */
-- session->rx_i = bodylen;
-- session->rx_state = RX_STATE_PROC;
-- }
-- else {
-- /* there is still some data outstanding */
-- session->rx_state = RX_STATE_DATA;
-- }
-- }
-- else if ( session->rx_state == RX_STATE_DATA ) {
-- /* we are reading the HTTP content (body) */
--
-- /* read bytes from the socket */
-- len = read( session->fd, &session->rx_dbuf[session->rx_i], session->rx_res );
-- if ( len <= 0 ) {
-- /* connection has been terminated, or error occurred */
-- goto done;
-- }
--
--#ifdef DEBUG_HTTP
-- purple_debug_info( MXIT_PLUGIN_ID, "HTTP POST READ 2: (%i)\n", len );
-- dump_bytes( session, &session->rx_dbuf[session->rx_i], len );
--#endif
-- session->rx_i += len;
-- session->rx_res -= len;
--
-- if ( session->rx_res == 0 ) {
-- /* ok, so now we have read in the whole packet */
-- session->rx_state = RX_STATE_PROC;
-- }
-- }
--
-- if ( session->rx_state == RX_STATE_PROC ) {
-- mxit_parse_packet( session );
--
--#if 0
-- if ( next ) {
-- /* there is another packet of which we read some data */
--
-- /* reset input */
-- session->rx_state = RX_STATE_RLEN;
-- session->rx_lbuf[0] = '\0';
-- session->rx_i = 0;
-- session->rx_res = 0;
--
-- /* move read data */
-- len = next - buf;
-- buflen = len;
-- memcpy( buf, next, len );
-- goto nextpacket;
-- }
--#endif
--
-- /* we are done */
-- goto done;
-- }
--
-- return;
--done:
-- close( session->fd );
-- purple_input_remove( session->http_handler );
-- session->http_handler = 0;
--}
--
--
--/*------------------------------------------------------------------------
-- * Callback invoked once the connection has been established to the HTTP server,
-- * or on connection failure.
-- *
-- * @param user_data The MXit session object
-- * @param source The file-descriptor associated with the connection
-- * @param error_message Message explaining why the connection failed
-- */
--static void mxit_cb_http_connect( gpointer user_data, gint source, const gchar* error_message )
--{
-- struct http_request* req = (struct http_request*) user_data;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_http_connect\n" );
--
-- /* source is the file descriptor of the new connection */
-- if ( source < 0 ) {
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_http_connect failed: %s\n", error_message );
-- purple_connection_error( req->session->con, _( "Unable to connect to the MXit HTTP server. Please check your server settings." ) );
-- return;
-- }
--
-- /* we now have an open and active TCP connection to the mxit server */
-- req->session->fd = source;
--
-- /* reset the receive buffer */
-- req->session->rx_state = RX_STATE_RLEN;
-- req->session->rx_lbuf[0] = '\0';
-- req->session->rx_i = 0;
-- req->session->rx_res = 0;
--
-- /* start listening on the open connection for messages from the server (reference: "libpurple/eventloop.h") */
-- req->session->http_handler = purple_input_add( req->session->fd, PURPLE_INPUT_READ, mxit_cb_http_read, req->session );
--
-- /* actually send the request to the HTTP server */
-- mxit_http_raw_write( req->session->fd, req->data, req->datalen );
--
-- /* free up resources */
-- free_http_request( req );
-- req = NULL;
--}
--
--
--/*------------------------------------------------------------------------
-- * Create HTTP connection for sending a HTTP request
-- *
-- * @param session The MXit session object
-- * @param host The server name to connect to
-- * @param port The port number to connect to
-- * @param data The HTTP request data (including HTTP headers etc.)
-- * @param datalen The HTTP request data length
-- */
--void mxit_http_send_request( struct MXitSession* session, char* host, int port, const char* data, int datalen )
--{
-- PurpleProxyConnectData* con = NULL;
-- struct http_request* req;
--
-- /* build the http request */
-- req = g_new0( struct http_request, 1 );
-- req->session = session;
-- req->host = host;
-- req->port = port;
-- req->data = g_malloc0( datalen );
-- memcpy( req->data, data, datalen );
-- req->datalen = datalen;
--
-- /* open connection to the HTTP server */
-- con = purple_proxy_connect( NULL, session->acc, host, port, mxit_cb_http_connect, req );
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/http.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/http.h
---- pidgin-2.10.7/libpurple/protocols/mxit/http.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/http.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,47 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- MXit client protocol implementation --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--
--#ifndef _MXIT_HTTP_H_
--#define _MXIT_HTTP_H_
--
--
--
--struct http_request
--{
-- struct MXitSession* session;
-- char* host;
-- int port;
-- char* data;
-- int datalen;
--};
--
--
--void mxit_http_send_request( struct MXitSession* session, char* host, int port, const char* data, int datalen );
--
--
--
--#endif /* _MXIT_HTTP_H_ */
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/login.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/login.c
---- pidgin-2.10.7/libpurple/protocols/mxit/login.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/login.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,798 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- MXit user login functionality --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "purple.h"
--
--#include "protocol.h"
--#include "mxit.h"
--#include "cipher.h"
--#include "login.h"
--#include "profile.h"
--
--/* requesting captcha size */
--#define MXIT_CAPTCHA_HEIGHT 50
--#define MXIT_CAPTCHA_WIDTH 150
--
--
--/* prototypes */
--static void mxit_register_view( struct MXitSession* session );
--static void get_clientinfo( struct MXitSession* session );
--
--
--/*------------------------------------------------------------------------
-- * Create a new mxit session object
-- *
-- * @return The MXit session object
-- */
--static struct MXitSession* mxit_create_object( PurpleAccount* account )
--{
-- struct MXitSession* session = NULL;
-- PurpleConnection* con = NULL;
--
-- /* currently the wapsite does not handle a '+' in front of the username (mxitid) so we just strip it */
-- if ( account->username[0] == '+' ) {
-- char* fixed;
--
-- /* cut off the '+' */
-- fixed = g_strdup( &account->username[1] );
-- purple_account_set_username( account, fixed );
-- g_free( fixed );
-- }
--
-- session = g_new0( struct MXitSession, 1 );
--
-- /* configure the connection (reference: "libpurple/connection.h") */
-- con = purple_account_get_connection( account );
-- con->proto_data = session;
-- con->flags |= PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_SUPPORT_MOODS;
-- session->con = con;
--
-- /* add account */
-- session->acc = account;
--
-- /* configure the session (reference: "libpurple/account.h") */
-- g_strlcpy( session->server, purple_account_get_string( account, MXIT_CONFIG_SERVER_ADDR, DEFAULT_SERVER ), sizeof( session->server ) );
-- g_strlcpy( session->http_server, purple_account_get_string( account, MXIT_CONFIG_HTTPSERVER, DEFAULT_HTTP_SERVER ), sizeof( session->http_server ) );
-- session->port = purple_account_get_int( account, MXIT_CONFIG_SERVER_PORT, DEFAULT_PORT );
-- g_strlcpy( session->distcode, purple_account_get_string( account, MXIT_CONFIG_DISTCODE, "" ), sizeof( session->distcode ) );
-- g_strlcpy( session->clientkey, purple_account_get_string( account, MXIT_CONFIG_CLIENTKEY, "" ), sizeof( session->clientkey ) );
-- g_strlcpy( session->dialcode, purple_account_get_string( account, MXIT_CONFIG_DIALCODE, "" ), sizeof( session->dialcode ) );
-- session->http = purple_account_get_bool( account, MXIT_CONFIG_USE_HTTP, FALSE );
-- session->iimages = g_hash_table_new( g_str_hash, g_str_equal );
-- session->rx_state = RX_STATE_RLEN;
-- session->http_interval = MXIT_HTTP_POLL_MIN;
-- session->http_last_poll = mxit_now_milli();
--
-- return session;
--}
--
--
--/*------------------------------------------------------------------------
-- * We now have a connection established with MXit, so we can start the
-- * login procedure
-- *
-- * @param session The MXit session object
-- */
--static void mxit_connected( struct MXitSession* session )
--{
-- int state;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_connected\n" );
--
-- session->flags |= MXIT_FLAG_CONNECTED;
-- purple_connection_update_progress( session->con, _( "Logging In..." ), 2, 4 );
--
-- /* create a timer to send a ping packet if the connection is idle */
-- session->last_tx = mxit_now_milli();
--
-- /* encrypt the user password */
-- session->encpwd = mxit_encrypt_password( session );
--
-- state = purple_account_get_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
-- if ( state == MXIT_STATE_LOGIN ) {
-- /* create and send login packet */
-- mxit_send_login( session );
-- }
-- else {
-- if ( !session->profile ) {
-- /* we have lost the session profile, so ask the user to enter it again */
-- mxit_register_view( session );
-- }
-- else {
-- /* create and send the register packet */
-- mxit_send_register( session );
-- }
-- }
--
-- /* enable signals */
-- mxit_enable_signals( session );
--
--#ifdef MXIT_LINK_CLICK
-- /* register for uri click notification */
-- mxit_register_uri_handler();
--#endif
--
-- /* start the polling if this is a HTTP connection */
-- if ( session->http ) {
-- session->http_timer_id = purple_timeout_add_seconds( 2, mxit_manage_polling, session );
-- }
--
-- /* This timer might already exist if we're registering a new account */
-- if ( session->q_slow_timer_id == 0 ) {
-- /* start the tx queue manager timer */
-- session->q_slow_timer_id = purple_timeout_add_seconds( 2, mxit_manage_queue_slow, session );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Callback invoked once the connection has been established to the MXit server,
-- * or on connection failure.
-- *
-- * @param user_data The MXit session object
-- * @param source The file-descriptor associated with the connection
-- * @param error_message Message explaining why the connection failed
-- */
--static void mxit_cb_connect( gpointer user_data, gint source, const gchar* error_message )
--{
-- struct MXitSession* session = (struct MXitSession*) user_data;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_connect\n" );
--
-- /* source is the file descriptor of the new connection */
-- if ( source < 0 ) {
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_connect failed: %s\n", error_message );
-- purple_connection_error( session->con, _( "Unable to connect to the MXit server. Please check your server settings." ) );
-- return;
-- }
--
-- /* we now have an open and active TCP connection to the mxit server */
-- session->fd = source;
--
-- /* start listening on the open connection for messages from the server (reference: "libpurple/eventloop.h") */
-- session->con->inpa = purple_input_add( session->fd, PURPLE_INPUT_READ, mxit_cb_rx, session );
--
-- mxit_connected( session );
--}
--
--
--/*------------------------------------------------------------------------
-- * Attempt to establish a connection to the MXit server.
-- *
-- * @param session The MXit session object
-- */
--static void mxit_login_connect( struct MXitSession* session )
--{
-- PurpleProxyConnectData* data = NULL;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_login_connect\n" );
--
-- purple_connection_update_progress( session->con, _( "Connecting..." ), 1, 4 );
--
-- /*
-- * at this stage we have all the user's information we require
-- * for logging into MXit. we will now create a new connection to
-- * a MXit server.
-- */
--
-- if ( !session->http ) {
-- /* socket connection */
-- data = purple_proxy_connect( session->con, session->acc, session->server, session->port, mxit_cb_connect, session );
-- if ( !data ) {
-- purple_connection_error( session->con, _( "Unable to connect to the MXit server. Please check your server settings." ) );
-- return;
-- }
-- }
-- else {
-- /* http connection */
-- mxit_connected( session );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Register a new account with MXit
-- *
-- * @param gc The connection object
-- * @param fields This is the fields filled-in by the user
-- */
--static void mxit_cb_register_ok( PurpleConnection *gc, PurpleRequestFields *fields )
--{
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
-- struct MXitProfile* profile = session->profile;
-- const char* str;
-- const char* pin;
-- const char* err = NULL;
-- int len;
-- int i;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_register_ok\n" );
--
-- if ( !PURPLE_CONNECTION_IS_VALID( gc ) ) {
-- purple_debug_error( MXIT_PLUGIN_ID, "Unable to register; account offline.\n" );
-- return;
-- }
--
-- /* nickname */
-- str = purple_request_fields_get_string( fields, "nickname" );
-- if ( ( !str ) || ( strlen( str ) < 3 ) ) {
-- err = _( "The Display Name you entered is too short." );
-- goto out;
-- }
-- g_strlcpy( profile->nickname, str, sizeof( profile->nickname ) );
--
-- /* birthdate */
-- str = purple_request_fields_get_string( fields, "bday" );
-- if ( ( !str ) || ( strlen( str ) < 10 ) || ( !validateDate( str ) ) ) {
-- err = _( "The birthday you entered is invalid. The correct format is: 'YYYY-MM-DD'." );
-- goto out;
-- }
-- g_strlcpy( profile->birthday, str, sizeof( profile->birthday ) );
--
-- /* gender */
-- profile->male = ( purple_request_fields_get_choice( fields, "male" ) != 0 );
--
-- /* pin */
-- pin = purple_request_fields_get_string( fields, "pin" );
-- if ( !pin ) {
-- err = _( "The PIN you entered is invalid." );
-- goto out;
-- }
-- len = strlen( pin );
-- if ( ( len < 7 ) || ( len > 10 ) ) {
-- err = _( "The PIN you entered has an invalid length [7-10]." );
-- goto out;
-- }
-- for ( i = 0; i < len; i++ ) {
-- if ( !g_ascii_isdigit( pin[i] ) ) {
-- err = _( "The PIN is invalid. It should only consist of digits [0-9]." );
-- goto out;
-- }
-- }
-- str = purple_request_fields_get_string( fields, "pin2" );
-- if ( ( !str ) || ( strcmp( pin, str ) != 0 ) ) {
-- err = _( "The two PINs you entered do not match." );
-- goto out;
-- }
-- g_strlcpy( profile->pin, pin, sizeof( profile->pin ) );
--
--out:
-- if ( !err ) {
-- purple_account_set_password( session->acc, session->profile->pin );
-- mxit_login_connect( session );
-- }
-- else {
-- /* show error to user */
-- mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Registration Error" ), err );
-- mxit_register_view( session );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Register a new account with MXit
-- *
-- * @param gc The connection object
-- * @param fields This is the fields filled-in by the user
-- */
--static void mxit_cb_register_cancel( PurpleConnection *gc, PurpleRequestFields *fields )
--{
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_register_cancel\n" );
--
-- /* disconnect */
-- purple_account_disconnect( gc->account );
--}
--
--
--/*------------------------------------------------------------------------
-- * Show a window to the user so that he can enter his information
-- *
-- * @param session The MXit session object
-- */
--static void mxit_register_view( struct MXitSession* session )
--{
-- struct MXitProfile* profile;
-- PurpleRequestFields* fields;
-- PurpleRequestFieldGroup* group;
-- PurpleRequestField* field;
--
-- if ( !session->profile ) {
-- /* we need to create a profile object here */
-- session->profile = g_new0( struct MXitProfile, 1 );
-- }
-- profile = session->profile;
--
-- fields = purple_request_fields_new();
-- group = purple_request_field_group_new( NULL );
-- purple_request_fields_add_group( fields, group );
--
-- /* mxit login name */
-- field = purple_request_field_string_new( "loginname", _( "MXit ID" ), purple_account_get_username( session->acc ), FALSE );
-- purple_request_field_string_set_editable( field, FALSE );
-- purple_request_field_group_add_field( group, field );
--
-- /* nick name (required) */
-- field = purple_request_field_string_new( "nickname", _( "Display Name" ), profile->nickname, FALSE );
-- purple_request_field_set_required( field, TRUE );
-- purple_request_field_group_add_field( group, field );
--
-- /* birthday (required) */
-- field = purple_request_field_string_new( "bday", _( "Birthday" ), profile->birthday, FALSE );
-- purple_request_field_string_set_default_value( field, "YYYY-MM-DD" );
-- purple_request_field_set_required( field, TRUE );
-- purple_request_field_group_add_field( group, field );
--
-- /* gender */
-- field = purple_request_field_choice_new( "male", _( "Gender" ), ( profile->male ) ? 1 : 0 );
-- purple_request_field_choice_add( field, _( "Female" ) ); /* 0 */
-- purple_request_field_choice_add( field, _( "Male" ) ); /* 1 */
-- purple_request_field_group_add_field( group, field );
--
-- /* pin (required) */
-- field = purple_request_field_string_new( "pin", _( "PIN" ), profile->pin, FALSE );
-- purple_request_field_string_set_masked( field, TRUE );
-- purple_request_field_set_required( field, TRUE );
-- purple_request_field_group_add_field( group, field );
-- field = purple_request_field_string_new( "pin2", _( "Verify PIN" ), "", FALSE );
-- purple_request_field_string_set_masked( field, TRUE );
-- purple_request_field_set_required( field, TRUE );
-- purple_request_field_group_add_field( group, field );
--
-- /* show the form to the user to complete */
-- purple_request_fields( session->con, _( "Register New MXit Account" ), _( "Register New MXit Account" ), _( "Please fill in the following fields:" ), fields, _( "OK" ), G_CALLBACK( mxit_cb_register_ok ), _( "Cancel" ), G_CALLBACK( mxit_cb_register_cancel ), session->acc, NULL, NULL, session->con );
--}
--
--
--/*------------------------------------------------------------------------
-- * Callback function invoked once the Authorization information has been submitted
-- * to the MXit WAP site.
-- *
-- * @param url_data libPurple internal object (see purple_util_fetch_url_request)
-- * @param user_data The MXit session object
-- * @param url_text The data returned from the WAP site
-- * @param len The length of the data returned
-- * @param error_message Descriptive error message
-- */
--static void mxit_cb_clientinfo2( PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message )
--{
-- struct MXitSession* session = (struct MXitSession*) user_data;
-- gchar** parts;
-- gchar** host;
-- int state;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_clientinfo_cb2\n" );
--
--#ifdef DEBUG_PROTOCOL
-- purple_debug_info( MXIT_PLUGIN_ID, "HTTP RESPONSE: '%s'\n", url_text );
--#endif
--
-- if ( !url_text ) {
-- /* no reply from the WAP site */
-- purple_connection_error( session->con, _( "Error contacting the MXit WAP site. Please try again later." ) );
-- return;
-- }
--
-- /* explode the response from the WAP site into an array */
-- parts = g_strsplit( url_text, ";", 15 );
--
-- if ( !parts ) {
-- /* wapserver error */
-- purple_connection_error( session->con, _( "MXit is currently unable to process the request. Please try again later." ) );
-- return;
-- }
--
-- /* check wapsite return code */
-- switch ( parts[0][0] ) {
-- case '0' :
-- /* valid reply! */
-- break;
-- case '1' :
-- purple_connection_error( session->con, _( "Wrong security code entered. Please try again later." ) );
-- return;
-- case '2' :
-- purple_connection_error( session->con, _( "Your session has expired. Please try again later." ) );
-- return;
-- case '5' :
-- purple_connection_error( session->con, _( "Invalid country selected. Please try again." ) );
-- return;
-- case '6' :
-- purple_connection_error( session->con, _( "The MXit ID you entered is not registered. Please register first." ) );
-- return;
-- case '7' :
-- purple_connection_error( session->con, _( "The MXit ID you entered is already registered. Please choose another." ) );
-- /* this user's account already exists, so we need to change the registration login flag to be login */
-- purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
-- return;
-- case '3' :
-- case '4' :
-- default :
-- purple_connection_error( session->con, _( "Internal error. Please try again later." ) );
-- return;
-- }
--
-- /* now parse and split the distribution code and the client key */
-- g_strlcpy( session->distcode, &parts[1][2], 36 + 1 );
-- g_strlcpy( session->clientkey, &parts[1][38], 8 + 1 );
--
-- /* get the dial code for the client */
-- g_strlcpy( session->dialcode, parts[4], sizeof( session->dialcode ) );
--
-- /* parse the proxy server address and port number */
-- host = g_strsplit( parts[2], ":", 4 );
-- g_strlcpy( session->server, &host[1][2], sizeof( session->server ) );
-- session->port = atoi( &host[2][0] );
--
-- /* parse the http proxy server address and port number */
-- g_strlcpy( session->http_server, parts[3], sizeof( session->http_server ) );
--
-- purple_debug_info( MXIT_PLUGIN_ID, "distcode='%s', clientkey='%s', dialcode='%s'\n", session->distcode, session->clientkey, session->dialcode );
-- purple_debug_info( MXIT_PLUGIN_ID, "sock_server='%s', http_server='%s', port='%i', cc='%s'\n", session->server, session->http_server, session->port, parts[11] );
--
-- /* save the information (reference: "libpurple/account.h") */
-- purple_account_set_string( session->acc, MXIT_CONFIG_DISTCODE, session->distcode );
-- purple_account_set_string( session->acc, MXIT_CONFIG_CLIENTKEY, session->clientkey );
-- purple_account_set_string( session->acc, MXIT_CONFIG_DIALCODE, session->dialcode );
-- purple_account_set_string( session->acc, MXIT_CONFIG_SERVER_ADDR, session->server );
-- purple_account_set_int( session->acc, MXIT_CONFIG_SERVER_PORT, session->port );
-- purple_account_set_string( session->acc, MXIT_CONFIG_HTTPSERVER, session->http_server );
--
-- /* update the state */
-- state = purple_account_get_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
-- if ( state == MXIT_STATE_REGISTER1 )
-- purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_REGISTER2 );
--
-- /* freeup the memory */
-- g_strfreev( host );
-- g_strfreev( parts );
--
-- if ( state == MXIT_STATE_LOGIN ) {
-- /* now we can continue with the login process */
-- mxit_login_connect( session );
-- }
-- else {
-- /* the user is registering so we need to get more information from him/her first to complete the process */
-- mxit_register_view( session );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Free up the data associated with the Authorization process.
-- *
-- * @param data The data object to free
-- */
--static void free_logindata( struct login_data* data )
--{
-- if ( !data )
-- return;
--
-- /* free up the login resources */
-- g_free( data->wapserver );
-- g_free( data->sessionid );
-- g_free( data->captcha );
-- g_free( data->cc );
-- g_free( data->locale );
-- g_free( data );
--}
--
--
--/*------------------------------------------------------------------------
-- * This function is called when the user accepts the Authorization form.
-- *
-- * @param gc The connection object
-- * @param fields The list of fields in the accepted form
-- */
--static void mxit_cb_captcha_ok( PurpleConnection* gc, PurpleRequestFields* fields )
--{
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
-- PurpleUtilFetchUrlData* url_data;
-- PurpleRequestField* field;
-- const char* captcha_resp;
-- GList* entries;
-- GList* entry;
-- char* url;
-- int state;
--
-- /* get the captcha response */
-- captcha_resp = purple_request_fields_get_string( fields, "code" );
-- if ( ( captcha_resp == NULL ) || ( captcha_resp[0] == '\0' ) ) {
-- /* the user did not fill in the captcha */
-- mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Error" ), _( "You did not enter the security code" ) );
-- free_logindata( session->logindata );
-- purple_account_disconnect( session->acc );
-- return;
-- }
--
-- /* get chosen country */
-- field = purple_request_fields_get_field( fields, "country" );
-- entries = purple_request_field_list_get_selected( field );
-- entry = g_list_first( entries );
-- session->logindata->cc = purple_request_field_list_get_data( field, entry->data );
-- purple_account_set_string( session->acc, MXIT_CONFIG_COUNTRYCODE, session->logindata->cc );
--
-- /* get chosen language */
-- field = purple_request_fields_get_field( fields, "locale" );
-- entries = purple_request_field_list_get_selected( field );
-- entry = g_list_first( entries );
-- session->logindata->locale = purple_request_field_list_get_data( field, entry->data );
-- purple_account_set_string( session->acc, MXIT_CONFIG_LOCALE, session->logindata->locale );
--
--#ifdef DEBUG_PROTOCOL
-- purple_debug_info( MXIT_PLUGIN_ID, "cc='%s', locale='%s', captcha='%s'\n", session->logindata->cc, session->logindata->locale, captcha_resp );
--#endif
--
-- /* get state */
-- state = purple_account_get_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
--
-- url = g_strdup_printf( "%s?type=getpid&sessionid=%s&login=%s&ver=%i.%i.%i&clientid=%s&cat=%s&chalresp=%s&cc=%s&loc=%s&path=%i&brand=%s&model=%s&h=%i&w=%i&ts=%li",
-- session->logindata->wapserver, session->logindata->sessionid, purple_url_encode( session->acc->username ), PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CLIENT_ID, MXIT_CP_ARCH,
-- captcha_resp, session->logindata->cc, session->logindata->locale, ( state == MXIT_STATE_REGISTER1 ) ? 0 : 1, MXIT_CP_PLATFORM, MXIT_CP_OS,
-- MXIT_CAPTCHA_HEIGHT, MXIT_CAPTCHA_WIDTH, time( NULL ) );
-- url_data = purple_util_fetch_url_request( url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, mxit_cb_clientinfo2, session );
--
--#ifdef DEBUG_PROTOCOL
-- purple_debug_info( MXIT_PLUGIN_ID, "HTTP REQUEST: '%s'\n", url );
--#endif
-- g_free( url );
--
-- /* free up the login resources */
-- free_logindata( session->logindata );
--}
--
--
--/*------------------------------------------------------------------------
-- * This function is called when the user cancels the Authorization form.
-- *
-- * @param gc The connection object
-- * @param fields The list of fields in the cancelled form
-- */
--static void mxit_cb_captcha_cancel( PurpleConnection* gc, PurpleRequestFields* fields )
--{
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
--
-- /* free up the login resources */
-- free_logindata( session->logindata );
--
-- /* we cannot continue, so we disconnect this account */
-- purple_account_disconnect( session->acc );
--}
--
--
--/*------------------------------------------------------------------------
-- * Callback function invoked once the client information has been retrieved from
-- * the MXit WAP site. Display page where user can select their authorization information.
-- *
-- * @param url_data libPurple internal object (see purple_util_fetch_url_request)
-- * @param user_data The MXit session object
-- * @param url_text The data returned from the WAP site
-- * @param len The length of the data returned
-- * @param error_message Descriptive error message
-- */
--static void mxit_cb_clientinfo1( PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message )
--{
-- struct MXitSession* session = (struct MXitSession*) user_data;
-- struct login_data* logindata;
-- PurpleRequestFields* fields;
-- PurpleRequestFieldGroup* group = NULL;
-- PurpleRequestField* field = NULL;
-- gchar** parts;
-- gchar** countries;
-- gchar** locales;
-- int i;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_clientinfo_cb1\n" );
--
--#ifdef DEBUG_PROTOCOL
-- purple_debug_info( MXIT_PLUGIN_ID, "RESPONSE: %s\n", url_text );
--#endif
--
-- if ( !url_text ) {
-- /* no reply from the WAP site */
-- purple_connection_error( session->con, _( "Error contacting the MXit WAP site. Please try again later." ) );
-- return;
-- }
--
-- /* explode the response from the WAP site into an array */
-- parts = g_strsplit( url_text, ";", 15 );
--
-- if ( ( !parts ) || ( parts[0][0] != '0' ) ) {
-- /* server could not find the user */
-- purple_connection_error( session->con, _( "MXit is currently unable to process the request. Please try again later." ) );
-- return;
-- }
--
-- /* save received settings */
-- logindata = g_new0( struct login_data, 1 );
-- logindata->wapserver = g_strdup( parts[1] );
-- logindata->sessionid = g_strdup( parts[2] );
-- session->logindata = logindata;
--
-- /* now generate the popup requesting the user for action */
--
-- fields = purple_request_fields_new();
-- group = purple_request_field_group_new( NULL );
-- purple_request_fields_add_group( fields, group );
--
-- /* add the captcha */
-- logindata->captcha = purple_base64_decode( parts[3], &logindata->captcha_size );
-- field = purple_request_field_image_new( "captcha", _( "Security Code" ), (gchar*) logindata->captcha, logindata->captcha_size );
-- purple_request_field_group_add_field( group, field );
--
-- /* ask for input (required) */
-- field = purple_request_field_string_new( "code", _( "Enter Security Code" ), NULL, FALSE );
-- purple_request_field_set_required( field, TRUE );
-- purple_request_field_group_add_field( group, field );
--
-- /* choose your country, but be careful, we already know your IP! ;-) */
-- countries = g_strsplit( parts[4], ",", 500 );
-- field = purple_request_field_list_new( "country", _( "Your Country" ) );
-- purple_request_field_list_set_multi_select( field, FALSE );
-- for ( i = 0; countries[i]; i++ ) {
-- gchar** country;
--
-- country = g_strsplit( countries[i], "|", 2 );
-- if ( !country ) {
-- /* oops, this is not good, time to bail */
-- break;
-- }
-- purple_request_field_list_add( field, country[1], g_strdup( country[0] ) );
-- if ( strcmp( country[1], parts[6] ) == 0 ) {
-- /* based on the user's IP, this is his current country code, so we default to it */
-- purple_request_field_list_add_selected( field, country[1] );
-- }
-- g_strfreev( country );
-- }
-- purple_request_field_group_add_field( group, field );
--
-- /* choose your language */
-- locales = g_strsplit( parts[5], ",", 200 );
-- field = purple_request_field_list_new( "locale", _( "Your Language" ) );
-- purple_request_field_list_set_multi_select( field, FALSE );
-- for ( i = 0; locales[i]; i++ ) {
-- gchar** locale;
--
-- locale = g_strsplit( locales[i], "|", 2 );
-- if ( !locale ) {
-- /* oops, this is not good, time to bail */
-- break;
-- }
-- purple_request_field_list_add( field, locale[1], g_strdup( locale[0] ) );
-- g_strfreev( locale );
-- }
-- purple_request_field_list_add_selected( field, "English" );
-- purple_request_field_group_add_field( group, field );
--
-- /* display the form to the user and wait for his/her input */
-- purple_request_fields( session->con, "MXit", _( "MXit Authorization" ), _( "MXit account validation" ), fields,
-- _( "Continue" ), G_CALLBACK( mxit_cb_captcha_ok ), _( "Cancel" ), G_CALLBACK( mxit_cb_captcha_cancel ), session->acc, NULL, NULL, session->con );
--
-- /* freeup the memory */
-- g_strfreev( parts );
--}
--
--
--/*------------------------------------------------------------------------
-- * Initiate a request for the client information (distribution code, client key, etc)
-- * required for logging in from the MXit WAP site.
-- *
-- * @param session The MXit session object
-- */
--static void get_clientinfo( struct MXitSession* session )
--{
-- PurpleUtilFetchUrlData* url_data;
-- const char* wapserver;
-- char* url;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "get_clientinfo\n" );
--
-- purple_connection_update_progress( session->con, _( "Retrieving User Information..." ), 0, 4 );
--
-- /* get the WAP site as was configured by the user in the advanced settings */
-- wapserver = purple_account_get_string( session->acc, MXIT_CONFIG_WAPSERVER, DEFAULT_WAPSITE );
--
-- /* reference: "libpurple/util.h" */
-- url = g_strdup_printf( "%s/res/?type=challenge&getcountries=true&getlanguage=true&getimage=true&h=%i&w=%i&ts=%li", wapserver, MXIT_CAPTCHA_HEIGHT, MXIT_CAPTCHA_WIDTH, time( NULL ) );
-- url_data = purple_util_fetch_url_request( url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, mxit_cb_clientinfo1, session );
--
--#ifdef DEBUG_PROTOCOL
-- purple_debug_info( MXIT_PLUGIN_ID, "HTTP REQUEST: '%s'\n", url );
--#endif
-- g_free( url );
--}
--
--
--/*------------------------------------------------------------------------
-- * Log the user into MXit.
-- *
-- * @param account The account object
-- */
--void mxit_login( PurpleAccount* account )
--{
-- struct MXitSession* session = NULL;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_login\n" );
--
-- /* create and save a new mxit session */
-- session = mxit_create_object( account );
--
-- /*
-- * before we can login we need to have a valid distribution code and client key for authentication.
-- * if we don't have any info saved from a previous login, we need to get it from the MXit WAP site.
-- * we do cache it, so this step is only done on the very first login for each account.
-- */
-- if ( ( session->distcode == NULL ) || ( strlen( session->distcode ) == 0 ) ) {
-- /* this must be the very first login, so we need to retrieve the user information */
-- get_clientinfo( session );
-- }
-- else {
-- /* we can continue with the login */
-- mxit_login_connect( session );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Perform a reconnect to the MXit server, and maintain same session object.
-- *
-- * @param account The account object
-- */
--void mxit_reconnect( struct MXitSession* session )
--{
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_reconnect\n" );
--
-- /* remove the input cb function */
-- if ( session->con->inpa ) {
-- purple_input_remove( session->con->inpa );
-- session->con->inpa = 0;
-- }
--
-- /* close existing connection */
-- session->flags &= ~MXIT_FLAG_CONNECTED;
-- purple_proxy_connect_cancel_with_handle( session->con );
--
-- /* perform the re-connect */
-- mxit_login_connect( session );
--}
--
--
--/*------------------------------------------------------------------------
-- * Register a new account with MXit
-- *
-- * @param acc The account object
-- */
--void mxit_register( PurpleAccount* account )
--{
-- struct MXitSession* session = NULL;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_register\n" );
--
-- /* create and save a new mxit session */
-- session = mxit_create_object( account );
-- purple_account_set_int( account, MXIT_CONFIG_STATE, MXIT_STATE_REGISTER1 );
--
-- get_clientinfo( session );
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/login.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/login.h
---- pidgin-2.10.7/libpurple/protocols/mxit/login.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/login.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,45 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- MXit user login functionality --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MXIT_LOGIN_H_
--#define _MXIT_LOGIN_H_
--
--
--struct login_data {
-- char* wapserver; /* direct WAP server for postback */
-- char* sessionid; /* unique session id */
-- guchar* captcha; /* actual captcha (PNG) */
-- gsize captcha_size; /* captcha size */
-- char* cc; /* country code */
-- char* locale; /* locale (language) */
--};
--
--
--void mxit_login( PurpleAccount* account );
--void mxit_register( PurpleAccount* account );
--void mxit_reconnect( struct MXitSession* session );
--
--
--#endif /* _MXIT_LOGIN_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/mxit/Makefile.am
---- pidgin-2.10.7/libpurple/protocols/mxit/Makefile.am 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/Makefile.am 1969-12-31 21:00:00.000000000 -0300
-@@ -1,65 +0,0 @@
--EXTRA_DIST = \
-- Makefile.mingw
--
--pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
--
--MXITSOURCES = \
-- actions.c \
-- actions.h \
-- aes.c \
-- aes.h \
-- chunk.c \
-- chunk.h \
-- cipher.c \
-- cipher.h \
-- filexfer.c \
-- filexfer.h \
-- formcmds.c \
-- formcmds.h \
-- http.c \
-- http.h \
-- login.c \
-- login.h \
-- markup.c \
-- markup.h \
-- multimx.c \
-- multimx.h \
-- mxit.c \
-- mxit.h \
-- profile.c \
-- profile.h \
-- protocol.c \
-- protocol.h \
-- roster.c \
-- roster.h \
-- splashscreen.c \
-- splashscreen.h \
-- voicevideo.c \
-- voicevideo.h
--
--
--AM_CFLAGS = $(st)
--
--libmxit_la_LDFLAGS = -module -avoid-version
--
--if STATIC_MXIT
--
--st = -DPURPLE_STATIC_PRPL
--noinst_LTLIBRARIES = libmxit.la
--libmxit_la_SOURCES = $(MXITSOURCES)
--libmxit_la_CFLAGS = $(AM_CFLAGS)
--
--else
--
--st =
--pkg_LTLIBRARIES = libmxit.la
--libmxit_la_SOURCES = $(MXITSOURCES)
--libmxit_la_LIBADD = $(GLIB_LIBS)
--
--endif
--
--AM_CPPFLAGS = \
-- -I$(top_srcdir)/libpurple \
-- -I$(top_builddir)/libpurple \
-- $(GLIB_CFLAGS) \
-- $(DEBUG_CFLAGS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/mxit/Makefile.in
---- pidgin-2.10.7/libpurple/protocols/mxit/Makefile.in 2013-02-11 07:17:21.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/Makefile.in 1969-12-31 21:00:00.000000000 -0300
-@@ -1,909 +0,0 @@
--# Makefile.in generated by automake 1.11.6 from Makefile.am.
--# @configure_input@
--
--# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
--# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
--# Foundation, Inc.
--# This Makefile.in is free software; the Free Software Foundation
--# gives unlimited permission to copy and/or distribute it,
--# with or without modifications, as long as this notice is preserved.
--
--# This program is distributed in the hope that it will be useful,
--# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
--# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
--# PARTICULAR PURPOSE.
--
--@SET_MAKE@
--
--VPATH = @srcdir@
--am__make_dryrun = \
-- { \
-- am__dry=no; \
-- case $$MAKEFLAGS in \
-- *\\[\ \ ]*) \
-- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
-- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
-- *) \
-- for am__flg in $$MAKEFLAGS; do \
-- case $$am__flg in \
-- *=*|--*) ;; \
-- *n*) am__dry=yes; break;; \
-- esac; \
-- done;; \
-- esac; \
-- test $$am__dry = yes; \
-- }
--pkgdatadir = $(datadir)/@PACKAGE@
--pkgincludedir = $(includedir)/@PACKAGE@
--pkglibdir = $(libdir)/@PACKAGE@
--pkglibexecdir = $(libexecdir)/@PACKAGE@
--am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
--install_sh_DATA = $(install_sh) -c -m 644
--install_sh_PROGRAM = $(install_sh) -c
--install_sh_SCRIPT = $(install_sh) -c
--INSTALL_HEADER = $(INSTALL_DATA)
--transform = $(program_transform_name)
--NORMAL_INSTALL = :
--PRE_INSTALL = :
--POST_INSTALL = :
--NORMAL_UNINSTALL = :
--PRE_UNINSTALL = :
--POST_UNINSTALL = :
--build_triplet = @build@
--host_triplet = @host@
--subdir = libpurple/protocols/mxit
--DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
--ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
--am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
-- $(top_srcdir)/configure.ac
--am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-- $(ACLOCAL_M4)
--mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
--CONFIG_HEADER = $(top_builddir)/config.h
--CONFIG_CLEAN_FILES =
--CONFIG_CLEAN_VPATH_FILES =
--am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
--am__vpath_adj = case $$p in \
-- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
-- *) f=$$p;; \
-- esac;
--am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
--am__install_max = 40
--am__nobase_strip_setup = \
-- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
--am__nobase_strip = \
-- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
--am__nobase_list = $(am__nobase_strip_setup); \
-- for p in $$list; do echo "$$p $$p"; done | \
-- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
-- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
-- if (++n[$$2] == $(am__install_max)) \
-- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
-- END { for (dir in files) print dir, files[dir] }'
--am__base_list = \
-- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
-- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
--am__uninstall_files_from_dir = { \
-- test -z "$$files" \
-- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
-- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
-- $(am__cd) "$$dir" && rm -f $$files; }; \
-- }
--am__installdirs = "$(DESTDIR)$(pkgdir)"
--LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkg_LTLIBRARIES)
--am__DEPENDENCIES_1 =
--@STATIC_MXIT_FALSE@libmxit_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
--am__libmxit_la_SOURCES_DIST = actions.c actions.h aes.c aes.h chunk.c \
-- chunk.h cipher.c cipher.h filexfer.c filexfer.h formcmds.c \
-- formcmds.h http.c http.h login.c login.h markup.c markup.h \
-- multimx.c multimx.h mxit.c mxit.h profile.c profile.h \
-- protocol.c protocol.h roster.c roster.h splashscreen.c \
-- splashscreen.h voicevideo.c voicevideo.h
--am__objects_1 = libmxit_la-actions.lo libmxit_la-aes.lo \
-- libmxit_la-chunk.lo libmxit_la-cipher.lo \
-- libmxit_la-filexfer.lo libmxit_la-formcmds.lo \
-- libmxit_la-http.lo libmxit_la-login.lo libmxit_la-markup.lo \
-- libmxit_la-multimx.lo libmxit_la-mxit.lo libmxit_la-profile.lo \
-- libmxit_la-protocol.lo libmxit_la-roster.lo \
-- libmxit_la-splashscreen.lo libmxit_la-voicevideo.lo
--@STATIC_MXIT_FALSE@am_libmxit_la_OBJECTS = $(am__objects_1)
--@STATIC_MXIT_TRUE@am_libmxit_la_OBJECTS = $(am__objects_1)
--libmxit_la_OBJECTS = $(am_libmxit_la_OBJECTS)
--AM_V_lt = $(am__v_lt_@AM_V@)
--am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
--am__v_lt_0 = --silent
--libmxit_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libmxit_la_CFLAGS) \
-- $(CFLAGS) $(libmxit_la_LDFLAGS) $(LDFLAGS) -o $@
--@STATIC_MXIT_FALSE@am_libmxit_la_rpath = -rpath $(pkgdir)
--@STATIC_MXIT_TRUE@am_libmxit_la_rpath =
--DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
--depcomp = $(SHELL) $(top_srcdir)/depcomp
--am__depfiles_maybe = depfiles
--am__mv = mv -f
--COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
--LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-- $(AM_CFLAGS) $(CFLAGS)
--AM_V_CC = $(am__v_CC_@AM_V@)
--am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
--am__v_CC_0 = @echo " CC " $@;
--AM_V_at = $(am__v_at_@AM_V@)
--am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
--am__v_at_0 = @
--CCLD = $(CC)
--LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-- $(AM_LDFLAGS) $(LDFLAGS) -o $@
--AM_V_CCLD = $(am__v_CCLD_@AM_V@)
--am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
--am__v_CCLD_0 = @echo " CCLD " $@;
--AM_V_GEN = $(am__v_GEN_@AM_V@)
--am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
--am__v_GEN_0 = @echo " GEN " $@;
--SOURCES = $(libmxit_la_SOURCES)
--DIST_SOURCES = $(am__libmxit_la_SOURCES_DIST)
--am__can_run_installinfo = \
-- case $$AM_UPDATE_INFO_DIR in \
-- n|no|NO) false;; \
-- *) (install-info --version) >/dev/null 2>&1;; \
-- esac
--ETAGS = etags
--CTAGS = ctags
--DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
--ACLOCAL = @ACLOCAL@
--ALLOCA = @ALLOCA@
--ALL_LINGUAS = @ALL_LINGUAS@
--AMTAR = @AMTAR@
--AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
--AR = @AR@
--AUTOCONF = @AUTOCONF@
--AUTOHEADER = @AUTOHEADER@
--AUTOMAKE = @AUTOMAKE@
--AVAHI_CFLAGS = @AVAHI_CFLAGS@
--AVAHI_LIBS = @AVAHI_LIBS@
--AWK = @AWK@
--CATALOGS = @CATALOGS@
--CATOBJEXT = @CATOBJEXT@
--CC = @CC@
--CCDEPMODE = @CCDEPMODE@
--CFLAGS = @CFLAGS@
--CHECK_CFLAGS = @CHECK_CFLAGS@
--CHECK_LIBS = @CHECK_LIBS@
--CPP = @CPP@
--CPPFLAGS = @CPPFLAGS@
--CYGPATH_W = @CYGPATH_W@
--DATADIRNAME = @DATADIRNAME@
--DBUS_CFLAGS = @DBUS_CFLAGS@
--DBUS_LIBS = @DBUS_LIBS@
--DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
--DEBUG_CFLAGS = @DEBUG_CFLAGS@
--DEFS = @DEFS@
--DEPDIR = @DEPDIR@
--DLLTOOL = @DLLTOOL@
--DOT = @DOT@
--DOXYGEN = @DOXYGEN@
--DSYMUTIL = @DSYMUTIL@
--DUMPBIN = @DUMPBIN@
--DYNALOADER_A = @DYNALOADER_A@
--DYNAMIC_PRPLS = @DYNAMIC_PRPLS@
--ECHO_C = @ECHO_C@
--ECHO_N = @ECHO_N@
--ECHO_T = @ECHO_T@
--EGREP = @EGREP@
--EVOLUTION_ADDRESSBOOK_CFLAGS = @EVOLUTION_ADDRESSBOOK_CFLAGS@
--EVOLUTION_ADDRESSBOOK_LIBS = @EVOLUTION_ADDRESSBOOK_LIBS@
--EXEEXT = @EXEEXT@
--FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
--FARSTREAM_LIBS = @FARSTREAM_LIBS@
--FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
--GCONFTOOL = @GCONFTOOL@
--GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
--GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
--GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
--GLIB_CFLAGS = @GLIB_CFLAGS@
--GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
--GLIB_LIBS = @GLIB_LIBS@
--GMOFILES = @GMOFILES@
--GMSGFMT = @GMSGFMT@
--GNT_CFLAGS = @GNT_CFLAGS@
--GNT_LIBS = @GNT_LIBS@
--GNT_LT_VERSION_INFO = @GNT_LT_VERSION_INFO@
--GNT_MAJOR_VERSION = @GNT_MAJOR_VERSION@
--GNT_MICRO_VERSION = @GNT_MICRO_VERSION@
--GNT_MINOR_VERSION = @GNT_MINOR_VERSION@
--GNT_VERSION = @GNT_VERSION@
--GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
--GNUTLS_LIBS = @GNUTLS_LIBS@
--GREP = @GREP@
--GSTINTERFACES_CFLAGS = @GSTINTERFACES_CFLAGS@
--GSTINTERFACES_LIBS = @GSTINTERFACES_LIBS@
--GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
--GSTREAMER_LIBS = @GSTREAMER_LIBS@
--GTKSPELL_CFLAGS = @GTKSPELL_CFLAGS@
--GTKSPELL_LIBS = @GTKSPELL_LIBS@
--GTK_CFLAGS = @GTK_CFLAGS@
--GTK_LIBS = @GTK_LIBS@
--IDN_CFLAGS = @IDN_CFLAGS@
--IDN_LIBS = @IDN_LIBS@
--INSTALL = @INSTALL@
--INSTALL_DATA = @INSTALL_DATA@
--INSTALL_PROGRAM = @INSTALL_PROGRAM@
--INSTALL_SCRIPT = @INSTALL_SCRIPT@
--INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
--INSTOBJEXT = @INSTOBJEXT@
--INTLLIBS = @INTLLIBS@
--INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
--INTLTOOL_MERGE = @INTLTOOL_MERGE@
--INTLTOOL_PERL = @INTLTOOL_PERL@
--INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
--INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
--INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
--INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
--INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
--KRB4_CFLAGS = @KRB4_CFLAGS@
--KRB4_LDFLAGS = @KRB4_LDFLAGS@
--KRB4_LIBS = @KRB4_LIBS@
--LD = @LD@
--LDADD = @LDADD@
--LDFLAGS = @LDFLAGS@
--LIBOBJS = @LIBOBJS@
--LIBPERL_A = @LIBPERL_A@
--LIBS = @LIBS@
--LIBTOOL = @LIBTOOL@
--LIBXML_CFLAGS = @LIBXML_CFLAGS@
--LIBXML_LIBS = @LIBXML_LIBS@
--LIPO = @LIPO@
--LN_S = @LN_S@
--LTLIBOBJS = @LTLIBOBJS@
--MAKEINFO = @MAKEINFO@
--MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
--MKDIR_P = @MKDIR_P@
--MKINSTALLDIRS = @MKINSTALLDIRS@
--MONO_CFLAGS = @MONO_CFLAGS@
--MONO_LIBS = @MONO_LIBS@
--MSGFMT = @MSGFMT@
--MSGFMT_OPTS = @MSGFMT_OPTS@
--MSGMERGE = @MSGMERGE@
--NETWORKMANAGER_CFLAGS = @NETWORKMANAGER_CFLAGS@
--NETWORKMANAGER_LIBS = @NETWORKMANAGER_LIBS@
--NM = @NM@
--NMEDIT = @NMEDIT@
--NSS_CFLAGS = @NSS_CFLAGS@
--NSS_LIBS = @NSS_LIBS@
--OBJDUMP = @OBJDUMP@
--OBJEXT = @OBJEXT@
--OTOOL = @OTOOL@
--OTOOL64 = @OTOOL64@
--PACKAGE = @PACKAGE@
--PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
--PACKAGE_NAME = @PACKAGE_NAME@
--PACKAGE_STRING = @PACKAGE_STRING@
--PACKAGE_TARNAME = @PACKAGE_TARNAME@
--PACKAGE_URL = @PACKAGE_URL@
--PACKAGE_VERSION = @PACKAGE_VERSION@
--PANGO_CFLAGS = @PANGO_CFLAGS@
--PANGO_LIBS = @PANGO_LIBS@
--PATH_SEPARATOR = @PATH_SEPARATOR@
--PERL = @PERL@
--PERL_CFLAGS = @PERL_CFLAGS@
--PERL_LIBS = @PERL_LIBS@
--PKG_CONFIG = @PKG_CONFIG@
--PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
--PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
--PLUGINS_DEFINE = @PLUGINS_DEFINE@
--POFILES = @POFILES@
--POSUB = @POSUB@
--PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
--PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
--PURPLE_LT_VERSION_INFO = @PURPLE_LT_VERSION_INFO@
--PURPLE_MAJOR_VERSION = @PURPLE_MAJOR_VERSION@
--PURPLE_MICRO_VERSION = @PURPLE_MICRO_VERSION@
--PURPLE_MINOR_VERSION = @PURPLE_MINOR_VERSION@
--PURPLE_VERSION = @PURPLE_VERSION@
--PYTHON = @PYTHON@
--PY_CFLAGS = @PY_CFLAGS@
--PY_LIBS = @PY_LIBS@
--RANLIB = @RANLIB@
--SASL_LIBS = @SASL_LIBS@
--SED = @SED@
--SET_MAKE = @SET_MAKE@
--SHELL = @SHELL@
--SILC_CFLAGS = @SILC_CFLAGS@
--SILC_LIBS = @SILC_LIBS@
--SM_LIBS = @SM_LIBS@
--SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
--SQLITE3_LIBS = @SQLITE3_LIBS@
--SSL_CERTIFICATES_DIR = @SSL_CERTIFICATES_DIR@
--STATIC_LINK_LIBS = @STATIC_LINK_LIBS@
--STATIC_PRPLS = @STATIC_PRPLS@
--STRIP = @STRIP@
--TCL_CFLAGS = @TCL_CFLAGS@
--TCL_LIBS = @TCL_LIBS@
--TK_LIBS = @TK_LIBS@
--USE_NLS = @USE_NLS@
--VERSION = @VERSION@
--X11_CFLAGS = @X11_CFLAGS@
--X11_LIBS = @X11_LIBS@
--XGETTEXT = @XGETTEXT@
--XMKMF = @XMKMF@
--XSLTPROC = @XSLTPROC@
--XSS_LIBS = @XSS_LIBS@
--X_CFLAGS = @X_CFLAGS@
--X_EXTRA_LIBS = @X_EXTRA_LIBS@
--X_LIBS = @X_LIBS@
--X_PRE_LIBS = @X_PRE_LIBS@
--ZEPHYR_CFLAGS = @ZEPHYR_CFLAGS@
--ZEPHYR_LDFLAGS = @ZEPHYR_LDFLAGS@
--ZEPHYR_LIBS = @ZEPHYR_LIBS@
--abs_builddir = @abs_builddir@
--abs_srcdir = @abs_srcdir@
--abs_top_builddir = @abs_top_builddir@
--abs_top_srcdir = @abs_top_srcdir@
--ac_ct_AR = @ac_ct_AR@
--ac_ct_CC = @ac_ct_CC@
--ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
--am__include = @am__include@
--am__leading_dot = @am__leading_dot@
--am__quote = @am__quote@
--am__tar = @am__tar@
--am__untar = @am__untar@
--bindir = @bindir@
--build = @build@
--build_alias = @build_alias@
--build_cpu = @build_cpu@
--build_os = @build_os@
--build_vendor = @build_vendor@
--builddir = @builddir@
--datadir = @datadir@
--datarootdir = @datarootdir@
--docdir = @docdir@
--dvidir = @dvidir@
--enable_dbus = @enable_dbus@
--enable_devhelp = @enable_devhelp@
--enable_dot = @enable_dot@
--enable_doxygen = @enable_doxygen@
--exec_prefix = @exec_prefix@
--host = @host@
--host_alias = @host_alias@
--host_cpu = @host_cpu@
--host_os = @host_os@
--host_vendor = @host_vendor@
--htmldir = @htmldir@
--includedir = @includedir@
--infodir = @infodir@
--install_sh = @install_sh@
--intltool__v_merge_options_ = @intltool__v_merge_options_@
--intltool__v_merge_options_0 = @intltool__v_merge_options_0@
--libdir = @libdir@
--libexecdir = @libexecdir@
--localedir = @localedir@
--localstatedir = @localstatedir@
--mandir = @mandir@
--mkdir_p = @mkdir_p@
--oldincludedir = @oldincludedir@
--pdfdir = @pdfdir@
--perlpath = @perlpath@
--pidginpath = @pidginpath@
--prefix = @prefix@
--program_transform_name = @program_transform_name@
--psdir = @psdir@
--sbindir = @sbindir@
--sedpath = @sedpath@
--sharedstatedir = @sharedstatedir@
--srcdir = @srcdir@
--sysconfdir = @sysconfdir@
--target_alias = @target_alias@
--top_build_prefix = @top_build_prefix@
--top_builddir = @top_builddir@
--top_srcdir = @top_srcdir@
--EXTRA_DIST = \
-- Makefile.mingw
--
--pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
--MXITSOURCES = \
-- actions.c \
-- actions.h \
-- aes.c \
-- aes.h \
-- chunk.c \
-- chunk.h \
-- cipher.c \
-- cipher.h \
-- filexfer.c \
-- filexfer.h \
-- formcmds.c \
-- formcmds.h \
-- http.c \
-- http.h \
-- login.c \
-- login.h \
-- markup.c \
-- markup.h \
-- multimx.c \
-- multimx.h \
-- mxit.c \
-- mxit.h \
-- profile.c \
-- profile.h \
-- protocol.c \
-- protocol.h \
-- roster.c \
-- roster.h \
-- splashscreen.c \
-- splashscreen.h \
-- voicevideo.c \
-- voicevideo.h
--
--AM_CFLAGS = $(st)
--libmxit_la_LDFLAGS = -module -avoid-version
--@STATIC_MXIT_FALSE@st =
--@STATIC_MXIT_TRUE@st = -DPURPLE_STATIC_PRPL
--@STATIC_MXIT_TRUE@noinst_LTLIBRARIES = libmxit.la
--@STATIC_MXIT_FALSE@libmxit_la_SOURCES = $(MXITSOURCES)
--@STATIC_MXIT_TRUE@libmxit_la_SOURCES = $(MXITSOURCES)
--@STATIC_MXIT_TRUE@libmxit_la_CFLAGS = $(AM_CFLAGS)
--@STATIC_MXIT_FALSE@pkg_LTLIBRARIES = libmxit.la
--@STATIC_MXIT_FALSE@libmxit_la_LIBADD = $(GLIB_LIBS)
--AM_CPPFLAGS = \
-- -I$(top_srcdir)/libpurple \
-- -I$(top_builddir)/libpurple \
-- $(GLIB_CFLAGS) \
-- $(DEBUG_CFLAGS)
--
--all: all-am
--
--.SUFFIXES:
--.SUFFIXES: .c .lo .o .obj
--$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
-- @for dep in $?; do \
-- case '$(am__configure_deps)' in \
-- *$$dep*) \
-- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
-- && { if test -f $@; then exit 0; else break; fi; }; \
-- exit 1;; \
-- esac; \
-- done; \
-- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpurple/protocols/mxit/Makefile'; \
-- $(am__cd) $(top_srcdir) && \
-- $(AUTOMAKE) --gnu libpurple/protocols/mxit/Makefile
--.PRECIOUS: Makefile
--Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-- @case '$?' in \
-- *config.status*) \
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-- *) \
-- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-- esac;
--
--$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--
--$(top_srcdir)/configure: $(am__configure_deps)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--$(ACLOCAL_M4): $(am__aclocal_m4_deps)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--$(am__aclocal_m4_deps):
--
--clean-noinstLTLIBRARIES:
-- -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-- @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
-- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-- test "$$dir" != "$$p" || dir=.; \
-- echo "rm -f \"$${dir}/so_locations\""; \
-- rm -f "$${dir}/so_locations"; \
-- done
--install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES)
-- @$(NORMAL_INSTALL)
-- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
-- list2=; for p in $$list; do \
-- if test -f $$p; then \
-- list2="$$list2 $$p"; \
-- else :; fi; \
-- done; \
-- test -z "$$list2" || { \
-- echo " $(MKDIR_P) '$(DESTDIR)$(pkgdir)'"; \
-- $(MKDIR_P) "$(DESTDIR)$(pkgdir)" || exit 1; \
-- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgdir)'"; \
-- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgdir)"; \
-- }
--
--uninstall-pkgLTLIBRARIES:
-- @$(NORMAL_UNINSTALL)
-- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
-- for p in $$list; do \
-- $(am__strip_dir) \
-- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgdir)/$$f'"; \
-- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgdir)/$$f"; \
-- done
--
--clean-pkgLTLIBRARIES:
-- -test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES)
-- @list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
-- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-- test "$$dir" != "$$p" || dir=.; \
-- echo "rm -f \"$${dir}/so_locations\""; \
-- rm -f "$${dir}/so_locations"; \
-- done
--libmxit.la: $(libmxit_la_OBJECTS) $(libmxit_la_DEPENDENCIES) $(EXTRA_libmxit_la_DEPENDENCIES)
-- $(AM_V_CCLD)$(libmxit_la_LINK) $(am_libmxit_la_rpath) $(libmxit_la_OBJECTS) $(libmxit_la_LIBADD) $(LIBS)
--
--mostlyclean-compile:
-- -rm -f *.$(OBJEXT)
--
--distclean-compile:
-- -rm -f *.tab.c
--
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-actions.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-aes.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-chunk.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-cipher.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-filexfer.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-formcmds.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-http.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-login.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-markup.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-multimx.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-mxit.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-profile.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-protocol.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-roster.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-splashscreen.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-voicevideo.Plo@am__quote@
--
--.c.o:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
--
--.c.obj:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
--
--.c.lo:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
--
--libmxit_la-actions.lo: actions.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-actions.lo -MD -MP -MF $(DEPDIR)/libmxit_la-actions.Tpo -c -o libmxit_la-actions.lo `test -f 'actions.c' || echo '$(srcdir)/'`actions.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-actions.Tpo $(DEPDIR)/libmxit_la-actions.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='actions.c' object='libmxit_la-actions.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-actions.lo `test -f 'actions.c' || echo '$(srcdir)/'`actions.c
--
--libmxit_la-aes.lo: aes.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-aes.lo -MD -MP -MF $(DEPDIR)/libmxit_la-aes.Tpo -c -o libmxit_la-aes.lo `test -f 'aes.c' || echo '$(srcdir)/'`aes.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-aes.Tpo $(DEPDIR)/libmxit_la-aes.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='aes.c' object='libmxit_la-aes.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-aes.lo `test -f 'aes.c' || echo '$(srcdir)/'`aes.c
--
--libmxit_la-chunk.lo: chunk.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-chunk.lo -MD -MP -MF $(DEPDIR)/libmxit_la-chunk.Tpo -c -o libmxit_la-chunk.lo `test -f 'chunk.c' || echo '$(srcdir)/'`chunk.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-chunk.Tpo $(DEPDIR)/libmxit_la-chunk.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='chunk.c' object='libmxit_la-chunk.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-chunk.lo `test -f 'chunk.c' || echo '$(srcdir)/'`chunk.c
--
--libmxit_la-cipher.lo: cipher.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-cipher.lo -MD -MP -MF $(DEPDIR)/libmxit_la-cipher.Tpo -c -o libmxit_la-cipher.lo `test -f 'cipher.c' || echo '$(srcdir)/'`cipher.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-cipher.Tpo $(DEPDIR)/libmxit_la-cipher.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cipher.c' object='libmxit_la-cipher.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-cipher.lo `test -f 'cipher.c' || echo '$(srcdir)/'`cipher.c
--
--libmxit_la-filexfer.lo: filexfer.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-filexfer.lo -MD -MP -MF $(DEPDIR)/libmxit_la-filexfer.Tpo -c -o libmxit_la-filexfer.lo `test -f 'filexfer.c' || echo '$(srcdir)/'`filexfer.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-filexfer.Tpo $(DEPDIR)/libmxit_la-filexfer.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='filexfer.c' object='libmxit_la-filexfer.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-filexfer.lo `test -f 'filexfer.c' || echo '$(srcdir)/'`filexfer.c
--
--libmxit_la-formcmds.lo: formcmds.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-formcmds.lo -MD -MP -MF $(DEPDIR)/libmxit_la-formcmds.Tpo -c -o libmxit_la-formcmds.lo `test -f 'formcmds.c' || echo '$(srcdir)/'`formcmds.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-formcmds.Tpo $(DEPDIR)/libmxit_la-formcmds.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='formcmds.c' object='libmxit_la-formcmds.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-formcmds.lo `test -f 'formcmds.c' || echo '$(srcdir)/'`formcmds.c
--
--libmxit_la-http.lo: http.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-http.lo -MD -MP -MF $(DEPDIR)/libmxit_la-http.Tpo -c -o libmxit_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-http.Tpo $(DEPDIR)/libmxit_la-http.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http.c' object='libmxit_la-http.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c
--
--libmxit_la-login.lo: login.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-login.lo -MD -MP -MF $(DEPDIR)/libmxit_la-login.Tpo -c -o libmxit_la-login.lo `test -f 'login.c' || echo '$(srcdir)/'`login.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-login.Tpo $(DEPDIR)/libmxit_la-login.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='login.c' object='libmxit_la-login.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-login.lo `test -f 'login.c' || echo '$(srcdir)/'`login.c
--
--libmxit_la-markup.lo: markup.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-markup.lo -MD -MP -MF $(DEPDIR)/libmxit_la-markup.Tpo -c -o libmxit_la-markup.lo `test -f 'markup.c' || echo '$(srcdir)/'`markup.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-markup.Tpo $(DEPDIR)/libmxit_la-markup.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='markup.c' object='libmxit_la-markup.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-markup.lo `test -f 'markup.c' || echo '$(srcdir)/'`markup.c
--
--libmxit_la-multimx.lo: multimx.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-multimx.lo -MD -MP -MF $(DEPDIR)/libmxit_la-multimx.Tpo -c -o libmxit_la-multimx.lo `test -f 'multimx.c' || echo '$(srcdir)/'`multimx.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-multimx.Tpo $(DEPDIR)/libmxit_la-multimx.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='multimx.c' object='libmxit_la-multimx.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-multimx.lo `test -f 'multimx.c' || echo '$(srcdir)/'`multimx.c
--
--libmxit_la-mxit.lo: mxit.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-mxit.lo -MD -MP -MF $(DEPDIR)/libmxit_la-mxit.Tpo -c -o libmxit_la-mxit.lo `test -f 'mxit.c' || echo '$(srcdir)/'`mxit.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-mxit.Tpo $(DEPDIR)/libmxit_la-mxit.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mxit.c' object='libmxit_la-mxit.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-mxit.lo `test -f 'mxit.c' || echo '$(srcdir)/'`mxit.c
--
--libmxit_la-profile.lo: profile.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-profile.lo -MD -MP -MF $(DEPDIR)/libmxit_la-profile.Tpo -c -o libmxit_la-profile.lo `test -f 'profile.c' || echo '$(srcdir)/'`profile.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-profile.Tpo $(DEPDIR)/libmxit_la-profile.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='profile.c' object='libmxit_la-profile.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-profile.lo `test -f 'profile.c' || echo '$(srcdir)/'`profile.c
--
--libmxit_la-protocol.lo: protocol.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-protocol.lo -MD -MP -MF $(DEPDIR)/libmxit_la-protocol.Tpo -c -o libmxit_la-protocol.lo `test -f 'protocol.c' || echo '$(srcdir)/'`protocol.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-protocol.Tpo $(DEPDIR)/libmxit_la-protocol.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='protocol.c' object='libmxit_la-protocol.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-protocol.lo `test -f 'protocol.c' || echo '$(srcdir)/'`protocol.c
--
--libmxit_la-roster.lo: roster.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-roster.lo -MD -MP -MF $(DEPDIR)/libmxit_la-roster.Tpo -c -o libmxit_la-roster.lo `test -f 'roster.c' || echo '$(srcdir)/'`roster.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-roster.Tpo $(DEPDIR)/libmxit_la-roster.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='roster.c' object='libmxit_la-roster.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-roster.lo `test -f 'roster.c' || echo '$(srcdir)/'`roster.c
--
--libmxit_la-splashscreen.lo: splashscreen.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-splashscreen.lo -MD -MP -MF $(DEPDIR)/libmxit_la-splashscreen.Tpo -c -o libmxit_la-splashscreen.lo `test -f 'splashscreen.c' || echo '$(srcdir)/'`splashscreen.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-splashscreen.Tpo $(DEPDIR)/libmxit_la-splashscreen.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='splashscreen.c' object='libmxit_la-splashscreen.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-splashscreen.lo `test -f 'splashscreen.c' || echo '$(srcdir)/'`splashscreen.c
--
--libmxit_la-voicevideo.lo: voicevideo.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-voicevideo.lo -MD -MP -MF $(DEPDIR)/libmxit_la-voicevideo.Tpo -c -o libmxit_la-voicevideo.lo `test -f 'voicevideo.c' || echo '$(srcdir)/'`voicevideo.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-voicevideo.Tpo $(DEPDIR)/libmxit_la-voicevideo.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='voicevideo.c' object='libmxit_la-voicevideo.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-voicevideo.lo `test -f 'voicevideo.c' || echo '$(srcdir)/'`voicevideo.c
--
--mostlyclean-libtool:
-- -rm -f *.lo
--
--clean-libtool:
-- -rm -rf .libs _libs
--
--ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- mkid -fID $$unique
--tags: TAGS
--
--TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
-- $(TAGS_FILES) $(LISP)
-- set x; \
-- here=`pwd`; \
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- shift; \
-- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-- test -n "$$unique" || unique=$$empty_fix; \
-- if test $$# -gt 0; then \
-- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-- "$$@" $$unique; \
-- else \
-- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-- $$unique; \
-- fi; \
-- fi
--ctags: CTAGS
--CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
-- $(TAGS_FILES) $(LISP)
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- test -z "$(CTAGS_ARGS)$$unique" \
-- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-- $$unique
--
--GTAGS:
-- here=`$(am__cd) $(top_builddir) && pwd` \
-- && $(am__cd) $(top_srcdir) \
-- && gtags -i $(GTAGS_ARGS) "$$here"
--
--distclean-tags:
-- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
--
--distdir: $(DISTFILES)
-- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-- list='$(DISTFILES)'; \
-- dist_files=`for file in $$list; do echo $$file; done | \
-- sed -e "s|^$$srcdirstrip/||;t" \
-- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-- case $$dist_files in \
-- */*) $(MKDIR_P) `echo "$$dist_files" | \
-- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-- sort -u` ;; \
-- esac; \
-- for file in $$dist_files; do \
-- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-- if test -d $$d/$$file; then \
-- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-- if test -d "$(distdir)/$$file"; then \
-- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-- fi; \
-- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-- fi; \
-- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-- else \
-- test -f "$(distdir)/$$file" \
-- || cp -p $$d/$$file "$(distdir)/$$file" \
-- || exit 1; \
-- fi; \
-- done
--check-am: all-am
--check: check-am
--all-am: Makefile $(LTLIBRARIES)
--installdirs:
-- for dir in "$(DESTDIR)$(pkgdir)"; do \
-- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
-- done
--install: install-am
--install-exec: install-exec-am
--install-data: install-data-am
--uninstall: uninstall-am
--
--install-am: all-am
-- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
--
--installcheck: installcheck-am
--install-strip:
-- if test -z '$(STRIP)'; then \
-- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-- install; \
-- else \
-- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-- fi
--mostlyclean-generic:
--
--clean-generic:
--
--distclean-generic:
-- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
--
--maintainer-clean-generic:
-- @echo "This command is intended for maintainers to use"
-- @echo "it deletes files that may require special tools to rebuild."
--clean: clean-am
--
--clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
-- clean-pkgLTLIBRARIES mostlyclean-am
--
--distclean: distclean-am
-- -rm -rf ./$(DEPDIR)
-- -rm -f Makefile
--distclean-am: clean-am distclean-compile distclean-generic \
-- distclean-tags
--
--dvi: dvi-am
--
--dvi-am:
--
--html: html-am
--
--html-am:
--
--info: info-am
--
--info-am:
--
--install-data-am: install-pkgLTLIBRARIES
--
--install-dvi: install-dvi-am
--
--install-dvi-am:
--
--install-exec-am:
--
--install-html: install-html-am
--
--install-html-am:
--
--install-info: install-info-am
--
--install-info-am:
--
--install-man:
--
--install-pdf: install-pdf-am
--
--install-pdf-am:
--
--install-ps: install-ps-am
--
--install-ps-am:
--
--installcheck-am:
--
--maintainer-clean: maintainer-clean-am
-- -rm -rf ./$(DEPDIR)
-- -rm -f Makefile
--maintainer-clean-am: distclean-am maintainer-clean-generic
--
--mostlyclean: mostlyclean-am
--
--mostlyclean-am: mostlyclean-compile mostlyclean-generic \
-- mostlyclean-libtool
--
--pdf: pdf-am
--
--pdf-am:
--
--ps: ps-am
--
--ps-am:
--
--uninstall-am: uninstall-pkgLTLIBRARIES
--
--.MAKE: install-am install-strip
--
--.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
-- clean-libtool clean-noinstLTLIBRARIES clean-pkgLTLIBRARIES \
-- ctags distclean distclean-compile distclean-generic \
-- distclean-libtool distclean-tags distdir dvi dvi-am html \
-- html-am info info-am install install-am install-data \
-- install-data-am install-dvi install-dvi-am install-exec \
-- install-exec-am install-html install-html-am install-info \
-- install-info-am install-man install-pdf install-pdf-am \
-- install-pkgLTLIBRARIES install-ps install-ps-am install-strip \
-- installcheck installcheck-am installdirs maintainer-clean \
-- maintainer-clean-generic mostlyclean mostlyclean-compile \
-- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-- tags uninstall uninstall-am uninstall-pkgLTLIBRARIES
--
--
--# Tell versions [3.59,3.63) of GNU make to not export all variables.
--# Otherwise a system limit (for SysV at least) may be exceeded.
--.NOEXPORT:
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/mxit/Makefile.mingw
---- pidgin-2.10.7/libpurple/protocols/mxit/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,92 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of libmxit
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = libmxit
--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)
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = actions.c \
-- aes.c \
-- chunk.c \
-- cipher.c \
-- filexfer.c \
-- formcmds.c \
-- http.c \
-- login.c \
-- markup.c \
-- multimx.c \
-- mxit.c \
-- profile.c \
-- protocol.c \
-- roster.c \
-- splashscreen.c \
-- voicevideo.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lintl \
-- -lws2_32 \
-- -lpurple
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll
--
--install: all $(DLL_INSTALL_DIR)
-- cp $(TARGET).dll $(DLL_INSTALL_DIR)
--
--$(OBJECTS): $(PURPLE_CONFIG_H)
--
--$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -f $(OBJECTS)
-- rm -f $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/markup.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/markup.c
---- pidgin-2.10.7/libpurple/protocols/mxit/markup.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/markup.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1231 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- convert between MXit and libPurple markup --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "purple.h"
--
--#include "protocol.h"
--#include "mxit.h"
--#include "markup.h"
--#include "chunk.h"
--#include "formcmds.h"
--#include "roster.h"
--
--
--/* define this to enable emoticon (markup) debugging */
--#undef MXIT_DEBUG_EMO
--/* define this to enable markup conversion debugging */
--#undef MXIT_DEBUG_MARKUP
--
--
--#define MXIT_FRAME_MAGIC "MXF\x01" /* mxit emoticon magic number */
--#define MXIT_MAX_EMO_ID 16 /* maximum emoticon ID length */
--#define COLORCODE_LEN 6 /* colour code ID length */
--
--
--/* HTML tag types */
--#define MXIT_TAG_COLOR 0x01 /* font color tag */
--#define MXIT_TAG_SIZE 0x02 /* font size tag */
--#define MXIT_MAX_MSG_TAGS 90 /* maximum tags per message (pigdin hack work around) */
--
--/*
-- * a HTML tag object
-- */
--struct tag {
-- char type;
-- char* value;
--};
--
--
--#define MXIT_VIBE_MSG_COLOR "#9933FF"
--#define MXIT_FAREWELL_MSG_COLOR "#949494"
--
--
--/* vibes */
--static const char* vibes[] = {
-- /* 0 */ N_( "Cool Vibrations" ),
-- /* 1 */ N_( "Purple Rain" ),
-- /* 2 */ N_( "Polite" ),
-- /* 3 */ N_( "Rock n Roll" ),
-- /* 4 */ N_( "Summer Slumber" ),
-- /* 5 */ N_( "Electric Razor" ),
-- /* 6 */ N_( "S.O.S" ),
-- /* 7 */ N_( "Jack Hammer" ),
-- /* 8 */ N_( "Bumble Bee" ),
-- /* 9 */ N_( "Ripple" )
--};
--
--
--
--#ifdef MXIT_DEBUG_EMO
--/*------------------------------------------------------------------------
-- * Dump a byte buffer as hexadecimal to the console for debugging purposes.
-- *
-- * @param buf The data to dump
-- * @param len The length of the data
-- */
--static void hex_dump( const char* buf, int len )
--{
-- char msg[256];
-- int pos;
-- int i;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "Dumping data (%i bytes)\n", len );
--
-- memset( msg, 0x00, sizeof( msg ) );
-- pos = 0;
--
-- for ( i = 0; i < len; i++ ) {
--
-- if ( pos == 0 )
-- pos += sprintf( &msg[pos], "%04i: ", i );
--
-- pos += sprintf( &msg[pos], "0x%02X ", (unsigned char) buf[i] );
--
-- if ( i % 16 == 15 ) {
-- pos += sprintf( &msg[pos], "\n" );
-- purple_debug_info( MXIT_PLUGIN_ID, msg );
-- pos = 0;
-- }
-- else if ( i % 16 == 7 )
-- pos += sprintf( &msg[pos], " " );
-- }
--
-- if ( pos > 0 ) {
-- pos += sprintf( &msg[pos], "\n" );
-- purple_debug_info( MXIT_PLUGIN_ID, msg );
-- pos = 0;
-- }
--}
--#endif
--
--
--/*------------------------------------------------------------------------
-- * Adds a link to a message
-- *
-- * @param mx The Markup message object
-- * @param replydata This is the what will be returned when the link gets clicked
-- * @param isStructured Indicates that the reply is a structured reply
-- * @param displaytext This is the text for the link which will be displayed in the UI
-- */
--void mxit_add_html_link( struct RXMsgData* mx, const char* replydata, gboolean isStructured, const char* displaytext )
--{
--#ifdef MXIT_LINK_CLICK
-- char retstr[256];
-- gchar* retstr64;
-- char link[256];
-- int len;
--
-- /*
-- * The link content is encoded as follows:
-- * MXIT_LINK_KEY | ACCOUNT_USER | ACCOUNT_PROTO | REPLY_TO | REPLY_FORMAT | REPLY_DATA
-- */
-- len = g_snprintf( retstr, sizeof( retstr ), "%s|%s|%s|%s|%i|%s",
-- MXIT_LINK_KEY,
-- purple_account_get_username( mx->session->acc ),
-- purple_account_get_protocol_id( mx->session->acc ),
-- mx->from,
-- isStructured ? 1 : 0,
-- replydata );
-- retstr64 = purple_base64_encode( (const unsigned char*) retstr, len );
-- g_snprintf( link, sizeof( link ), "%s%s", MXIT_LINK_PREFIX, retstr64 );
-- g_free( retstr64 );
--
-- g_string_append_printf( mx->msg, "<a href=\"%s\">%s</a>", link, displaytext );
--#else
-- g_string_append_printf( mx->msg, "<b>%s</b>", replydata );
--#endif
--}
--
--
--/*------------------------------------------------------------------------
-- * Extract an ASN.1 formatted length field from the data.
-- *
-- * @param data The source data
-- * @param size The extracted length
-- * @return The number of bytes extracted
-- */
--static unsigned int asn_getlength( const char* data, int* size )
--{
-- unsigned int len = 0;
-- unsigned char bytes;
-- unsigned char byte;
-- int i;
--
-- /* first byte specifies the number of bytes in the length */
-- bytes = ( data[0] & ~0x80 );
-- if ( bytes > sizeof( unsigned int ) ) {
-- /* file too big! */
-- return -1;
-- }
-- data++;
--
-- /* parse out the actual length */
-- for ( i = 0; i < bytes; i++ ) {
-- byte = data[i];
-- len <<= 8;
-- len += byte;
-- }
--
-- *size = len;
-- return bytes + 1;
--}
--
--
--/*------------------------------------------------------------------------
-- * Extract an ASN.1 formatted UTF-8 string field from the data.
-- *
-- * @param data The source data
-- * @param type Expected type of string
-- * @param utf8 The extracted string. Must be deallocated by caller.
-- * @return The number of bytes extracted
-- */
--static int asn_getUtf8( const char* data, char type, char** utf8 )
--{
-- int len;
--
-- /* validate the field type [1 byte] */
-- if ( data[0] != type ) {
-- /* this is not a utf-8 string! */
-- purple_debug_error( MXIT_PLUGIN_ID, "Invalid UTF-8 encoded string in ASN data (0x%02X)\n", (unsigned char) data[0] );
-- return -1;
-- }
--
-- len = data[1]; /* length field [1 bytes] */
-- *utf8 = g_malloc( len + 1 );
-- memcpy( *utf8, &data[2], len ); /* data field */
-- (*utf8)[len] = '\0';
--
-- return ( len + 2 );
--}
--
--
--/*------------------------------------------------------------------------
-- * Free data associated with a Markup message object.
-- *
-- * @param mx The Markup message object
-- */
--static void free_markupdata( struct RXMsgData* mx )
--{
-- if ( mx ) {
-- if ( mx->msg )
-- g_string_free( mx->msg, TRUE );
-- if ( mx->from )
-- g_free( mx->from );
-- g_free( mx );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Split the message into smaller messages and send them one at a time
-- * to pidgin to be displayed on the UI
-- *
-- * @param mx The received message object
-- */
--static void mxit_show_split_message( struct RXMsgData* mx )
--{
-- GString* msg = NULL;
-- char* ch = NULL;
-- int pos = 0;
-- int start = 0;
-- int l_nl = 0;
-- int l_sp = 0;
-- int l_gt = 0;
-- int stop = 0;
-- int tags = 0;
-- gboolean intag = FALSE;
--
-- /*
-- * awful hack to work around the awful hack in pidgin to work around GtkIMHtml's
-- * inefficient rendering of messages with lots of formatting changes.
-- * (reference: see the function pidgin_conv_write_conv() in gtkconv.c) the issue
-- * is that when you have more than 100 '<' characters in the message passed to
-- * pidgin, none of the markup (including links) are rendered and thus just dump
-- * all the text as is to the conversation window. this message dump is very
-- * confusing and makes it totally unusable. to work around this we will count
-- * the amount of tags and if its more than the pidgin threshold, we will just
-- * break the message up into smaller parts and send them separately to pidgin.
-- * to the user it will look like multiple messages, but at least he will be able
-- * to use and understand it.
-- */
--
-- ch = mx->msg->str;
-- pos = start;
-- while ( ch[pos] ) {
--
-- if ( ch[pos] == '<' ) {
-- tags++;
-- intag = TRUE;
-- }
-- else if ( ch[pos] == '\n' ) {
-- l_nl = pos;
-- }
-- else if ( ch[pos] == '>' ) {
-- l_gt = pos;
-- intag = FALSE;
-- }
-- else if ( ch[pos] == ' ' ) {
-- /* ignore spaces inside tags */
-- if ( !intag )
-- l_sp = pos;
-- }
-- else if ( ( ch[pos] == 'w' ) && ( pos + 4 < mx->msg->len ) && ( memcmp( &ch[pos], "www.", 4 ) == 0 ) ) {
-- tags += 2;
-- }
-- else if ( ( ch[pos] == 'h' ) && ( pos + 8 < mx->msg->len ) && ( memcmp( &ch[pos], "http://", 7 ) == 0 ) ) {
-- tags += 2;
-- }
--
-- if ( tags > MXIT_MAX_MSG_TAGS ) {
-- /* we have reached the maximum amount of tags pidgin (gtk) can handle per message.
-- so its time to send what we have and then start building a new message */
--
-- /* now find the right place to break the message */
-- if ( l_nl > start ) {
-- /* break at last '\n' char */
-- stop = l_nl;
-- ch[stop] = '\0';
-- msg = g_string_new( &ch[start] );
-- ch[stop] = '\n';
-- }
-- else if ( l_sp > start ) {
-- /* break at last ' ' char */
-- stop = l_sp;
-- ch[stop] = '\0';
-- msg = g_string_new( &ch[start] );
-- ch[stop] = ' ';
-- }
-- else {
-- /* break at the last '>' char */
-- char t;
-- stop = l_gt + 1;
-- t = ch[stop];
-- ch[stop] = '\0';
-- msg = g_string_new( &ch[start] );
-- ch[stop] = t;
-- stop--;
-- }
--
-- /* push message to pidgin */
-- serv_got_im( mx->session->con, mx->from, msg->str, mx->flags, mx->timestamp );
-- g_string_free( msg, TRUE );
-- msg = NULL;
--
-- /* next part need this flag set */
-- mx->flags |= PURPLE_MESSAGE_RAW;
--
-- tags = 0;
-- start = stop + 1;
-- pos = start;
-- }
-- else
-- pos++;
-- }
--
-- if ( start != pos ) {
-- /* send the last part of the message */
--
-- /* build the string */
-- ch[pos] = '\0';
-- msg = g_string_new( &ch[start] );
-- ch[pos] = '\n';
--
-- /* push message to pidgin */
-- serv_got_im( mx->session->con, mx->from, msg->str, mx->flags, mx->timestamp );
-- g_string_free( msg, TRUE );
-- msg = NULL;
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Insert custom emoticons and inline images into the message (if there
-- * are any), then give the message to the UI to display to the user.
-- *
-- * @param mx The received message object
-- */
--void mxit_show_message( struct RXMsgData* mx )
--{
-- char* pos;
-- int start;
-- unsigned int end;
-- int emo_ofs;
-- char* ii;
-- char tag[64];
-- int* img_id;
--
-- if ( mx->got_img ) {
-- /* search and replace all emoticon tags with proper image tags */
--
-- while ( ( pos = strstr( mx->msg->str, MXIT_II_TAG ) ) != NULL ) {
-- start = pos - mx->msg->str; /* offset at which MXIT_II_TAG starts */
-- emo_ofs = start + strlen( MXIT_II_TAG ); /* offset at which EMO's ID starts */
-- end = emo_ofs + 1; /* offset at which MXIT_II_TAG ends */
--
-- while ( ( end < mx->msg->len ) && ( mx->msg->str[end] != '>' ) )
-- end++;
--
-- if ( end == mx->msg->len ) /* end of emoticon tag not found */
-- break;
--
-- ii = g_strndup(&mx->msg->str[emo_ofs], end - emo_ofs);
--
-- /* remove inline image tag */
-- g_string_erase( mx->msg, start, ( end - start ) + 1 );
--
-- /* find the image entry */
-- img_id = (int*) g_hash_table_lookup( mx->session->iimages, ii );
-- if ( !img_id ) {
-- /* inline image not found, so we will just skip it */
-- purple_debug_error( MXIT_PLUGIN_ID, "inline image NOT found (%s)\n", ii );
-- }
-- else {
-- /* insert img tag */
-- g_snprintf( tag, sizeof( tag ), "<img id=\"%i\">", *img_id );
-- g_string_insert( mx->msg, start, tag );
-- }
--
-- g_free(ii);
-- }
-- }
--
--#ifdef MXIT_DEBUG_MARKUP
-- purple_debug_info( MXIT_PLUGIN_ID, "Markup RX (converted): '%s'\n", mx->msg->str );
--#endif
--
-- if ( mx->processed ) {
-- /* this message has already been taken care of, so just ignore it here */
-- }
-- else if ( mx->chatid < 0 ) {
-- /* normal chat message */
-- mxit_show_split_message( mx );
-- }
-- else {
-- /* this is a multimx message */
-- serv_got_chat_in( mx->session->con, mx->chatid, mx->from, mx->flags, mx->msg->str, mx->timestamp);
-- }
--
-- /* freeup resource */
-- free_markupdata( mx );
--}
--
--
--/*------------------------------------------------------------------------
-- * Extract the custom emoticon ID from the message.
-- *
-- * @param message The input data
-- * @param emid The extracted emoticon ID
-- */
--static void parse_emoticon_str( const char* message, char* emid )
--{
-- int i;
--
-- for ( i = 0; ( message[i] != '\0' && message[i] != '}' && i < MXIT_MAX_EMO_ID ); i++ ) {
-- emid[i] = message[i];
-- }
--
-- if ( message[i] == '\0' ) {
-- /* end of message reached, ignore the tag */
-- emid[0] = '\0';
-- }
-- else if ( i == MXIT_MAX_EMO_ID ) {
-- /* invalid tag length, ignore the tag */
-- emid[0] = '\0';
-- }
-- else
-- emid[i] = '\0';
--}
--
--
--/*------------------------------------------------------------------------
-- * Callback function invoked when a custom emoticon request to the WAP site completes.
-- *
-- * @param url_data
-- * @param user_data The Markup message object
-- * @param url_text The data returned from the WAP site
-- * @param len The length of the data returned
-- * @param error_message Descriptive error message
-- */
--static void emoticon_returned( PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message )
--{
-- struct RXMsgData* mx = (struct RXMsgData*) user_data;
-- const char* data = url_text;
-- unsigned int pos = 0;
-- char emo[16];
-- int id;
-- char* str;
-- int em_size = 0;
-- char* em_data = NULL;
-- char* em_id = NULL;
-- int* intptr = NULL;
-- int res;
--
--#ifdef MXIT_DEBUG_EMO
-- purple_debug_info( MXIT_PLUGIN_ID, "emoticon_returned\n" );
--#endif
--
-- if ( !url_text ) {
-- /* no reply from the WAP site */
-- purple_debug_error( MXIT_PLUGIN_ID, "Error contacting the MXit WAP site. Please try again later (emoticon).\n" );
-- goto done;
-- }
--
--#ifdef MXIT_DEBUG_EMO
-- hex_dump( data, len );
--#endif
--
-- /* parse out the emoticon */
-- pos = 0;
--
-- /* validate the binary data received from the wapsite */
-- if ( memcmp( MXIT_FRAME_MAGIC, &data[pos], strlen( MXIT_FRAME_MAGIC ) ) != 0 ) {
-- /* bad data, magic constant is wrong */
-- purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad magic)\n" );
-- goto done;
-- }
-- pos += strlen( MXIT_FRAME_MAGIC );
--
-- /* validate the image frame desc byte */
-- if ( data[pos] != '\x6F' ) {
-- /* bad frame desc */
-- purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad frame desc)\n" );
-- goto done;
-- }
-- pos++;
--
-- /* get the data length */
-- res = asn_getlength( &data[pos], &em_size );
-- if ( res <= 0 ) {
-- /* bad frame length */
-- purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad frame length)\n" );
-- goto done;
-- }
-- pos += res;
--#ifdef MXIT_DEBUG_EMO
-- purple_debug_info( MXIT_PLUGIN_ID, "read the length '%i'\n", em_size );
--#endif
--
-- /* utf-8 (emoticon name) */
-- res = asn_getUtf8( &data[pos], 0x0C, &str );
-- if ( res <= 0 ) {
-- /* bad utf-8 string */
-- purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad name string)\n" );
-- goto done;
-- }
-- pos += res;
--#ifdef MXIT_DEBUG_EMO
-- purple_debug_info( MXIT_PLUGIN_ID, "read the string '%s'\n", str );
--#endif
-- g_free( str );
-- str = NULL;
--
-- /* utf-8 (emoticon shortcut) */
-- res = asn_getUtf8( &data[pos], 0x81, &str );
-- if ( res <= 0 ) {
-- /* bad utf-8 string */
-- purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad shortcut string)\n" );
-- goto done;
-- }
-- pos += res;
--#ifdef MXIT_DEBUG_EMO
-- purple_debug_info( MXIT_PLUGIN_ID, "read the string '%s'\n", str );
--#endif
-- em_id = str;
--
-- /* validate the image data type */
-- if ( data[pos] != '\x82' ) {
-- /* bad frame desc */
-- purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad data type)\n" );
-- g_free( em_id );
-- goto done;
-- }
-- pos++;
--
-- /* get the data length */
-- res = asn_getlength( &data[pos], &em_size );
-- if ( res <= 0 ) {
-- /* bad frame length */
-- purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad data length)\n" );
-- g_free( em_id );
-- goto done;
-- }
-- pos += res;
--#ifdef MXIT_DEBUG_EMO
-- purple_debug_info( MXIT_PLUGIN_ID, "read the length '%i'\n", em_size );
--#endif
--
-- if ( g_hash_table_lookup( mx->session->iimages, em_id ) ) {
-- /* emoticon found in the table, so ignore this one */
-- goto done;
-- }
--
-- /* make a copy of the data */
-- em_data = g_malloc( em_size );
-- memcpy( em_data, &data[pos], em_size );
--
-- /* strip the mxit markup tags from the emoticon id */
-- if ( ( em_id[0] == '.' ) && ( em_id[1] == '{' ) ) {
-- parse_emoticon_str( &em_id[2], emo );
-- strcpy( em_id, emo );
-- }
--
-- /* we now have the emoticon, store it in the imagestore */
-- id = purple_imgstore_add_with_id( em_data, em_size, NULL );
--
-- /* map the mxit emoticon id to purple image id */
-- intptr = g_malloc( sizeof( int ) );
-- *intptr = id;
-- g_hash_table_insert( mx->session->iimages, em_id, intptr );
--
-- mx->flags |= PURPLE_MESSAGE_IMAGES;
--done:
-- mx->img_count--;
-- if ( ( mx->img_count == 0 ) && ( mx->converted ) ) {
-- /*
-- * this was the last outstanding emoticon for this message,
-- * so we can now display it to the user.
-- */
-- mxit_show_message( mx );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a request to the MXit WAP site to download the specified emoticon.
-- *
-- * @param mx The Markup message object
-- * @param id The ID for the emoticon
-- */
--static void emoticon_request( struct RXMsgData* mx, const char* id )
--{
-- PurpleUtilFetchUrlData* url_data;
-- const char* wapserver;
-- char* url;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "sending request for emoticon '%s'\n", id );
--
-- wapserver = purple_account_get_string( mx->session->acc, MXIT_CONFIG_WAPSERVER, DEFAULT_WAPSITE );
--
-- /* reference: "libpurple/util.h" */
-- url = g_strdup_printf( "%s/res/?type=emo&mlh=%i&sc=%s&ts=%li", wapserver, MXIT_EMOTICON_SIZE, id, time( NULL ) );
-- url_data = purple_util_fetch_url_request( url, TRUE, NULL, TRUE, NULL, FALSE, emoticon_returned, mx );
-- g_free( url );
--}
--
--
--/*------------------------------------------------------------------------
-- * Parse a Vibe command.
-- *
-- * @param mx The Markup message object
-- * @param message The message text (which contains the vibe)
-- * @return id The length of the message to skip
-- */
--static int mxit_parse_vibe( struct RXMsgData* mx, const char* message )
--{
-- int vibeid;
--
-- vibeid = message[2] - '0';
--
-- purple_debug_info( MXIT_PLUGIN_ID, "Vibe received (%i)\n", vibeid );
--
-- if ( vibeid > ( ARRAY_SIZE( vibes ) - 1 ) ) {
-- purple_debug_warning( MXIT_PLUGIN_ID, "Unsupported vibe received (%i)\n", vibeid );
-- /* unsupported vibe */
-- return 0;
-- }
--
-- g_string_append_printf( mx->msg, "<font color=\"%s\"><i>%s Vibe...</i></font>", MXIT_VIBE_MSG_COLOR, _( vibes[vibeid] ) );
-- return 2;
--}
--
--
--/*------------------------------------------------------------------------
-- * Extract the nickname from a chatroom message and display it nicely in
-- * libPurple-style (HTML) markup.
-- *
-- * @param mx The received message data object
-- * @param message The message text
-- * @return The length of the message to skip
-- */
--static int mxit_extract_chatroom_nick( struct RXMsgData* mx, char* message, int len, int msgflags )
--{
-- int i;
--
-- if ( message[0] == '<' ) {
-- /*
-- * The message MIGHT contains an embedded nickname. But we can't
-- * be sure unless we find the end-of-nickname sequence: (>\n)
-- * Search for it....
-- */
-- gboolean found = FALSE;
--
-- for ( i = 1; i < len; i++ ) {
-- if ( ( message[i] == '\n' ) && ( message[i-1] == '>' ) ) {
-- found = TRUE;
-- message[i-1] = '\0'; /* loose the '>' */
-- i++; /* and skip the new-line */
-- break;
-- }
-- }
--
-- if ( found ) {
-- gchar* nickname;
--
-- /*
-- * The message definitely had an embedded nickname - generate a marked-up
-- * message to be displayed.
-- */
-- nickname = g_markup_escape_text( &message[1], -1 );
--
-- /* Remove any MXit escaping from nickname ("\X" --> "X") */
-- if ( msgflags & CP_MSG_MARKUP ) {
-- int nicklen = strlen( nickname );
-- int j, k;
--
-- for ( j = 0, k = 0; j < nicklen; j++ ) {
-- if ( nickname[j] == '\\' )
-- j++;
--
-- nickname[k] = nickname[j];
-- k++;
-- }
--
-- nickname[k] = '\0'; /* terminate string */
-- }
--
-- /* add nickname within some BOLD markup to the new converted message */
-- g_string_append_printf( mx->msg, "<b>%s:</b> ", nickname );
--
-- /* free up the resources */
-- g_free( nickname );
--
-- return i;
-- }
-- }
--
-- return 0;
--}
--
--
--
--/*------------------------------------------------------------------------
-- * Convert a message containing MXit protocol markup to libPurple-style (HTML) markup.
-- *
-- * @param mx The received message data object
-- * @param message The message text
-- * @param len The length of the message
-- */
--void mxit_parse_markup( struct RXMsgData* mx, char* message, int len, short msgtype, int msgflags )
--{
-- char tmpstr1[128];
-- char* ch;
-- int i = 0;
--
-- /* tags */
-- gboolean tag_bold = FALSE;
-- gboolean tag_under = FALSE;
-- gboolean tag_italic = FALSE;
-- int font_size = 0;
--
--#ifdef MXIT_DEBUG_MARKUP
-- purple_debug_info( MXIT_PLUGIN_ID, "Markup RX (original): '%s'\n", message );
--#endif
--
--
-- /*
-- * supported MXit markup:
-- * '*' bold
-- * '_' underline
-- * '/' italics
-- * '$' highlight text
-- * '.+' inc font size
-- * '.-' dec font size
-- * '#XXXXXX' foreground color
-- * '.{XX}' custom emoticon
-- * '\' escape the following character
-- * '::' MXit commands
-- */
--
--
-- if ( is_mxit_chatroom_contact( mx->session, mx->from ) ) {
-- /* chatroom message, so we need to extract and skip the sender's nickname
-- * which is embedded inside the message */
-- i = mxit_extract_chatroom_nick( mx, message, len, msgflags );
-- }
--
-- /* run through the message and check for custom emoticons and markup */
-- for ( ; i < len; i++ ) {
-- switch ( message[i] ) {
--
--
-- /* mxit markup parsing */
-- case '*' :
-- if ( !( msgflags & CP_MSG_MARKUP ) ) {
-- g_string_append_c( mx->msg, message[i] );
-- break;
-- }
--
-- /* bold markup */
-- if ( !tag_bold )
-- g_string_append( mx->msg, "<b>" );
-- else
-- g_string_append( mx->msg, "</b>" );
-- tag_bold = !tag_bold;
-- break;
-- case '_' :
-- if ( !( msgflags & CP_MSG_MARKUP ) ) {
-- g_string_append_c( mx->msg, message[i] );
-- break;
-- }
--
-- /* underscore markup */
-- if ( !tag_under )
-- g_string_append( mx->msg, "<u>" );
-- else
-- g_string_append( mx->msg, "</u>" );
-- tag_under = !tag_under;
-- break;
-- case '/' :
-- if ( !( msgflags & CP_MSG_MARKUP ) ) {
-- g_string_append_c( mx->msg, message[i] );
-- break;
-- }
--
-- /* italics markup */
-- if ( !tag_italic )
-- g_string_append( mx->msg, "<i>" );
-- else
-- g_string_append( mx->msg, "</i>" );
-- tag_italic = !tag_italic;
-- break;
-- case '$' :
-- if ( !( msgflags & CP_MSG_MARKUP ) ) {
-- g_string_append_c( mx->msg, message[i] );
-- break;
-- }
-- else if ( i + 1 >= len ) {
-- /* message too short for complete link */
-- g_string_append_c( mx->msg, '$' );
-- break;
-- }
--
-- /* find the end tag */
-- ch = strstr( &message[i + 1], "$" );
-- if ( ch ) {
-- /* end found */
-- *ch = '\0';
-- mxit_add_html_link( mx, &message[i + 1], FALSE, &message[i + 1] );
-- *ch = '$';
-- i += ( ch - &message[i + 1] ) + 1;
-- }
-- else {
-- g_string_append_c( mx->msg, message[i] );
-- }
-- /* highlight text */
-- break;
-- case '#' :
-- if ( !( msgflags & CP_MSG_MARKUP ) ) {
-- g_string_append_c( mx->msg, message[i] );
-- break;
-- }
-- else if ( i + COLORCODE_LEN >= len ) {
-- /* message too short for complete colour code */
-- g_string_append_c( mx->msg, '#' );
-- break;
-- }
--
-- /* foreground (text) color */
-- memcpy( tmpstr1, &message[i + 1], COLORCODE_LEN );
-- tmpstr1[ COLORCODE_LEN ] = '\0'; /* terminate string */
-- if ( strcmp( tmpstr1, "??????" ) == 0 ) {
-- /* need to reset the font */
-- g_string_append( mx->msg, "</font>" );
-- i += COLORCODE_LEN;
-- }
-- else if ( strspn( tmpstr1, "0123456789abcdefABCDEF") == COLORCODE_LEN ) {
-- /* definitely a numeric colour code */
-- g_string_append_printf( mx->msg, "<font color=\"#%s\">", tmpstr1 );
-- i += COLORCODE_LEN;
-- }
-- else {
-- /* not valid colour markup */
-- g_string_append_c( mx->msg, '#' );
-- }
-- break;
-- case '.' :
-- if ( i + 1 >= len ) {
-- /* message too short */
-- g_string_append_c( mx->msg, '.' );
-- break;
-- }
--
-- if ( ( msgflags & CP_MSG_EMOTICON ) && ( message[i+1] == '{' ) ) {
-- /* custom emoticon */
-- if ( i + 2 >= len ) {
-- /* message too short */
-- g_string_append_c( mx->msg, '.' );
-- break;
-- }
--
-- parse_emoticon_str( &message[i+2], tmpstr1 );
-- if ( tmpstr1[0] != '\0' ) {
-- mx->got_img = TRUE;
--
-- if ( g_hash_table_lookup( mx->session->iimages, tmpstr1 ) ) {
-- /* emoticon found in the cache, so we do not have to request it from the WAPsite */
-- }
-- else {
-- /* request emoticon from the WAPsite */
-- mx->img_count++;
-- emoticon_request( mx, tmpstr1 );
-- }
--
-- g_string_append_printf( mx->msg, MXIT_II_TAG"%s>", tmpstr1 );
-- i += strlen( tmpstr1 ) + 2;
-- }
-- else
-- g_string_append_c( mx->msg, '.' );
-- }
-- else if ( ( msgflags & CP_MSG_MARKUP ) && ( message[i+1] == '+' ) ) {
-- /* increment text size */
-- font_size++;
-- g_string_append_printf( mx->msg, "<font size=\"%+i\">", font_size );
-- i++;
-- }
-- else if ( ( msgflags & CP_MSG_MARKUP ) && ( message[i+1] == '-' ) ) {
-- /* decrement text size */
-- font_size--;
-- g_string_append_printf( mx->msg, "<font size=\"%+i\">", font_size );
-- i++;
-- }
-- else
-- g_string_append_c( mx->msg, '.' );
--
-- break;
-- case '\\' :
-- if ( i + 1 >= len ) {
-- /* message too short for an escaped character */
-- g_string_append_c( mx->msg, '\\' );
-- }
-- else {
-- /* ignore the next character, because its been escaped */
-- g_string_append_c( mx->msg, message[i + 1] );
-- i++;
-- }
-- break;
--
--
-- /* command parsing */
-- case ':' :
-- if ( i + 1 >= len ) {
-- /* message too short */
-- g_string_append_c( mx->msg, ':' );
-- break;
-- }
--
-- if ( message[i+1] == '@' ) {
-- /* this is a vibe! */
-- int size;
--
-- if ( i + 2 >= len ) {
-- /* message too short */
-- g_string_append_c( mx->msg, message[i] );
-- break;
-- }
--
-- size = mxit_parse_vibe( mx, &message[i] );
-- if ( size == 0 )
-- g_string_append_c( mx->msg, message[i] );
-- else
-- i += size;
-- }
-- else if ( msgtype != CP_MSGTYPE_COMMAND ) {
-- /* this is not a command message */
-- g_string_append_c( mx->msg, message[i] );
-- }
-- else if ( message[i+1] == ':' ) {
-- /* parse out the command */
-- int size;
--
-- size = mxit_parse_command( mx, &message[i] );
-- if ( size == 0 )
-- g_string_append_c( mx->msg, ':' );
-- else
-- i += size;
-- }
-- else {
-- g_string_append_c( mx->msg, ':' );
-- }
-- break;
--
--
-- /* these aren't MXit markup, but are interpreted by libPurple */
-- case '<' :
-- g_string_append( mx->msg, "&lt;" );
-- break;
-- case '>' :
-- g_string_append( mx->msg, "&gt;" );
-- break;
-- case '&' :
-- g_string_append( mx->msg, "&amp;" );
-- break;
-- case '"' :
-- g_string_append( mx->msg, "&quot;" );
-- break;
--
-- default :
-- /* text */
-- g_string_append_c( mx->msg, message[i] );
-- break;
-- }
-- }
--
-- if ( msgflags & CP_MSG_FAREWELL ) {
-- /* this is a farewell message */
-- g_string_prepend( mx->msg, "<font color=\""MXIT_FAREWELL_MSG_COLOR"\"><i>" );
-- g_string_append( mx->msg, "</i></font>" );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Insert an inline image command.
-- *
-- * @param mx The message text as processed so far.
-- * @oaram id The imgstore ID of the inline image.
-- */
--static void inline_image_add( GString* mx, int id )
--{
-- PurpleStoredImage *image;
-- gconstpointer img_data;
-- gsize img_size;
-- gchar* enc;
--
-- image = purple_imgstore_find_by_id( id );
-- if ( image == NULL )
-- return;
--
-- img_data = purple_imgstore_get_data( image );
-- img_size = purple_imgstore_get_size( image );
--
-- enc = purple_base64_encode( img_data, img_size );
--
-- g_string_append( mx, "::op=img|dat=" );
-- g_string_append( mx, enc );
-- g_string_append_c( mx, ':' );
--
-- g_free( enc );
--}
--
--
--/*------------------------------------------------------------------------
-- * Convert libpurple (HTML) markup to MXit protocol markup (for sending to MXit).
-- * Any MXit markup codes in the original message also need to be escaped.
-- *
-- * @param message The message text containing libPurple (HTML) markup
-- * @return The message text containing MXit markup
-- */
--char* mxit_convert_markup_tx( const char* message, int* msgtype )
--{
-- GString* mx;
-- struct tag* tag;
-- GList* entry;
-- GList* tagstack = NULL;
-- char* reply;
-- char color[8];
-- int len = strlen ( message );
-- int i;
--
--#ifdef MXIT_DEBUG_MARKUP
-- purple_debug_info( MXIT_PLUGIN_ID, "Markup TX (original): '%s'\n", message );
--#endif
--
-- /*
-- * libPurple uses the following HTML markup codes:
-- * Bold: <b>...</b>
-- * Italics: <i>...</i>
-- * Underline: <u>...</u>
-- * Strikethrough: <s>...</s> (NO MXIT SUPPORT)
-- * Font size: <font size="">...</font>
-- * Font type: <font face="">...</font> (NO MXIT SUPPORT)
-- * Font colour: <font color=#">...</font>
-- * Links: <a href="">...</a>
-- * Newline: <br>
-- * Inline image: <IMG ID="">
-- * The following characters are also encoded:
-- * &amp; &quot; &lt; &gt;
-- */
--
-- /* new message data */
-- mx = g_string_sized_new( len );
--
-- /* run through the message and check for HTML markup */
-- for ( i = 0; i < len; i++ ) {
--
-- switch ( message[i] ) {
-- case '<' :
-- if ( purple_str_has_prefix( &message[i], "<b>" ) || purple_str_has_prefix( &message[i], "</b>" ) ) {
-- /* bold */
-- g_string_append_c( mx, '*' );
-- }
-- else if ( purple_str_has_prefix( &message[i], "<i>" ) || purple_str_has_prefix( &message[i], "</i>" ) ) {
-- /* italics */
-- g_string_append_c( mx, '/' );
-- }
-- else if ( purple_str_has_prefix( &message[i], "<u>" ) || purple_str_has_prefix( &message[i], "</u>" ) ) {
-- /* underline */
-- g_string_append_c( mx, '_' );
-- }
-- else if ( purple_str_has_prefix( &message[i], "<br>" ) ) {
-- /* newline */
-- g_string_append_c( mx, '\n' );
-- }
-- else if ( purple_str_has_prefix( &message[i], "<font size=" ) ) {
-- /* font size */
-- int fontsize;
--
-- tag = g_new0( struct tag, 1 );
-- tag->type = MXIT_TAG_SIZE;
-- tagstack = g_list_prepend( tagstack, tag );
-- // TODO: implement size control
-- if ( sscanf( &message[i+12], "%i", &fontsize ) ) {
-- purple_debug_info( MXIT_PLUGIN_ID, "Font size set to %i\n", fontsize );
-- }
-- }
-- else if ( purple_str_has_prefix( &message[i], "<font color=" ) ) {
-- /* font colour */
-- tag = g_new0( struct tag, 1 );
-- tag->type = MXIT_TAG_COLOR;
-- tagstack = g_list_append( tagstack, tag );
-- memset( color, 0x00, sizeof( color ) );
-- memcpy( color, &message[i + 13], 7 );
-- g_string_append( mx, color );
-- }
-- else if ( purple_str_has_prefix( &message[i], "</font>" ) ) {
-- /* end of font tag */
-- entry = g_list_last( tagstack );
-- if ( entry ) {
-- tag = entry->data;
-- if ( tag->type == MXIT_TAG_COLOR ) {
-- /* font color reset */
-- g_string_append( mx, "#??????" );
-- }
-- else if ( tag->type == MXIT_TAG_SIZE ) {
-- /* font size */
-- // TODO: implement size control
-- }
-- tagstack = g_list_remove( tagstack, tag );
-- g_free( tag );
-- }
-- }
-- else if ( purple_str_has_prefix( &message[i], "<IMG ID=" ) ) {
-- /* inline image */
-- int imgid;
--
-- if ( sscanf( &message[i+9], "%i", &imgid ) ) {
-- inline_image_add( mx, imgid );
-- *msgtype = CP_MSGTYPE_COMMAND; /* inline image must be sent as a MXit command */
-- }
-- }
--
-- /* skip to end of tag ('>') */
-- for ( i++; ( i < len ) && ( message[i] != '>' ) ; i++ );
--
-- break;
--
-- case '*' : /* MXit bold */
-- case '_' : /* MXit underline */
-- case '/' : /* MXit italic */
-- case '#' : /* MXit font color */
-- case '$' : /* MXit highlight text */
-- case '\\' : /* MXit escape backslash */
-- g_string_append( mx, "\\" ); /* escape character */
-- g_string_append_c( mx, message[i] ); /* character to escape */
-- break;
--
-- case '.' : /* might be a MXit font size change, or custom emoticon */
-- if ( i + 1 < len ) {
-- if ( ( message[i+1] == '+' ) || ( message[i+1] == '-' ) )
-- g_string_append( mx, "\\." ); /* escape "." */
-- else
-- g_string_append_c( mx, '.' );
-- }
-- else
-- g_string_append_c( mx, '.' );
-- break;
--
-- default:
-- g_string_append_c( mx, message[i] );
-- break;
-- }
-- }
--
-- /* unescape HTML entities to their literal characters (reference: "libpurple/utils.h") */
-- reply = purple_unescape_html( mx->str );
--
-- g_string_free( mx, TRUE );
--
--#ifdef MXIT_DEBUG_MARKUP
-- purple_debug_info( MXIT_PLUGIN_ID, "Markup TX (converted): '%s'\n", reply );
--#endif
--
-- return reply;
--}
--
--
--/*------------------------------------------------------------------------
-- * Free an emoticon entry.
-- *
-- * @param key MXit emoticon ID
-- * @param value Imagestore ID for emoticon
-- * @param user_data NULL (unused)
-- * @return TRUE
-- */
--static gboolean emoticon_entry_free( gpointer key, gpointer value, gpointer user_data )
--{
-- int* imgid = value;
--
-- /* key is a string */
-- g_free( key );
--
-- /* value is 'id' in imagestore */
-- purple_imgstore_unref_by_id( *imgid );
-- g_free( value );
--
-- return TRUE;
--}
--
--
--/*------------------------------------------------------------------------
-- * Free all entries in the emoticon cache.
-- *
-- * @param session The MXit session object
-- */
--void mxit_free_emoticon_cache( struct MXitSession* session )
--{
-- g_hash_table_foreach_remove( session->iimages, emoticon_entry_free, NULL );
-- g_hash_table_destroy ( session->iimages );
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/markup.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/markup.h
---- pidgin-2.10.7/libpurple/protocols/mxit/markup.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/markup.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,40 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- convert between MXit and libPurple markup --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MXIT_MARKUP_H_
--#define _MXIT_MARKUP_H_
--
--#define MXIT_II_TAG "<MXII=" /* inline image placeholder string */
--
--
--void mxit_parse_markup( struct RXMsgData* mx, char* message, int len, short msgtype, int msgflags );
--char* mxit_convert_markup_tx( const char* message, int* msgtype );
--void mxit_add_html_link( struct RXMsgData* mx, const char* replydata, gboolean isStructured, const char* displaytext );
--void mxit_show_message( struct RXMsgData* mx );
--
--void mxit_free_emoticon_cache( struct MXitSession* session );
--
--
--#endif /* _MXIT_MARKUP_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/multimx.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/multimx.c
---- pidgin-2.10.7/libpurple/protocols/mxit/multimx.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/multimx.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,650 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- MultiMx GroupChat --
-- *
-- * Andrew Victor <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "purple.h"
--#include "prpl.h"
--
--#include "protocol.h"
--#include "mxit.h"
--#include "multimx.h"
--#include "markup.h"
--
--
--#if 0
--static void multimx_dump(struct multimx* multimx)
--{
-- purple_debug_info(MXIT_PLUGIN_ID, "MultiMX:\n");
-- purple_debug_info(MXIT_PLUGIN_ID, " Chat ID: %i\n", multimx->chatid);
-- purple_debug_info(MXIT_PLUGIN_ID, " Username: %s\n", multimx->roomid);
-- purple_debug_info(MXIT_PLUGIN_ID, " Alias: %s\n", multimx->roomname);
-- purple_debug_info(MXIT_PLUGIN_ID, " State: %i\n", multimx->state);
--}
--#endif
--
--
--/*------------------------------------------------------------------------
-- * Find a MultiMx session based on libpurple chatID.
-- *
-- * @param session The MXit session object
-- * @param id The libpurple group-chat ID
-- * @return The MultiMX room object (or NULL if not found)
-- */
--static struct multimx* find_room_by_id(struct MXitSession* session, int id)
--{
-- GList* x = session->rooms;
--
-- while (x != NULL) {
-- struct multimx* multimx = (struct multimx *) x->data;
--
-- if (multimx->chatid == id)
-- return multimx;
--
-- x = g_list_next(x);
-- }
--
-- return NULL;
--}
--
--
--/*------------------------------------------------------------------------
-- * Find a MultiMx session based on Alias
-- *
-- * @param session The MXit session object
-- * @param roomname The UI room-name
-- * @return The MultiMX room object (or NULL if not found)
-- */
--static struct multimx* find_room_by_alias(struct MXitSession* session, const char* roomname)
--{
-- GList* x = session->rooms;
--
-- while (x != NULL) {
-- struct multimx* multimx = (struct multimx *) x->data;
--
-- if (!strcmp(multimx->roomname, roomname))
-- return multimx;
--
-- x = g_list_next(x);
-- }
--
-- return NULL;
--}
--
--
--/*------------------------------------------------------------------------
-- * Find a MultiMx session based on Username (MXit RoomId)
-- *
-- * @param session The MXit session object
-- * @param username The MXit RoomID (MultiMX contact username)
-- * @return The MultiMX room object (or NULL if not found)
-- */
--static struct multimx* find_room_by_username(struct MXitSession* session, const char* username)
--{
-- GList* x = session->rooms;
--
-- while (x != NULL) {
-- struct multimx* multimx = (struct multimx *) x->data;
--
-- if (!strcmp(multimx->roomid, username))
-- return multimx;
--
-- x = g_list_next(x);
-- }
--
-- return NULL;
--}
--
--
--/*------------------------------------------------------------------------
-- * Create a GroupChat room, and add to list of rooms.
-- *
-- * @param session The MXit session object
-- * @param roomid The MXit RoomID (MultiMX contact username)
-- * @param roomname The UI room-name
-- * @param state The initial state of the room (see multimx.h)
-- * @return The MultiMX room object
-- */
--static struct multimx* room_create(struct MXitSession* session, const char* roomid, const char* roomname, short state)
--{
-- struct multimx* multimx = NULL;
-- static int groupchatID = 1;
--
-- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat create - roomid='%s' roomname='%s'\n", roomid, roomname);
--
-- /* Create a new GroupChat */
-- multimx = g_new0(struct multimx, 1);
--
-- /* Initialize groupchat */
-- g_strlcpy(multimx->roomid, roomid, sizeof(multimx->roomid));
-- g_strlcpy(multimx->roomname, roomname, sizeof(multimx->roomname));
-- multimx->chatid = groupchatID++;
-- multimx->state = state;
--
-- /* determine our nickname (from profile) */
-- if (session->profile && (session->profile->nickname[0] != '\0'))
-- multimx->nickname = g_strdup(session->profile->nickname);
--
-- /* Add to GroupChat list */
-- session->rooms = g_list_append(session->rooms, multimx);
--
-- return multimx;
--}
--
--
--/*------------------------------------------------------------------------
-- * Free the Groupchat room.
-- *
-- * @param session The MXit session object
-- * @param multimx The MultiMX room object to deallocate
-- */
--static void room_remove(struct MXitSession* session, struct multimx* multimx)
--{
-- /* Remove from GroupChat list */
-- session->rooms = g_list_remove(session->rooms, multimx);
--
-- /* free nickname */
-- if (multimx->nickname)
-- g_free(multimx->nickname);
--
-- /* Deallocate it */
-- g_free (multimx);
-- multimx = NULL;
--}
--
--
--/*------------------------------------------------------------------------
-- * Another user has join the GroupChat, add them to the member-list.
-- *
-- * @param convo The Conversation object
-- * @param nickname The nickname of the user who joined the room
-- */
--static void member_added(PurpleConversation* convo, const char* nickname)
--{
-- purple_debug_info(MXIT_PLUGIN_ID, "member_added: '%s'\n", nickname);
--
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), nickname, NULL, PURPLE_CBFLAGS_NONE, TRUE);
--}
--
--
--/*------------------------------------------------------------------------
-- * Another user has left the GroupChat, remove them from the member-list.
-- *
-- * @param convo The Conversation object
-- * @param nickname The nickname of the user who left the room
-- */
--static void member_removed(PurpleConversation* convo, const char* nickname)
--{
-- purple_debug_info(MXIT_PLUGIN_ID, "member_removed: '%s'\n", nickname);
--
-- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), nickname, NULL);
--}
--
--
--/*------------------------------------------------------------------------
-- * A user was kicked from the GroupChat, remove them from the member-list.
-- *
-- * @param convo The Conversation object
-- * @param nickname The nickname of the user who was kicked
-- */
--static void member_kicked(PurpleConversation* convo, const char* nickname)
--{
-- purple_debug_info(MXIT_PLUGIN_ID, "member_kicked: '%s'\n", nickname);
--
-- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), nickname, _("was kicked"));
--}
--
--
--/*------------------------------------------------------------------------
-- * You were kicked from the GroupChat.
-- *
-- * @param convo The Conversation object
-- * @param session The MXit session object
-- * @param multimx The MultiMX room object
-- */
--static void you_kicked(PurpleConversation* convo, struct MXitSession* session, struct multimx* multimx)
--{
-- purple_debug_info(MXIT_PLUGIN_ID, "you_kicked\n");
--
-- purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "MXit", _("You have been kicked from this MultiMX."), PURPLE_MESSAGE_SYSTEM, time(NULL));
-- purple_conv_chat_clear_users(PURPLE_CONV_CHAT(convo));
-- serv_got_chat_left(session->con, multimx->chatid);
--}
--
--
--/*------------------------------------------------------------------------
-- * Update the full GroupChat member list.
-- *
-- * @param convo The Conversation object
-- * @param data The nicknames of the users in the room (separated by \n)
-- */
--static void member_update(PurpleConversation* convo, char* data)
--{
-- gchar** userlist;
-- int i = 0;
--
-- purple_debug_info(MXIT_PLUGIN_ID, "member_update: '%s'\n", data);
--
-- /* Clear list */
-- purple_conv_chat_clear_users(PURPLE_CONV_CHAT(convo));
--
-- /* Add each member */
-- data = g_strstrip(data); /* string leading & trailing whitespace */
-- userlist = g_strsplit(data, "\n", 0); /* tokenize string */
-- while (userlist[i] != NULL) {
-- purple_debug_info(MXIT_PLUGIN_ID, "member_update - adding: '%s'\n", userlist[i]);
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), userlist[i], NULL, PURPLE_CBFLAGS_NONE, FALSE);
-- i++;
-- }
-- g_strfreev(userlist);
--}
--
--
--/* -------------------------------------------------------------------------------------------------
-- * Calls from MXit Protocol layer
-- * ------------------------------------------------------------------------------------------------- */
--
--/*------------------------------------------------------------------------
-- * Received a Subscription Request to a MultiMX room.
-- *
-- * @param session The MXit session object
-- * @param contact The invited MultiMX room's contact information
-- * @param creator The nickname of the room's creator / invitor
-- */
--void multimx_invite(struct MXitSession* session, struct contact* contact, const char* creator)
--{
-- GHashTable *components;
-- struct multimx* multimx = NULL;
--
-- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat invite to '%s' (roomid='%s') by '%s'\n", contact->alias, contact->username, creator);
--
-- /* Check if the room already exists (ie, already joined or invite pending) */
-- if (find_room_by_username(session, contact->username) != NULL)
-- return;
--
-- /* Create a new room */
-- multimx = room_create(session, contact->username, contact->alias, STATE_INVITED);
--
-- components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-- g_hash_table_insert(components, g_strdup("room"), g_strdup(contact->alias));
--
-- /* Call libpurple - will trigger either 'mxit_chat_join' or 'mxit_chat_reject' */
-- serv_got_chat_invite(session->con, contact->alias, creator, NULL, components);
--}
--
--
--/*------------------------------------------------------------------------
-- * MultiMX room has been added to the roster.
-- *
-- * @param session The MXit session object
-- * @param contact The MultiMX room's contact information
-- */
--void multimx_created(struct MXitSession* session, struct contact* contact)
--{
-- PurpleConnection *gc = session->con;
-- struct multimx* multimx = NULL;
--
-- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat '%s' created as '%s'\n", contact->alias, contact->username);
--
-- /* Find matching MultiMX group */
-- multimx = find_room_by_username(session, contact->username);
-- if (multimx == NULL) {
-- multimx = room_create(session, contact->username, contact->alias, TRUE);
-- }
-- else if (multimx->state == STATE_INVITED) {
-- /* After successfully accepting an invitation */
-- multimx->state = STATE_JOINED;
-- }
--
-- /* Call libpurple - will trigger 'mxit_chat_join' */
-- serv_got_joined_chat(gc, multimx->chatid, multimx->roomname);
--
-- /* Send ".list" command to GroupChat server to retrieve current member-list */
-- mxit_send_message(session, multimx->roomid, ".list", FALSE, FALSE);
--}
--
--
--/*------------------------------------------------------------------------
-- * Is this username a MultiMX contact?
-- *
-- * @param session The MXit session object
-- * @param username The username of the contact
-- * @return TRUE if this contacts matches the RoomID of a MultiMX room.
-- */
--gboolean is_multimx_contact(struct MXitSession* session, const char* username)
--{
-- /* Check for username in list of open rooms */
-- return (find_room_by_username(session, username) != NULL);
--}
--
--
--/*------------------------------------------------------------------------
-- * Received a message from a MultiMX room.
-- *
-- */
--void multimx_message_received(struct RXMsgData* mx, char* msg, int msglen, short msgtype, int msgflags)
--{
-- struct multimx* multimx = NULL;
--
-- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat message received: %s\n", msg);
--
-- /* Find matching multimx group */
-- multimx = find_room_by_username(mx->session, mx->from);
-- if (multimx == NULL) {
-- purple_debug_error(MXIT_PLUGIN_ID, "Groupchat '%s' not found\n", mx->from);
-- return;
-- }
--
-- /* Determine if system message or a message from a contact */
-- if (msg[0] == '<') {
-- /* Message contains embedded nickname - must be from contact */
-- unsigned int i;
--
-- for (i = 1; i < strlen(msg); i++) { /* search for end of nickname */
-- if (msg[i] == '>') {
-- msg[i] = '\0';
-- g_free(mx->from);
-- mx->from = g_strdup(&msg[1]);
-- msg = &msg[i+2]; /* skip '>' and newline */
-- break;
-- }
-- }
--
-- /* now do markup processing on the message */
-- mx->chatid = multimx->chatid;
-- mxit_parse_markup(mx, msg, strlen(msg), msgtype, msgflags);
-- }
-- else {
-- /* Must be a service message */
-- char* ofs;
--
-- PurpleConversation* convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, multimx->roomname, mx->session->acc);
-- if (convo == NULL) {
-- purple_debug_error(MXIT_PLUGIN_ID, "Conversation '%s' not found\n", multimx->roomname);
-- return;
-- }
--
-- /* Determine if somebody has joined or left - update member-list */
-- if ((ofs = strstr(msg, " has joined")) != NULL) {
-- /* Somebody has joined */
-- *ofs = '\0';
-- member_added(convo, msg);
-- mx->processed = TRUE;
-- }
-- else if ((ofs = strstr(msg, " has left")) != NULL) {
-- /* Somebody has left */
-- *ofs = '\0';
-- member_removed(convo, msg);
-- mx->processed = TRUE;
-- }
-- else if ((ofs = strstr(msg, " has been kicked")) != NULL) {
-- /* Somebody has been kicked */
-- *ofs = '\0';
-- member_kicked(convo, msg);
-- mx->processed = TRUE;
-- }
-- else if (strcmp(msg, "You have been kicked.") == 0) {
-- /* You have been kicked */
-- you_kicked(convo, mx->session, multimx);
-- mx->processed = TRUE;
-- }
-- else if (g_str_has_prefix(msg, "The following users are in this MultiMx:") == TRUE) {
-- member_update(convo, msg + strlen("The following users are in this MultiMx:") + 1);
-- mx->processed = TRUE;
-- }
-- else {
-- /* Display server message in chat window */
-- serv_got_chat_in(mx->session->con, multimx->chatid, "MXit", PURPLE_MESSAGE_SYSTEM, msg, mx->timestamp);
-- mx->processed = TRUE;
-- }
-- }
--}
--
--
--
--/* -------------------------------------------------------------------------------------------------
-- * Callbacks from libpurple
-- * ------------------------------------------------------------------------------------------------- */
--
--/*------------------------------------------------------------------------
-- * User has selected "Add Chat" from the main menu.
-- *
-- * @param gc The connection object
-- * @return A list of chat configuration values
-- */
--GList* mxit_chat_info(PurpleConnection *gc)
--{
-- GList *m = NULL;
-- struct proto_chat_entry *pce;
--
-- /* Configuration option: Room Name */
-- pce = g_new0(struct proto_chat_entry, 1);
-- pce->label = _( "_Room Name:" );
-- pce->identifier = "room";
-- pce->required = TRUE;
-- m = g_list_append(m, pce);
--
-- return m;
--}
--
--
--/*------------------------------------------------------------------------
-- * User has joined a chatroom, either because they are creating it or they
-- * accepted an invite.
-- *
-- * @param gc The connection object
-- * @param components The list of chat configuration values
-- */
--void mxit_chat_join(PurpleConnection *gc, GHashTable *components)
--{
-- struct MXitSession* session = purple_connection_get_protocol_data(gc);
-- const char* roomname = NULL;
-- struct multimx* multimx = NULL;
--
-- purple_debug_info(MXIT_PLUGIN_ID, "mxit_chat_join\n");
--
-- /* Determine if groupchat already exists */
-- roomname = g_hash_table_lookup(components, "room");
-- multimx = find_room_by_alias(session, roomname);
--
-- if (multimx != NULL) {
-- /* The room information already exists */
--
-- if (multimx->state == STATE_INVITED) {
-- /* Invite is pending */
-- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat %i accept sent\n", multimx->chatid);
--
-- /* Send Subscription Accept to MXit */
-- mxit_send_allow_sub(session, multimx->roomid, multimx->roomname);
-- }
-- else {
-- /* Join existing room */
-- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat %i rejoined\n", multimx->chatid);
--
-- serv_got_joined_chat(gc, multimx->chatid, multimx->roomname);
-- }
-- }
-- else {
-- /* Send Groupchat Create to MXit */
-- mxit_send_groupchat_create(session, roomname, 0, NULL);
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * User has rejected an invite to join a MultiMX room.
-- *
-- * @param gc The connection object
-- * @param components The list of chat configuration values
-- */
--void mxit_chat_reject(PurpleConnection *gc, GHashTable* components)
--{
-- struct MXitSession* session = purple_connection_get_protocol_data(gc);
-- const char* roomname = NULL;
-- struct multimx* multimx = NULL;
--
-- purple_debug_info(MXIT_PLUGIN_ID, "mxit_chat_reject\n");
--
-- roomname = g_hash_table_lookup(components, "room");
-- multimx = find_room_by_alias(session, roomname);
-- if (multimx == NULL) {
-- purple_debug_error(MXIT_PLUGIN_ID, "Groupchat '%s' not found\n", roomname);
-- return;
-- }
--
-- /* Send Subscription Reject to MXit */
-- mxit_send_deny_sub(session, multimx->roomid, NULL);
--
-- /* Remove from our list of rooms */
-- room_remove(session, multimx);
--}
--
--
--/*------------------------------------------------------------------------
-- * Return name of chatroom (on mouse hover)
-- *
-- * @param components The list of chat configuration values.
-- * @return The name of the chat room
-- */
--char* mxit_chat_name(GHashTable *components)
--{
-- return g_strdup(g_hash_table_lookup(components, "room"));
--}
--
--
--/*------------------------------------------------------------------------
-- * User has selected to invite somebody to a chatroom.
-- *
-- * @param gc The connection object
-- * @param id The chat room ID
-- * @param msg The invitation message entered by the user
-- * @param name The username of the person to invite
-- */
--void mxit_chat_invite(PurpleConnection *gc, int id, const char *msg, const char *username)
--{
-- struct MXitSession* session = purple_connection_get_protocol_data(gc);
-- struct multimx* multimx = NULL;
-- PurpleBuddy* buddy;
-- PurpleConversation *convo;
-- char* tmp;
--
-- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat invite to '%s'\n", username);
--
-- /* Find matching MultiMX group */
-- multimx = find_room_by_id(session, id);
-- if (multimx == NULL) {
-- purple_debug_error(MXIT_PLUGIN_ID, "Could not find groupchat %i\n", id);
-- return;
-- }
--
-- /* Send invite to MXit */
-- mxit_send_groupchat_invite(session, multimx->roomid, 1, &username);
--
-- /* Find the buddy information for this contact (reference: "libpurple/blist.h") */
-- buddy = purple_find_buddy(session->acc, username);
-- if (!buddy) {
-- purple_debug_warning(MXIT_PLUGIN_ID, "mxit_chat_invite: unable to find the buddy '%s'\n", username);
-- return;
-- }
--
-- convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, multimx->roomname, session->acc);
-- if (convo == NULL) {
-- purple_debug_error(MXIT_PLUGIN_ID, "Conversation '%s' not found\n", multimx->roomname);
-- return;
-- }
--
-- /* Display system message in chat window */
-- tmp = g_strdup_printf("%s: %s", _("You have invited"), purple_buddy_get_alias(buddy));
-- purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "MXit", tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));
-- g_free(tmp);
--}
--
--
--/*------------------------------------------------------------------------
-- * User as closed the chat window, and the chatroom is not marked as persistent.
-- *
-- * @param gc The connection object
-- * @param id The chat room ID
-- */
--void mxit_chat_leave(PurpleConnection *gc, int id)
--{
-- struct MXitSession* session = purple_connection_get_protocol_data(gc);
-- struct multimx* multimx = NULL;
--
-- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat %i leave\n", id);
--
-- /* Find matching multimx group */
-- multimx = find_room_by_id(session, id);
-- if (multimx == NULL) {
-- purple_debug_error(MXIT_PLUGIN_ID, "Could not find groupchat %i\n", id);
-- return;
-- }
--
-- /* Send Remove Groupchat to MXit */
-- mxit_send_remove(session, multimx->roomid);
--
-- /* Remove from our list of rooms */
-- room_remove(session, multimx);
--}
--
--
--/*------------------------------------------------------------------------
-- * User has entered a message in a chatroom window, send it to the MXit server.
-- *
-- * @param gc The connection object
-- * @param id The chat room ID
-- * @param message The sent message data
-- * @param flags The message flags
-- * @return Indicates success / failure
-- */
--int mxit_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)
--{
-- struct MXitSession* session = purple_connection_get_protocol_data(gc);
-- struct multimx* multimx = NULL;
-- const char* nickname;
--
-- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat %i message send: '%s'\n", id, message);
--
-- /* Find matching MultiMX group */
-- multimx = find_room_by_id(session, id);
-- if (multimx == NULL) {
-- purple_debug_error(MXIT_PLUGIN_ID, "Could not find groupchat %i\n", id);
-- return -1;
-- }
--
-- /* Send packet to MXit */
-- mxit_send_message(session, multimx->roomid, message, TRUE, FALSE);
--
-- /* Determine our nickname to display */
-- if (multimx->nickname)
-- nickname = multimx->nickname;
-- else
-- nickname = purple_account_get_alias(purple_connection_get_account(gc)); /* local alias */
--
-- /* Display message in chat window */
-- serv_got_chat_in(gc, id, nickname, flags, message, time(NULL));
--
-- return 0;
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/multimx.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/multimx.h
---- pidgin-2.10.7/libpurple/protocols/mxit/multimx.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/multimx.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,105 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- MultiMx GroupChat --
-- *
-- * Andrew Victor <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MXIT_MULTIMX_H_
--#define _MXIT_MULTIMX_H_
--
--#include "roster.h"
--
--
--/* GroupChat Room state */
--#define STATE_CREATOR 0
--#define STATE_INVITED 1
--#define STATE_JOINED 2
--
--/*
-- * a MultiMX room
-- */
--struct multimx {
-- char roomname[MXIT_CP_MAX_ALIAS_LEN]; /* name of the room */
-- char roomid[MXIT_CP_MAX_JID_LEN]; /* internal JID for room */
-- int chatid; /* libpurple chat ID */
-- char* nickname; /* our nickname in the room */
-- short state; /* state */
--};
--
--
--/*
-- * Received a Subscription Request to a MultiMX room.
-- */
--void multimx_invite(struct MXitSession* session, struct contact* contact, const char* creator);
--
--/*
-- * MultiMX room has been added to the roster.
-- */
--void multimx_created(struct MXitSession* session, struct contact* contact);
--
--/*
-- * Is this username a MultiMX contact?
-- */
--gboolean is_multimx_contact(struct MXitSession* session, const char* username);
--
--/*
-- * Received a message from a MultiMX room.
-- */
--void multimx_message_received(struct RXMsgData* mx, char* message, int len, short msgtype, int msgflags);
--
--/*
-- * User has selected "Add Chat" from the main menu.
-- */
--GList* mxit_chat_info(PurpleConnection *gc);
--
--/*
-- * User has joined a chatroom, either because they are creating it or they accepted an invite.
-- */
--void mxit_chat_join(PurpleConnection *gc, GHashTable *data);
--
--/*
-- * User has rejected an invite to join a MultiMX room.
-- */
--void mxit_chat_reject(PurpleConnection *gc, GHashTable* components);
--
--/*
-- * Return name of chatroom (on mouse hover)
-- */
--char* mxit_chat_name(GHashTable *data);
--
--/*
-- * User has selected to invite somebody to a chatroom.
-- */
--void mxit_chat_invite(PurpleConnection *gc, int id, const char *msg, const char *name);
--
--/*
-- * User as closed the chat window, and the chatroom is not marked as persistent.
-- */
--void mxit_chat_leave(PurpleConnection *gc, int id);
--
--/*
-- * User has entered a message in a chatroom window, send it to the MXit server.
-- */
--int mxit_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags);
--
--
--#endif /* _MXIT_MULTIMX_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/mxit.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/mxit.c
---- pidgin-2.10.7/libpurple/protocols/mxit/mxit.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/mxit.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,868 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- MXit libPurple plugin API --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "purple.h"
--#include "notify.h"
--#include "plugin.h"
--#include "version.h"
--
--#include "mxit.h"
--#include "protocol.h"
--#include "login.h"
--#include "roster.h"
--#include "chunk.h"
--#include "filexfer.h"
--#include "actions.h"
--#include "multimx.h"
--#include "voicevideo.h"
--
--
--#ifdef MXIT_LINK_CLICK
--
--
--/* pidgin callback function pointers for URI click interception */
--static void *(*mxit_pidgin_uri_cb)(const char *uri);
--static PurpleNotifyUiOps* mxit_nots_override_original;
--static PurpleNotifyUiOps mxit_nots_override;
--static int not_link_ref_count = 0;
--
--
--/*------------------------------------------------------------------------
-- * Handle an URI clicked on the UI
-- *
-- * @param link the link name which has been clicked
-- */
--static void* mxit_link_click( const char* link64 )
--{
-- PurpleAccount* account;
-- PurpleConnection* gc;
-- gchar** parts = NULL;
-- gchar* link = NULL;
-- gsize len;
-- gboolean is_command = FALSE;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_link_click (%s)\n", link64 );
--
-- if ( g_ascii_strncasecmp( link64, MXIT_LINK_PREFIX, strlen( MXIT_LINK_PREFIX ) ) != 0 ) {
-- /* this is not for us */
-- goto skip;
-- }
--
-- /* decode the base64 payload */
-- link = (gchar*) purple_base64_decode( link64 + strlen( MXIT_LINK_PREFIX ), &len );
-- purple_debug_info( MXIT_PLUGIN_ID, "Clicked Link: '%s'\n", link );
--
-- parts = g_strsplit( link, "|", 6 );
--
-- /* check if this is a valid mxit link */
-- if ( ( !parts ) || ( !parts[0] ) || ( !parts[1] ) || ( !parts[2] ) || ( !parts[3] ) || ( !parts[4] ) || ( !parts[5] ) ) {
-- /* this is not for us */
-- goto skip;
-- }
-- else if ( g_ascii_strcasecmp( parts[0], MXIT_LINK_KEY ) != 0 ) {
-- /* this is not for us */
-- goto skip;
-- }
--
-- /* find the account */
-- account = purple_accounts_find( parts[1], parts[2] );
-- if ( !account )
-- goto skip;
-- gc = purple_account_get_connection( account );
-- if ( !gc )
-- goto skip;
--
-- /* determine if it's a command-response to send */
-- is_command = ( atoi( parts[4] ) == 1 );
--
-- /* send click message back to MXit */
-- mxit_send_message( purple_connection_get_protocol_data( gc ), parts[3], parts[5], FALSE, is_command );
--
-- g_free( link );
-- link = NULL;
-- g_strfreev( parts );
-- parts = NULL;
--
-- return (void*) link64;
--
--skip:
-- /* this is not an internal mxit link */
--
-- if ( link )
-- g_free( link );
-- link = NULL;
--
-- if ( parts )
-- g_strfreev( parts );
-- parts = NULL;
--
-- if ( mxit_pidgin_uri_cb )
-- return mxit_pidgin_uri_cb( link64 );
-- else
-- return (void*) link64;
--}
--
--
--/*------------------------------------------------------------------------
-- * Register MXit to receive URI click notifications from the UI
-- */
--void mxit_register_uri_handler(void)
--{
-- not_link_ref_count++;
-- if ( not_link_ref_count == 1 ) {
-- /* make copy of notifications */
-- mxit_nots_override_original = purple_notify_get_ui_ops();
-- memcpy( &mxit_nots_override, mxit_nots_override_original, sizeof( PurpleNotifyUiOps ) );
--
-- /* save previously configured callback function pointer */
-- mxit_pidgin_uri_cb = mxit_nots_override.notify_uri;
--
-- /* override the URI function call with MXit's own one */
-- mxit_nots_override.notify_uri = mxit_link_click;
-- purple_notify_set_ui_ops( &mxit_nots_override );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Unregister MXit from receiving URI click notifications from the UI
-- */
--static void mxit_unregister_uri_handler()
--{
-- not_link_ref_count--;
-- if ( not_link_ref_count == 0 ) {
-- /* restore the notifications to its original state */
-- purple_notify_set_ui_ops( mxit_nots_override_original );
-- }
--}
--
--#endif
--
--
--/*------------------------------------------------------------------------
-- * This gets called when a new chat conversation is opened by the user
-- *
-- * @param conv The conversation object
-- * @param session The MXit session object
-- */
--static void mxit_cb_chat_created( PurpleConversation* conv, struct MXitSession* session )
--{
-- PurpleConnection* gc;
-- struct contact* contact;
-- PurpleBuddy* buddy;
-- const char* who;
-- char* tmp;
--
-- gc = purple_conversation_get_gc( conv );
-- if ( session->con != gc ) {
-- /* not our conversation */
-- return;
-- }
-- else if ( purple_conversation_get_type( conv ) != PURPLE_CONV_TYPE_IM ) {
-- /* wrong type of conversation */
-- return;
-- }
--
-- /* get the contact name */
-- who = purple_conversation_get_name( conv );
-- if ( !who )
-- return;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "Conversation started with '%s'\n", who );
--
-- /* find the buddy object */
-- buddy = purple_find_buddy( session->acc, who );
-- if ( !buddy )
-- return;
--
-- contact = purple_buddy_get_protocol_data(buddy);
-- if ( !contact )
-- return;
--
-- /* we ignore all conversations with which we have chatted with in this session */
-- if ( find_active_chat( session->active_chats, who ) )
-- return;
--
-- /* determine if this buddy is a MXit service */
-- switch ( contact->type ) {
-- case MXIT_TYPE_BOT :
-- case MXIT_TYPE_CHATROOM :
-- case MXIT_TYPE_GALLERY :
-- case MXIT_TYPE_INFO :
-- tmp = g_strdup_printf("<font color=\"#999999\">%s</font>\n", _( "Loading menu..." ));
-- serv_got_im( session->con, who, tmp, PURPLE_MESSAGE_NOTIFY, time( NULL ) );
-- g_free(tmp);
-- mxit_send_message( session, who, " ", FALSE, FALSE );
-- default :
-- break;
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Enable some signals to handled by our plugin
-- *
-- * @param session The MXit session object
-- */
--void mxit_enable_signals( struct MXitSession* session )
--{
-- /* enable the signal when a new conversation is opened by the user */
-- purple_signal_connect_priority( purple_conversations_get_handle(), "conversation-created", session, PURPLE_CALLBACK( mxit_cb_chat_created ),
-- session, PURPLE_SIGNAL_PRIORITY_HIGHEST );
--}
--
--
--/*------------------------------------------------------------------------
-- * Disable some signals handled by our plugin
-- *
-- * @param session The MXit session object
-- */
--static void mxit_disable_signals( struct MXitSession* session )
--{
-- /* disable the signal when a new conversation is opened by the user */
-- purple_signal_disconnect( purple_conversations_get_handle(), "conversation-created", session, PURPLE_CALLBACK( mxit_cb_chat_created ) );
--}
--
--
--/*------------------------------------------------------------------------
-- * Return the base icon name.
-- *
-- * @param account The MXit account object
-- * @param buddy The buddy
-- * @return The icon name (excluding extension)
-- */
--static const char* mxit_list_icon( PurpleAccount* account, PurpleBuddy* buddy )
--{
-- return "mxit";
--}
--
--
--/*------------------------------------------------------------------------
-- * Return the emblem icon name.
-- *
-- * @param buddy The buddy
-- * @return The icon name (excluding extension)
-- */
--static const char* mxit_list_emblem( PurpleBuddy* buddy )
--{
-- struct contact* contact = purple_buddy_get_protocol_data(buddy);
--
-- if ( !contact )
-- return NULL;
--
-- /* subscription state is Pending, Rejected or Deleted */
-- if ( contact->subtype != MXIT_SUBTYPE_BOTH )
-- return "not-authorized";
--
-- switch ( contact-> type ) {
-- case MXIT_TYPE_JABBER : /* external contacts via MXit */
-- case MXIT_TYPE_MSN :
-- case MXIT_TYPE_YAHOO :
-- case MXIT_TYPE_ICQ :
-- case MXIT_TYPE_AIM :
-- case MXIT_TYPE_QQ :
-- case MXIT_TYPE_WV :
-- return "external";
--
-- case MXIT_TYPE_BOT : /* MXit services */
-- case MXIT_TYPE_GALLERY :
-- case MXIT_TYPE_INFO :
-- return "bot";
--
-- case MXIT_TYPE_CHATROOM : /* MXit group chat services */
-- case MXIT_TYPE_MULTIMX :
-- default:
-- return NULL;
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Return short string representing buddy's status for display on buddy list.
-- * Returns status message (if one is set), or otherwise the mood.
-- *
-- * @param buddy The buddy.
-- * @return The status text
-- */
--char* mxit_status_text( PurpleBuddy* buddy )
--{
-- char* text = NULL;
-- struct contact* contact = purple_buddy_get_protocol_data(buddy);
--
-- if ( !contact )
-- return NULL;
--
-- if ( contact->statusMsg ) /* status message */
-- return g_strdup( contact-> statusMsg );
-- else if ( contact->mood != MXIT_MOOD_NONE ) /* mood */
-- return g_strdup( mxit_convert_mood_to_name( contact->mood ) );
--
-- return text;
--}
--
--
--/*------------------------------------------------------------------------
-- * Return UI tooltip information for a buddy when hovering in buddy list.
-- *
-- * @param buddy The buddy
-- * @param info The tooltip info being returned
-- * @param full Return full or summarized information
-- */
--static void mxit_tooltip( PurpleBuddy* buddy, PurpleNotifyUserInfo* info, gboolean full )
--{
-- struct contact* contact = purple_buddy_get_protocol_data(buddy);
--
-- if ( !contact )
-- return;
--
-- /* status (reference: "libpurple/notify.h") */
-- if ( contact->presence != MXIT_PRESENCE_OFFLINE )
-- purple_notify_user_info_add_pair( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) );
--
-- /* status message */
-- if ( contact->statusMsg )
-- purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg );
--
-- /* mood */
-- if ( contact->mood != MXIT_MOOD_NONE )
-- purple_notify_user_info_add_pair( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) );
--
-- /* subscription type */
-- if ( contact->subtype != 0 )
-- purple_notify_user_info_add_pair( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) );
--
-- /* rejection message */
-- if ( ( contact->subtype == MXIT_SUBTYPE_REJECTED ) && ( contact->msg != NULL ) )
-- purple_notify_user_info_add_pair( info, _( "Rejection Message" ), contact->msg );
--}
--
--
--/*------------------------------------------------------------------------
-- * Initiate the logout sequence, close the connection and clear the session data.
-- *
-- * @param gc The connection object
-- */
--static void mxit_close( PurpleConnection* gc )
--{
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
--
-- /* disable signals */
-- mxit_disable_signals( session );
--
-- /* close the connection */
-- mxit_close_connection( session );
--
--#ifdef MXIT_LINK_CLICK
-- /* unregister for uri click notification */
-- mxit_unregister_uri_handler();
--#endif
--
-- purple_debug_info( MXIT_PLUGIN_ID, "Releasing the session object..\n" );
--
-- /* free the session memory */
-- g_free( session );
-- session = NULL;
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a message to a contact
-- *
-- * @param gc The connection object
-- * @param who The username of the recipient
-- * @param message The message text
-- * @param flags Message flags (defined in conversation.h)
-- * @return Positive value (success, and echo to conversation window)
-- Zero (success, no echo)
-- Negative value (error)
-- */
--static int mxit_send_im( PurpleConnection* gc, const char* who, const char* message, PurpleMessageFlags flags )
--{
-- purple_debug_info( MXIT_PLUGIN_ID, "Sending message '%s' to buddy '%s'\n", message, who );
--
-- mxit_send_message( gc->proto_data, who, message, TRUE, FALSE );
--
-- return 1; /* echo to conversation window */
--}
--
--
--/*------------------------------------------------------------------------
-- * The user changed their current presence state.
-- *
-- * @param account The MXit account object
-- * @param status The new status (libPurple status type)
-- */
--static void mxit_set_status( PurpleAccount* account, PurpleStatus* status )
--{
-- struct MXitSession* session = purple_account_get_connection( account )->proto_data;
-- const char* statusid;
-- int presence;
-- char* statusmsg1;
-- char* statusmsg2;
--
-- /* Handle mood changes */
-- if (purple_status_type_get_primitive(purple_status_get_type(status)) == PURPLE_STATUS_MOOD) {
-- const char* moodid = purple_status_get_attr_string( status, PURPLE_MOOD_NAME );
-- int mood;
--
-- /* convert the purple mood to a mxit mood */
-- mood = mxit_convert_mood( moodid );
-- if ( mood < 0 ) {
-- /* error, mood not found */
-- purple_debug_info( MXIT_PLUGIN_ID, "Mood status NOT found! (id = %s)\n", moodid );
-- return;
-- }
--
-- /* update mood state */
-- mxit_send_mood( session, mood );
-- return;
-- }
--
-- /* get the status id (reference: "libpurple/status.h") */
-- statusid = purple_status_get_id( status );
--
-- /* convert the purple status to a mxit status */
-- presence = mxit_convert_presence( statusid );
-- if ( presence < 0 ) {
-- /* error, status not found */
-- purple_debug_info( MXIT_PLUGIN_ID, "Presence status NOT found! (id = %s)\n", statusid );
-- return;
-- }
--
-- statusmsg1 = purple_markup_strip_html( purple_status_get_attr_string( status, "message" ) );
-- statusmsg2 = g_strndup( statusmsg1, CP_MAX_STATUS_MSG );
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_status: '%s'\n", statusmsg2 );
--
-- /* update presence state */
-- mxit_send_presence( session, presence, statusmsg2 );
--
-- g_free( statusmsg1 );
-- g_free( statusmsg2 );
--}
--
--
--/*------------------------------------------------------------------------
-- * MXit supports messages to offline contacts.
-- *
-- * @param buddy The buddy
-- */
--static gboolean mxit_offline_message( const PurpleBuddy *buddy )
--{
-- return TRUE;
--}
--
--
--/*------------------------------------------------------------------------
-- * Free the resources used to store a buddy.
-- *
-- * @param buddy The buddy
-- */
--static void mxit_free_buddy( PurpleBuddy* buddy )
--{
-- struct contact* contact;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_free_buddy\n" );
--
-- contact = purple_buddy_get_protocol_data(buddy);
-- if ( contact ) {
-- if ( contact->statusMsg )
-- g_free( contact->statusMsg );
-- if ( contact->avatarId )
-- g_free( contact->avatarId );
-- if ( contact->msg )
-- g_free( contact->msg );
-- g_free( contact );
-- }
--
-- purple_buddy_set_protocol_data(buddy, NULL);
--}
--
--
--/*------------------------------------------------------------------------
-- * Periodic task called every KEEPALIVE_INTERVAL (30 sec) to to maintain
-- * idle connections, timeouts and the transmission queue to the MXit server.
-- *
-- * @param gc The connection object
-- */
--static void mxit_keepalive( PurpleConnection *gc )
--{
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
--
-- /* if not logged in, there is nothing to do */
-- if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) )
-- return;
--
-- /* pinging is only for socket connections (HTTP does polling) */
-- if ( session->http )
-- return;
--
-- if ( session->last_tx <= ( mxit_now_milli() - ( MXIT_PING_INTERVAL * 1000 ) ) ) {
-- /*
-- * this connection has been idle for too long, better ping
-- * the server before it kills our connection.
-- */
-- mxit_send_ping( session );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Set or clear our Buddy icon.
-- *
-- * @param gc The connection object
-- * @param img The buddy icon data
-- */
--static void mxit_set_buddy_icon( PurpleConnection *gc, PurpleStoredImage *img )
--{
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
--
-- if ( img == NULL )
-- mxit_set_avatar( session, NULL, 0 );
-- else
-- mxit_set_avatar( session, purple_imgstore_get_data( img ), purple_imgstore_get_size( img ) );
--}
--
--
--/*------------------------------------------------------------------------
-- * Request profile information for another MXit contact.
-- *
-- * @param gc The connection object
-- * @param who The username of the contact.
-- */
--static void mxit_get_info( PurpleConnection *gc, const char *who )
--{
-- PurpleBuddy* buddy;
-- struct contact* contact;
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
-- const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME,
-- CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_LASTSEEN,
-- CP_PROFILE_STATUS, CP_PROFILE_AVATAR, CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME, CP_PROFILE_RELATIONSHIP };
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_info: '%s'\n", who );
--
-- /* find the buddy information for this contact (reference: "libpurple/blist.h") */
-- buddy = purple_find_buddy( session->acc, who );
-- if ( buddy ) {
-- /* user is in our contact-list, so it's not an invite */
-- contact = purple_buddy_get_protocol_data( buddy );
-- if ( !contact )
-- return;
--
-- /* only MXit users have profiles */
-- if ( contact->type != MXIT_TYPE_MXIT ) {
-- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "No profile available" ), _( "This contact does not have a profile." ) );
-- return;
-- }
-- }
--
-- /* send profile request */
-- mxit_send_extprofile_request( session, who, ARRAY_SIZE( profilelist ), profilelist );
--}
--
--
--/*------------------------------------------------------------------------
-- * Return a list of labels to be used by Pidgin for assisting the user.
-- */
--static GHashTable* mxit_get_text_table( PurpleAccount* acc )
--{
-- GHashTable* table;
--
-- table = g_hash_table_new( g_str_hash, g_str_equal );
--
-- g_hash_table_insert( table, "login_label", (gpointer)_( "Your MXit ID..." ) );
--
-- return table;
--}
--
--
--/*------------------------------------------------------------------------
-- * Re-Invite was selected from the buddy-list menu.
-- *
-- * @param node The entry in the buddy list.
-- * @param ignored (not used)
-- */
--static void mxit_reinvite( PurpleBlistNode *node, gpointer ignored )
--{
-- PurpleBuddy* buddy;
-- struct contact* contact;
-- PurpleConnection* gc;
-- struct MXitSession* session;
--
-- buddy = (PurpleBuddy *)node;
-- gc = purple_account_get_connection( purple_buddy_get_account( buddy ) );
-- session = gc->proto_data;
--
-- contact = purple_buddy_get_protocol_data( (PurpleBuddy*) node );
-- if ( !contact )
-- return;
--
-- /* send a new invite */
-- mxit_send_invite( session, contact->username, TRUE, contact->alias, contact->groupname, NULL );
--}
--
--
--/*------------------------------------------------------------------------
-- * Buddy-list menu.
-- *
-- * @param node The entry in the buddy list.
-- */
--static GList* mxit_blist_menu( PurpleBlistNode *node )
--{
-- PurpleBuddy* buddy;
-- struct contact* contact;
-- GList* m = NULL;
-- PurpleMenuAction* act;
--
-- if ( !PURPLE_BLIST_NODE_IS_BUDDY( node ) )
-- return NULL;
--
-- buddy = (PurpleBuddy *) node;
-- contact = purple_buddy_get_protocol_data( buddy );
-- if ( !contact )
-- return NULL;
--
-- if ( ( contact->subtype == MXIT_SUBTYPE_DELETED ) || ( contact->subtype == MXIT_SUBTYPE_REJECTED ) || ( contact->subtype == MXIT_SUBTYPE_NONE ) ) {
-- /* contact is in Deleted, Rejected or None state */
-- act = purple_menu_action_new( _( "Re-Invite" ), PURPLE_CALLBACK( mxit_reinvite ), NULL, NULL );
-- m = g_list_append(m, act);
-- }
--
-- return m;
--}
--
--
--/*------------------------------------------------------------------------
-- * Return Chat-room default settings.
-- *
-- * @return Chat defaults list
-- */
--static GHashTable *mxit_chat_info_defaults( PurpleConnection *gc, const char *chat_name )
--{
-- return g_hash_table_new_full( g_str_hash, g_str_equal, NULL, g_free );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a typing indicator event.
-- *
-- * @param gc The connection object
-- * @param name The username of the contact
-- * @param state The typing state to be reported.
-- */
--static unsigned int mxit_send_typing( PurpleConnection *gc, const char *name, PurpleTypingState state )
--{
-- PurpleAccount* account = purple_connection_get_account( gc );
-- struct MXitSession* session = purple_connection_get_protocol_data( gc );
-- PurpleBuddy* buddy;
-- struct contact* contact;
-- gchar* messageId = NULL;
--
-- /* find the buddy information for this contact (reference: "libpurple/blist.h") */
-- buddy = purple_find_buddy( account, name );
-- if ( !buddy ) {
-- purple_debug_warning( MXIT_PLUGIN_ID, "mxit_send_typing: unable to find the buddy '%s'\n", name );
-- return 0;
-- }
--
-- contact = purple_buddy_get_protocol_data( buddy );
-- if ( !contact )
-- return 0;
--
-- /* does this contact support and want typing notification? */
-- if ( ! ( contact->capabilities & MXIT_PFLAG_TYPING ) )
-- return 0;
--
-- messageId = purple_uuid_random(); /* generate a unique message id */
--
-- switch ( state ) {
-- case PURPLE_TYPING : /* currently typing */
-- mxit_send_msgevent( session, name, messageId, CP_MSGEVENT_TYPING );
-- break;
--
-- case PURPLE_TYPED : /* stopped typing */
-- case PURPLE_NOT_TYPING : /* not typing / erased all text */
-- mxit_send_msgevent( session, name, messageId, CP_MSGEVENT_STOPPED );
-- break;
--
-- default:
-- break;
-- }
--
-- g_free( messageId );
--
-- return 0;
--}
--
--
--/*========================================================================================================================*/
--
--static PurplePluginProtocolInfo proto_info = {
-- OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE, /* options */
-- NULL, /* user_splits */
-- NULL, /* protocol_options */
-- { /* icon_spec */
-- "png,jpeg,bmp", /* supported formats */
-- 32, 32, /* min width & height */
-- 800, 800, /* max width & height */
-- CP_MAX_FILESIZE, /* max filesize */
-- PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY /* scaling rules */
-- },
-- mxit_list_icon, /* list_icon */
-- mxit_list_emblem, /* list_emblem */
-- mxit_status_text, /* status_text */
-- mxit_tooltip, /* tooltip_text */
-- mxit_status_types, /* status types [roster.c] */
-- mxit_blist_menu, /* blist_node_menu */
-- mxit_chat_info, /* chat_info [multimx.c] */
-- mxit_chat_info_defaults,/* chat_info_defaults */
-- mxit_login, /* login [login.c] */
-- mxit_close, /* close */
-- mxit_send_im, /* send_im */
-- NULL, /* set_info */
-- mxit_send_typing, /* send_typing */
-- mxit_get_info, /* get_info */
-- mxit_set_status, /* set_status */
-- NULL, /* set_idle */
-- NULL, /* change_passwd */
-- NULL, /* add_buddy [roster.c] */
-- NULL, /* add_buddies */
-- mxit_remove_buddy, /* remove_buddy [roster.c] */
-- NULL, /* remove_buddies */
-- NULL, /* add_permit */
-- NULL, /* add_deny */
-- NULL, /* rem_permit */
-- NULL, /* rem_deny */
-- NULL, /* set_permit_deny */
-- mxit_chat_join, /* join_chat [multimx.c] */
-- mxit_chat_reject, /* reject chat invite [multimx.c] */
-- mxit_chat_name, /* get_chat_name [multimx.c] */
-- mxit_chat_invite, /* chat_invite [multimx.c] */
-- mxit_chat_leave, /* chat_leave [multimx.c] */
-- NULL, /* chat_whisper */
-- mxit_chat_send, /* chat_send [multimx.c] */
-- mxit_keepalive, /* keepalive */
-- mxit_register, /* register_user */
-- NULL, /* get_cb_info */
-- NULL, /* get_cb_away */
-- mxit_buddy_alias, /* alias_buddy [roster.c] */
-- mxit_buddy_group, /* group_buddy [roster.c] */
-- mxit_rename_group, /* rename_group [roster.c] */
-- mxit_free_buddy, /* buddy_free */
-- NULL, /* convo_closed */
-- NULL, /* normalize */
-- mxit_set_buddy_icon, /* set_buddy_icon */
-- NULL, /* remove_group */ // TODO: Add function to move all contacts out of this group (cmd=30 - remove group)?
-- NULL, /* get_cb_real_name */
-- NULL, /* set_chat_topic */
-- NULL, /* find_blist_chat */
-- NULL, /* roomlist_get_list */
-- NULL, /* roomlist_cancel */
-- NULL, /* roomlist_expand_category */
-- mxit_xfer_enabled, /* can_receive_file [filexfer.c] */
-- mxit_xfer_tx, /* send_file [filexfer.c */
-- mxit_xfer_new, /* new_xfer [filexfer.c] */
-- mxit_offline_message, /* offline_message */
-- NULL, /* whiteboard_prpl_ops */
-- NULL, /* send_raw */
-- NULL, /* roomlist_room_serialize */
-- NULL, /* unregister_user */
-- NULL, /* send_attention */
-- NULL, /* attention_types */
-- sizeof( PurplePluginProtocolInfo ), /* struct_size */
-- mxit_get_text_table, /* get_account_text_table */
-- mxit_media_initiate, /* initiate_media */
-- mxit_media_caps, /* get_media_caps */
-- mxit_get_moods, /* get_moods */
-- NULL, /* set_public_alias */
-- NULL, /* get_public_alias */
-- mxit_add_buddy, /* add_buddy_with_invite */
-- NULL /* add_buddies_with_invite */
--};
--
--
--static PurplePluginInfo plugin_info = {
-- PURPLE_PLUGIN_MAGIC, /* purple magic, this must always be PURPLE_PLUGIN_MAGIC */
-- PURPLE_MAJOR_VERSION, /* libpurple version */
-- PURPLE_MINOR_VERSION, /* libpurple version */
-- PURPLE_PLUGIN_PROTOCOL, /* plugin type (connecting to another network) */
-- NULL, /* UI requirement (NULL for core plugin) */
-- 0, /* plugin flags (zero is default) */
-- NULL, /* plugin dependencies (set this value to NULL no matter what) */
-- PURPLE_PRIORITY_DEFAULT, /* libpurple priority */
--
-- MXIT_PLUGIN_ID, /* plugin id (must be unique) */
-- MXIT_PLUGIN_NAME, /* plugin name (this will be displayed in the UI) */
-- DISPLAY_VERSION, /* version of the plugin */
--
-- MXIT_PLUGIN_SUMMARY, /* short summary of the plugin */
-- MXIT_PLUGIN_DESC, /* description of the plugin (can be long) */
-- MXIT_PLUGIN_EMAIL, /* plugin author name and email address */
-- MXIT_PLUGIN_WWW, /* plugin website (to find new versions and reporting of bugs) */
--
-- NULL, /* function pointer for loading the plugin */
-- NULL, /* function pointer for unloading the plugin */
-- NULL, /* function pointer for destroying the plugin */
--
-- NULL, /* pointer to an UI-specific struct */
-- &proto_info, /* pointer to either a PurplePluginLoaderInfo or PurplePluginProtocolInfo struct */
-- NULL, /* pointer to a PurplePluginUiInfo struct */
-- mxit_actions, /* function pointer where you can define plugin-actions */
--
-- /* padding */
-- NULL, /* pointer reserved for future use */
-- NULL, /* pointer reserved for future use */
-- NULL, /* pointer reserved for future use */
-- NULL /* pointer reserved for future use */
--};
--
--
--/*------------------------------------------------------------------------
-- * Initialising the MXit plugin.
-- *
-- * @param plugin The plugin object
-- */
--static void init_plugin( PurplePlugin* plugin )
--{
-- PurpleAccountOption* option;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "Loading MXit libPurple plugin...\n" );
--
-- /* Configuration options */
--
-- /* WAP server (reference: "libpurple/accountopt.h") */
-- option = purple_account_option_string_new( _( "WAP Server" ), MXIT_CONFIG_WAPSERVER, DEFAULT_WAPSITE );
-- proto_info.protocol_options = g_list_append( proto_info.protocol_options, option );
--
-- option = purple_account_option_bool_new( _( "Connect via HTTP" ), MXIT_CONFIG_USE_HTTP, FALSE );
-- proto_info.protocol_options = g_list_append( proto_info.protocol_options, option );
--
-- option = purple_account_option_bool_new( _( "Enable splash-screen popup" ), MXIT_CONFIG_SPLASHPOPUP, FALSE );
-- proto_info.protocol_options = g_list_append( proto_info.protocol_options, option );
--}
--
--PURPLE_INIT_PLUGIN( mxit, init_plugin, plugin_info );
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/mxit.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/mxit.h
---- pidgin-2.10.7/libpurple/protocols/mxit/mxit.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/mxit.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,199 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- MXit libPurple plugin API --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MXIT_H_
--#define _MXIT_H_
--
--
--#include "internal.h"
--
--
--#if defined( __APPLE__ )
--/* apple architecture */
--#ifndef HOST_NAME_MAX
--#define HOST_NAME_MAX 512
--#endif
--#elif defined( _WIN32 )
--/* windows architecture */
--#ifndef HOST_NAME_MAX
--#define HOST_NAME_MAX 512
--#endif
--#include "libc_interface.h"
--#elif defined( __linux__ )
--/* linux architecture */
--#include <net/if.h>
--#include <sys/ioctl.h>
--#include <sys/socket.h>
--#include <netinet/in.h>
--#include <arpa/inet.h>
--#else
--/* other architecture */
--#ifndef HOST_NAME_MAX
--#define HOST_NAME_MAX 512
--#endif
--#endif
--
--
--#include "protocol.h"
--#include "profile.h"
--
--
--/* Plugin details */
--#define MXIT_PLUGIN_ID "prpl-loubserp-mxit"
--#define MXIT_PLUGIN_NAME "MXit"
--#define MXIT_PLUGIN_EMAIL "Pieter Loubser <libpurple@mxit.com>"
--#define MXIT_PLUGIN_WWW "http://www.mxit.com"
--#define MXIT_PLUGIN_SUMMARY "MXit Protocol Plugin"
--#define MXIT_PLUGIN_DESC "MXit"
--
--#define MXIT_HTTP_USERAGENT "libpurple-"DISPLAY_VERSION
--
--
--/* default connection settings */
--#define DEFAULT_SERVER "stream.mxit.co.za"
--#define DEFAULT_PORT 9119
--#define DEFAULT_WAPSITE "http://www.mxit.com"
--#define DEFAULT_HTTP_SERVER "http://int.poll.mxit.com:80/mxit"
--
--
--/* Purple account configuration variable names */
--#define MXIT_CONFIG_STATE "state"
--#define MXIT_CONFIG_WAPSERVER "wap_server"
--#define MXIT_CONFIG_DISTCODE "distcode"
--#define MXIT_CONFIG_CLIENTKEY "clientkey"
--#define MXIT_CONFIG_DIALCODE "dialcode"
--#define MXIT_CONFIG_SERVER_ADDR "server"
--#define MXIT_CONFIG_SERVER_PORT "port"
--#define MXIT_CONFIG_HTTPSERVER "httpserver"
--#define MXIT_CONFIG_SPLASHID "splashid"
--#define MXIT_CONFIG_SPLASHCLICK "splashclick"
--#define MXIT_CONFIG_SPLASHPOPUP "splashpopup"
--#define MXIT_CONFIG_COUNTRYCODE "cc"
--#define MXIT_CONFIG_LOCALE "locale"
--#define MXIT_CONFIG_USE_HTTP "use_http"
--
--
--/* account states */
--#define MXIT_STATE_LOGIN 0x00
--#define MXIT_STATE_REGISTER1 0x01
--#define MXIT_STATE_REGISTER2 0x02
--
--
--/* Client session flags */
--#define MXIT_FLAG_CONNECTED 0x01 /* established connection to the server */
--#define MXIT_FLAG_LOGGEDIN 0x02 /* user currently logged in */
--#define MXIT_FLAG_FIRSTROSTER 0x04 /* set to true once the first roster update has been received and processed */
--
--
--/* Maximum number of search results */
--#define MXIT_SEARCHRESULTS_MAX 30
--
--
--/* define this to enable the link clicking support */
--#define MXIT_LINK_CLICK
--
--#ifdef MXIT_LINK_CLICK
--#define MXIT_LINK_PREFIX "gopher://"
--#define MXIT_LINK_KEY "MXIT"
--#endif
--
--
--#define ARRAY_SIZE( x ) ( sizeof( x ) / sizeof( x[0] ) )
--
--
--/*
-- * data structure containing all MXit session information
-- */
--struct MXitSession {
-- /* socket connection */
-- char server[HOST_NAME_MAX]; /* MXit server name to connect to */
-- int port; /* MXit server port to connect on */
-- int fd; /* connection file descriptor */
--
-- /* http connection */
-- gboolean http; /* connect to MXit via HTTP and not by socket */
-- char http_server[HOST_NAME_MAX]; /* MXit HTTP server */
-- unsigned int http_sesid; /* HTTP session id */
-- unsigned int http_seqno; /* HTTP request sequence number */
-- guint http_timer_id; /* timer resource id (pidgin) */
-- int http_interval; /* poll inverval */
-- gint64 http_last_poll; /* the last time a poll has been sent */
-- guint http_handler; /* HTTP connection handler */
-- void* http_out_req; /* HTTP outstanding request */
--
-- /* other servers */
-- char voip_server[HOST_NAME_MAX]; /* voice/video server */
--
-- /* client */
-- struct login_data* logindata;
-- char* encpwd; /* encrypted password */
-- char distcode[64]; /* distribution code */
-- char clientkey[16]; /* client key */
-- char dialcode[8]; /* dialing code */
-- short flags; /* client session flags (see above) */
--
-- /* personal (profile) */
-- struct MXitProfile* profile; /* user's profile information */
-- char* uid; /* the user's UID */
--
-- /* libpurple */
-- PurpleAccount* acc; /* pointer to the libpurple internal account struct */
-- PurpleConnection* con; /* pointer to the libpurple internal connection struct */
--
-- /* transmit */
-- struct tx_queue queue; /* transmit packet queue (FIFO mode) */
-- gint64 last_tx; /* timestamp of last packet sent */
-- int outack; /* outstanding ack packet */
-- guint q_slow_timer_id; /* timer handle for slow tx queue */
-- guint q_fast_timer_id; /* timer handle for fast tx queue */
--
-- /* receive */
-- char rx_lbuf[16]; /* receive byte buffer (socket packet length) */
-- char rx_dbuf[CP_MAX_PACKET]; /* receive byte buffer (raw data) */
-- unsigned int rx_i; /* receive buffer current index */
-- int rx_res; /* amount of bytes still outstanding for the current packet */
-- char rx_state; /* current receiver state */
-- gint64 last_rx; /* timestamp of last packet received */
-- GList* active_chats; /* list of all our contacts we received messages from (active chats) */
-- GList* invites; /* list of all the invites that we have received */
--
-- /* groupchat */
-- GList* rooms; /* active groupchat rooms */
--
-- /* inline images */
-- GHashTable* iimages; /* table which maps inline images (including emoticons) to purple's imgstore id's */
--};
--
--
--char* mxit_status_text( PurpleBuddy* buddy );
--void mxit_enable_signals( struct MXitSession* session );
--
--#ifdef MXIT_LINK_CLICK
--void mxit_register_uri_handler(void);
--#endif
--
--
--#endif /* _MXIT_H_ */
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/profile.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/profile.c
---- pidgin-2.10.7/libpurple/protocols/mxit/profile.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/profile.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,366 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- user profile's --
-- *
-- * Andrew Victor <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#define _XOPEN_SOURCE
--#include <time.h>
--
--#include "internal.h"
--#include "purple.h"
--
--#include "mxit.h"
--#include "profile.h"
--#include "roster.h"
--
--
--/*------------------------------------------------------------------------
-- * Return the MXit Relationship status as a string.
-- *
-- * @param id The Relationship status value (see profile.h)
-- * @return The relationship status as a text string.
-- */
--const char* mxit_relationship_to_name( short id )
--{
-- switch ( id ) {
-- case MXIT_RELATIONSHIP_UNKNOWN :
-- return _( "Unknown" );
-- case MXIT_RELATIONSHIP_DONTSAY :
-- return _( "Don't want to say" );
-- case MXIT_RELATIONSHIP_SINGLE :
-- return _( "Single" );
-- case MXIT_RELATIONSHIP_INVOLVED :
-- return _( "In a relationship" );
-- case MXIT_RELATIONSHIP_ENGAGED :
-- return _( "Engaged" );
-- case MXIT_RELATIONSHIP_MARRIED :
-- return _( "Married" );
-- case MXIT_RELATIONSHIP_COMPLICATED :
-- return _( "It's complicated" );
-- case MXIT_RELATIONSHIP_WIDOWED :
-- return _( "Widowed" );
-- case MXIT_RELATIONSHIP_SEPARATED :
-- return _( "Separated" );
-- case MXIT_RELATIONSHIP_DIVORCED :
-- return _( "Divorced" );
-- default :
-- return "";
-- }
--}
--
--/*------------------------------------------------------------------------
-- * Returns true if it is a valid date.
-- *
-- * @param bday Date-of-Birth string (YYYY-MM-DD)
-- * @return TRUE if valid, else FALSE
-- */
--gboolean validateDate( const char* bday )
--{
-- struct tm* tm;
-- time_t t;
-- int cur_year;
-- int max_days[13] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-- char date[16];
-- int year;
-- int month;
-- int day;
--
-- /* validate length */
-- if ( strlen( bday ) != 10 ) {
-- return FALSE;
-- }
--
-- /* validate the format */
-- if ( ( !isdigit( bday[0] ) ) || ( !isdigit( bday[1] ) ) || ( !isdigit( bday[2] ) ) || ( !isdigit( bday[3] ) ) || /* year */
-- ( bday[4] != '-' ) ||
-- ( !isdigit( bday[5] ) ) || ( !isdigit( bday[6] ) ) || /* month */
-- ( bday[7] != '-' ) ||
-- ( !isdigit( bday[8] ) ) || ( !isdigit( bday[9] ) ) ) { /* day */
-- return FALSE;
-- }
--
-- /* convert */
-- t = time( NULL );
-- tm = gmtime( &t );
-- cur_year = tm->tm_year + 1900;
-- memcpy( date, bday, 10 );
-- date[4] = '\0';
-- date[7] = '\0';
-- date[10] = '\0';
-- year = atoi( &date[0] );
-- month = atoi( &date[5] );
-- day = atoi( &date[8] );
--
-- /* validate month */
-- if ( ( month < 1 ) || ( month > 12 ) ) {
-- return FALSE;
-- }
--
-- /* validate day */
-- if ( ( day < 1 ) || ( day > max_days[month] ) ) {
-- return FALSE;
-- }
--
-- /* validate year */
-- if ( ( year < ( cur_year - 100 ) ) || ( year >= cur_year ) ) {
-- /* you are either tooo old or tooo young to join mxit... sorry */
-- return FALSE;
-- }
--
-- /* special case leap-year */
-- if ( ( year % 4 != 0 ) && ( month == 2 ) && ( day == 29 ) ) {
-- /* cannot have 29 days in February in non leap-years! */
-- return FALSE;
-- }
--
-- return TRUE;
--}
--
--
--/*------------------------------------------------------------------------
-- * Calculate an Age from the date-of-birth.
-- *
-- * @param date Date-of-Birth string (YYYY-MM-DD)
-- * @return The age
-- */
--static int calculateAge( const char* date )
--{
-- time_t t;
-- struct tm now, bdate;
-- int age;
--
-- if ( ( !date ) || ( strlen( date ) == 0 ) )
-- return 0;
--
-- /* current time */
-- t = time(NULL);
-- localtime_r( &t, &now );
--
-- /* decode hdate */
-- memset( &bdate, 0, sizeof( struct tm ) );
-- purple_str_to_time(date, FALSE, &bdate, NULL, NULL);
--
-- /* calculate difference */
-- age = now.tm_year - bdate.tm_year;
-- if ( now.tm_mon < bdate.tm_mon ) /* is before month of birth */
-- age--;
-- else if ( (now.tm_mon == bdate.tm_mon ) && ( now.tm_mday < bdate.tm_mday ) ) /* before birthday in current month */
-- age--;
--
-- return age;
--}
--
--
--/*------------------------------------------------------------------------
-- * Returns timestamp field in date & time format (DD-MM-YYYY HH:MM:SS)
-- *
-- * @param msecs The timestamps (milliseconds since epoch)
-- * @return Date & Time in a display'able format.
-- */
--static const char* datetime( gint64 msecs )
--{
-- time_t secs = msecs / 1000;
--
-- struct tm t;
-- localtime_r( &secs, &t );
--
-- return purple_utf8_strftime( "%d-%m-%Y %H:%M:%S", &t );
--}
--
--
--/*------------------------------------------------------------------------
-- * Display the profile information.
-- *
-- * @param session The MXit session object
-- * @param username The username who's profile information this is
-- * @param profile The profile
-- */
--void mxit_show_profile( struct MXitSession* session, const char* username, struct MXitProfile* profile )
--{
-- PurpleNotifyUserInfo* info = purple_notify_user_info_new();
-- struct contact* contact = NULL;
-- PurpleBuddy* buddy;
-- gchar* tmp = NULL;
--
-- buddy = purple_find_buddy( session->acc, username );
-- if ( buddy ) {
-- purple_notify_user_info_add_pair( info, _( "Alias" ), purple_buddy_get_alias( buddy ) );
-- purple_notify_user_info_add_section_break( info );
-- contact = purple_buddy_get_protocol_data(buddy);
-- }
--
-- purple_notify_user_info_add_pair( info, _( "Display Name" ), profile->nickname );
--
-- tmp = g_strdup_printf("%s (%i)", profile->birthday, calculateAge( profile->birthday ) );
-- purple_notify_user_info_add_pair( info, _( "Birthday" ), tmp );
-- g_free( tmp );
--
-- purple_notify_user_info_add_pair( info, _( "Gender" ), profile->male ? _( "Male" ) : _( "Female" ) );
--
-- /* optional information */
-- purple_notify_user_info_add_pair( info, _( "First Name" ), profile->firstname );
-- purple_notify_user_info_add_pair( info, _( "Last Name" ), profile->lastname );
-- purple_notify_user_info_add_pair( info, _( "Country" ), profile->regcountry );
--
-- if ( strlen( profile->aboutme ) > 0 )
-- purple_notify_user_info_add_pair( info, _( "About Me" ), profile->aboutme );
-- if ( strlen( profile->whereami ) > 0 )
-- purple_notify_user_info_add_pair( info, _( "Where I Live" ), profile->whereami );
--
-- purple_notify_user_info_add_pair_plaintext( info, _( "Relationship Status" ), mxit_relationship_to_name( profile->relationship ) );
--
-- purple_notify_user_info_add_section_break( info );
--
-- if ( contact ) {
-- /* presence */
-- purple_notify_user_info_add_pair( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) );
--
-- /* last online */
-- if ( contact->presence == MXIT_PRESENCE_OFFLINE )
-- purple_notify_user_info_add_pair( info, _( "Last Online" ), ( profile->lastonline == 0 ) ? _( "Unknown" ) : datetime( profile->lastonline ) );
--
-- /* mood */
-- if ( contact->mood != MXIT_MOOD_NONE )
-- purple_notify_user_info_add_pair( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) );
-- else
-- purple_notify_user_info_add_pair( info, _( "Mood" ), _( "None" ) );
--
-- /* status message */
-- if ( contact->statusMsg )
-- purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg );
--
-- /* subscription type */
-- purple_notify_user_info_add_pair( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) );
-- }
-- else {
-- /* this is an invite */
-- contact = get_mxit_invite_contact( session, username );
-- if ( contact ) {
-- /* invite found */
--
-- if ( contact->msg )
-- purple_notify_user_info_add_pair( info, _( "Invite Message" ), contact->msg );
--
-- if ( contact->imgid ) {
-- /* this invite has a avatar */
-- char* img_text;
-- img_text = g_strdup_printf( "<img id='%d'>", contact->imgid );
-- purple_notify_user_info_add_pair( info, _( "Photo" ), img_text );
-- g_free( img_text );
-- }
--
-- if ( contact->statusMsg )
-- purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg );
-- }
-- }
--
-- purple_notify_userinfo( session->con, username, info, NULL, NULL );
-- purple_notify_user_info_destroy( info );
--}
--
--
--/*------------------------------------------------------------------------
-- * Display the profiles of search results.
-- *
-- * @param gc The connection object
-- * @param row The selected row from search-results
-- * @param user_data NULL (unused)
-- */
--static void mxit_search_results_add_cb( PurpleConnection *gc, GList *row, gpointer user_data )
--{
-- /* display add buddy dialog */
-- purple_blist_request_add_buddy( purple_connection_get_account( gc ), g_list_nth_data( row, 0 ), NULL, g_list_nth_data( row, 1 ) );
--}
--
--
--/*------------------------------------------------------------------------
-- * Display the profiles of search results.
-- *
-- * @param session The MXit session object
-- * @param searchType The type of search (CP_SUGGEST_*)
-- * @param maxResults The maximum number of results
-- * @param entries The list of profile entries
-- */
--void mxit_show_search_results( struct MXitSession* session, int searchType, int maxResults, GList* entries )
--{
-- PurpleNotifySearchResults* results;
-- PurpleNotifySearchColumn* column;
-- gchar* text;
--
-- if ( !entries ) {
-- mxit_popup( PURPLE_NOTIFY_MSG_INFO, _( "No results" ), _( "No contacts found." ) );
-- return;
-- }
--
-- results = purple_notify_searchresults_new();
-- if ( !results )
-- return;
--
-- /* define columns */
-- column = purple_notify_searchresults_column_new( _( "UserId" ) );
-- purple_notify_searchresults_column_add( results, column );
-- column = purple_notify_searchresults_column_new( _( "Display Name" ) );
-- purple_notify_searchresults_column_add( results, column );
-- column = purple_notify_searchresults_column_new( _( "First Name" ) );
-- purple_notify_searchresults_column_add( results, column );
-- column = purple_notify_searchresults_column_new( _( "Last Name" ) );
-- purple_notify_searchresults_column_add( results, column );
-- column = purple_notify_searchresults_column_new( _( "Gender" ) );
-- purple_notify_searchresults_column_add( results, column );
-- column = purple_notify_searchresults_column_new( _( "Age" ) );
-- purple_notify_searchresults_column_add( results, column );
-- column = purple_notify_searchresults_column_new( _( "Where I live" ) );
-- purple_notify_searchresults_column_add( results, column );
--
-- while (entries != NULL) {
-- struct MXitProfile* profile = ( struct MXitProfile *) entries->data;
-- GList* row;
-- gchar* tmp = purple_base64_encode( (unsigned char *) profile->userid, strlen( profile->userid ) );
--
-- /* column values */
-- row = g_list_append( NULL, g_strdup_printf( "#%s", tmp ) );
-- row = g_list_append( row, g_strdup( profile->nickname ) );
-- row = g_list_append( row, g_strdup( profile->firstname ) );
-- row = g_list_append( row, g_strdup( profile->lastname ) );
-- row = g_list_append( row, g_strdup( profile->male ? "Male" : "Female" ) );
-- row = g_list_append( row, g_strdup_printf( "%i", calculateAge( profile->birthday ) ) );
-- row = g_list_append( row, g_strdup( profile->whereami ) );
--
-- purple_notify_searchresults_row_add( results, row );
-- entries = g_list_next( entries );
--
-- g_free( tmp );
-- }
--
-- /* button */
-- purple_notify_searchresults_button_add( results, PURPLE_NOTIFY_BUTTON_INVITE, mxit_search_results_add_cb );
--
-- if ( searchType == CP_SUGGEST_FRIENDS )
-- text = g_strdup_printf( dngettext( PACKAGE, "You have %i suggested friend.", "You have %i suggested friends.", maxResults ), maxResults );
-- else
-- text = g_strdup_printf( dngettext( PACKAGE, "We found %i contact that matches your search.", "We found %i contacts that match your search.", maxResults ), maxResults );
--
-- purple_notify_searchresults( session->con, NULL, text, NULL, results, NULL, NULL );
--
-- g_free( text);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/profile.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/profile.h
---- pidgin-2.10.7/libpurple/protocols/mxit/profile.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/profile.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,76 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- user profile's --
-- *
-- * Andrew Victor <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MXIT_PROFILE_H_
--#define _MXIT_PROFILE_H_
--
--#include <glib.h>
--
--
--/* MXit relationship status types */
--#define MXIT_RELATIONSHIP_UNKNOWN 0
--#define MXIT_RELATIONSHIP_DONTSAY 1
--#define MXIT_RELATIONSHIP_SINGLE 2
--#define MXIT_RELATIONSHIP_INVOLVED 3
--#define MXIT_RELATIONSHIP_ENGAGED 4
--#define MXIT_RELATIONSHIP_MARRIED 5
--#define MXIT_RELATIONSHIP_COMPLICATED 6
--#define MXIT_RELATIONSHIP_WIDOWED 7
--#define MXIT_RELATIONSHIP_SEPARATED 8
--#define MXIT_RELATIONSHIP_DIVORCED 9
--
--struct MXitProfile {
-- /* required */
-- char loginname[64]; /* name user uses to log into MXit with (aka 'mxitid') */
-- char userid[51]; /* internal UserId (only in search results) */
-- char nickname[101]; /* user's own display name (aka 'display name', aka 'fullname', aka 'alias') in MXit */
-- char birthday[16]; /* user's birthday "YYYY-MM-DD" */
-- gboolean male; /* true if the user's gender is male (otherwise female) */
-- char pin[16]; /* user's password */
--
-- /* optional */
-- char title[21]; /* user's title */
-- char firstname[51]; /* user's first name */
-- char lastname[51]; /* user's last name (aka 'surname') */
-- char email[201]; /* user's email address */
-- char mobilenr[21]; /* user's mobile number */
-- char regcountry[3]; /* user's registered country code */
-- char whereami[51]; /* where am I / where I live */
-- char aboutme[513]; /* about me */
-- int relationship; /* relationship status */
--
-- int flags; /* user's profile flags */
-- gint64 lastonline; /* user's last-online timestamp */
--};
--
--struct MXitSession;
--void mxit_show_profile( struct MXitSession* session, const char* username, struct MXitProfile* profile );
--void mxit_show_search_results( struct MXitSession* session, int searchType, int maxResults, GList* entries );
--const char* mxit_relationship_to_name( short id );
--
--gboolean validateDate( const char* bday );
--
--
--#endif /* _MXIT_PROFILE_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/protocol.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/protocol.c
---- pidgin-2.10.7/libpurple/protocols/mxit/protocol.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/protocol.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,2949 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- MXit client protocol implementation --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "purple.h"
--
--#include "protocol.h"
--#include "mxit.h"
--#include "roster.h"
--#include "chunk.h"
--#include "filexfer.h"
--#include "markup.h"
--#include "multimx.h"
--#include "splashscreen.h"
--#include "login.h"
--#include "formcmds.h"
--#include "http.h"
--#include "voicevideo.h"
--
--
--#define MXIT_MS_OFFSET 3
--
--/* configure the right record terminator char to use */
--#define CP_REC_TERM ( ( session->http ) ? CP_HTTP_REC_TERM : CP_SOCK_REC_TERM )
--
--
--/*------------------------------------------------------------------------
-- * return the current timestamp in milliseconds
-- */
--gint64 mxit_now_milli( void )
--{
-- GTimeVal now;
--
-- g_get_current_time( &now );
--
-- return ( ( now.tv_sec * 1000 ) + ( now.tv_usec / 1000 ) );
--}
--
--
--/*------------------------------------------------------------------------
-- * Display a notification popup message to the user.
-- *
-- * @param type The type of notification:
-- * - info: PURPLE_NOTIFY_MSG_INFO
-- * - warning: PURPLE_NOTIFY_MSG_WARNING
-- * - error: PURPLE_NOTIFY_MSG_ERROR
-- * @param heading Heading text
-- * @param message Message text
-- */
--void mxit_popup( int type, const char* heading, const char* message )
--{
-- /* (reference: "libpurple/notify.h") */
-- purple_notify_message( NULL, type, _( MXIT_POPUP_WIN_NAME ), heading, message, NULL, NULL );
--}
--
--
--/*------------------------------------------------------------------------
-- * For compatibility with legacy clients, all usernames are sent from MXit with a domain
-- * appended. For MXit contacts, this domain is set to "@m". This function strips
-- * those fake domains.
-- *
-- * @param username The username of the contact
-- */
--void mxit_strip_domain( char* username )
--{
-- if ( g_str_has_suffix( username, "@m" ) )
-- username[ strlen(username) - 2 ] = '\0';
--}
--
--
--/*------------------------------------------------------------------------
-- * Dump a byte buffer to the console for debugging purposes.
-- *
-- * @param buf The data
-- * @param len The data length
-- */
--void dump_bytes( struct MXitSession* session, const char* buf, int len )
--{
-- char msg[( len * 3 ) + 1];
-- int i;
--
-- memset( msg, 0x00, sizeof( msg ) );
--
-- for ( i = 0; i < len; i++ ) {
-- if ( buf[i] == CP_REC_TERM ) /* record terminator */
-- msg[i] = '!';
-- else if ( buf[i] == CP_FLD_TERM ) /* field terminator */
-- msg[i] = '^';
-- else if ( buf[i] == CP_PKT_TERM ) /* packet terminator */
-- msg[i] = '@';
-- else if ( buf[i] < 0x20 )
-- msg[i] = '_';
-- else
-- msg[i] = buf[i];
--
-- }
--
-- purple_debug_info( MXIT_PLUGIN_ID, "DUMP: '%s'\n", msg );
--}
--
--
--/*------------------------------------------------------------------------
-- * Determine if we have an active chat with a specific contact
-- *
-- * @param session The MXit session object
-- * @param who The contact name
-- * @return Return true if we have an active chat with the contact
-- */
--gboolean find_active_chat( const GList* chats, const char* who )
--{
-- const GList* list = chats;
-- const char* chat = NULL;
--
-- while ( list ) {
-- chat = (const char*) list->data;
--
-- if ( strcmp( chat, who ) == 0 )
-- return TRUE;
--
-- list = g_list_next( list );
-- }
--
-- return FALSE;
--}
--
--
--/*========================================================================================================================
-- * Low-level Packet transmission
-- */
--
--/*------------------------------------------------------------------------
-- * Remove next packet from transmission queue.
-- *
-- * @param session The MXit session object
-- * @return The next packet for transmission (or NULL)
-- */
--static struct tx_packet* pop_tx_packet( struct MXitSession* session )
--{
-- struct tx_packet* packet = NULL;
--
-- if ( session->queue.count > 0 ) {
-- /* dequeue the next packet */
-- packet = session->queue.packets[session->queue.rd_i];
-- session->queue.packets[session->queue.rd_i] = NULL;
-- session->queue.rd_i = ( session->queue.rd_i + 1 ) % MAX_QUEUE_SIZE;
-- session->queue.count--;
-- }
--
-- return packet;
--}
--
--
--/*------------------------------------------------------------------------
-- * Add packet to transmission queue.
-- *
-- * @param session The MXit session object
-- * @param packet The packet to transmit
-- * @return Return TRUE if packet was enqueue, or FALSE if queue is full.
-- */
--static gboolean push_tx_packet( struct MXitSession* session, struct tx_packet* packet )
--{
-- if ( session->queue.count < MAX_QUEUE_SIZE ) {
-- /* enqueue packet */
-- session->queue.packets[session->queue.wr_i] = packet;
-- session->queue.wr_i = ( session->queue.wr_i + 1 ) % MAX_QUEUE_SIZE;
-- session->queue.count++;
-- return TRUE;
-- }
-- else
-- return FALSE; /* queue is full */
--}
--
--
--/*------------------------------------------------------------------------
-- * Deallocate transmission packet.
-- *
-- * @param packet The packet to deallocate.
-- */
--static void free_tx_packet( struct tx_packet* packet )
--{
-- g_free( packet->data );
-- g_free( packet );
-- packet = NULL;
--}
--
--
--/*------------------------------------------------------------------------
-- * Flush all the packets from the tx queue and release the resources.
-- *
-- * @param session The MXit session object
-- */
--static void flush_queue( struct MXitSession* session )
--{
-- struct tx_packet* packet;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "flushing the tx queue\n" );
--
-- while ( (packet = pop_tx_packet( session ) ) != NULL )
-- free_tx_packet( packet );
--}
--
--
--/*------------------------------------------------------------------------
-- * TX Step 3: Write the packet data to the TCP connection.
-- *
-- * @param fd The file descriptor
-- * @param pktdata The packet data
-- * @param pktlen The length of the packet data
-- * @return Return -1 on error, otherwise 0
-- */
--static int mxit_write_sock_packet( int fd, const char* pktdata, int pktlen )
--{
-- int written;
-- int res;
--
-- written = 0;
-- while ( written < pktlen ) {
-- res = write( fd, &pktdata[written], pktlen - written );
-- if ( res <= 0 ) {
-- /* error on socket */
-- if ( errno == EAGAIN )
-- continue;
--
-- purple_debug_error( MXIT_PLUGIN_ID, "Error while writing packet to MXit server (%i)\n", res );
-- return -1;
-- }
-- written += res;
-- }
--
-- return 0;
--}
--
--
--/*------------------------------------------------------------------------
-- * Callback called for handling a HTTP GET response
-- *
-- * @param url_data libPurple internal object (see purple_util_fetch_url_request)
-- * @param user_data The MXit session object
-- * @param url_text The data returned (could be NULL if error)
-- * @param len The length of the data returned (0 if error)
-- * @param error_message Descriptive error message
-- */
--static void mxit_cb_http_rx( PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message )
--{
-- struct MXitSession* session = (struct MXitSession*) user_data;
--
-- /* clear outstanding request */
-- session->http_out_req = NULL;
--
-- if ( ( !url_text ) || ( len == 0 ) ) {
-- /* error with request */
-- purple_debug_error( MXIT_PLUGIN_ID, "HTTP response error (%s)\n", error_message );
-- return;
-- }
--
-- /* convert the HTTP result */
-- memcpy( session->rx_dbuf, url_text, len );
-- session->rx_i = len;
--
-- mxit_parse_packet( session );
--}
--
--
--/*------------------------------------------------------------------------
-- * TX Step 3: Write the packet data to the HTTP connection (GET style).
-- *
-- * @param session The MXit session object
-- * @param pktdata The packet data
-- * @param pktlen The length of the packet data
-- * @return Return -1 on error, otherwise 0
-- */
--static void mxit_write_http_get( struct MXitSession* session, struct tx_packet* packet )
--{
-- char* part = NULL;
-- char* url = NULL;
--
-- if ( packet->datalen > 0 ) {
-- char* tmp = NULL;
--
-- tmp = g_strndup( packet->data, packet->datalen );
-- part = g_strdup( purple_url_encode( tmp ) );
-- g_free( tmp );
-- }
--
-- url = g_strdup_printf( "%s?%s%s", session->http_server, purple_url_encode( packet->header ), ( !part ) ? "" : part );
--
--#ifdef DEBUG_PROTOCOL
-- purple_debug_info( MXIT_PLUGIN_ID, "HTTP GET: '%s'\n", url );
--#endif
--
-- /* send the HTTP request */
-- session->http_out_req = purple_util_fetch_url_request( url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, mxit_cb_http_rx, session );
--
-- g_free( url );
-- if ( part )
-- g_free( part );
--}
--
--
--/*------------------------------------------------------------------------
-- * TX Step 3: Write the packet data to the HTTP connection (POST style).
-- *
-- * @param session The MXit session object
-- * @param pktdata The packet data
-- * @param pktlen The length of the packet data
-- * @return Return -1 on error, otherwise 0
-- */
--static void mxit_write_http_post( struct MXitSession* session, struct tx_packet* packet )
--{
-- char request[256 + packet->datalen];
-- int reqlen;
-- char* host_name;
-- int host_port;
-- gboolean ok;
--
-- /* extract the HTTP host name and host port number to connect to */
-- ok = purple_url_parse( session->http_server, &host_name, &host_port, NULL, NULL, NULL );
-- if ( !ok ) {
-- purple_debug_error( MXIT_PLUGIN_ID, "HTTP POST error: (host name '%s' not valid)\n", session->http_server );
-- }
--
-- /* strip off the last '&' from the header */
-- packet->header[packet->headerlen - 1] = '\0';
-- packet->headerlen--;
--
-- /* build the HTTP request packet */
-- reqlen = g_snprintf( request, 256,
-- "POST %s?%s HTTP/1.1\r\n"
-- "User-Agent: " MXIT_HTTP_USERAGENT "\r\n"
-- "Content-Type: application/octet-stream\r\n"
-- "Host: %s\r\n"
-- "Content-Length: %d\r\n"
-- "\r\n",
-- session->http_server,
-- purple_url_encode( packet->header ),
-- host_name,
-- packet->datalen - MXIT_MS_OFFSET
-- );
--
-- /* copy over the packet body data (could be binary) */
-- memcpy( request + reqlen, packet->data + MXIT_MS_OFFSET, packet->datalen - MXIT_MS_OFFSET );
-- reqlen += packet->datalen;
--
--#ifdef DEBUG_PROTOCOL
-- purple_debug_info( MXIT_PLUGIN_ID, "HTTP POST:\n" );
-- dump_bytes( session, request, reqlen );
--#endif
--
-- /* send the request to the HTTP server */
-- mxit_http_send_request( session, host_name, host_port, request, reqlen );
--}
--
--
--/*------------------------------------------------------------------------
-- * TX Step 2: Handle the transmission of the packet to the MXit server.
-- *
-- * @param session The MXit session object
-- * @param packet The packet to transmit
-- */
--static void mxit_send_packet( struct MXitSession* session, struct tx_packet* packet )
--{
-- int res;
--
-- if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) {
-- /* we are not connected so ignore all packets to be send */
-- purple_debug_error( MXIT_PLUGIN_ID, "Dropping TX packet (we are not connected)\n" );
-- return;
-- }
--
-- purple_debug_info( MXIT_PLUGIN_ID, "Packet send CMD:%i (%i)\n", packet->cmd, packet->headerlen + packet->datalen );
--#ifdef DEBUG_PROTOCOL
-- dump_bytes( session, packet->header, packet->headerlen );
-- dump_bytes( session, packet->data, packet->datalen );
--#endif
--
-- if ( !session->http ) {
-- /* socket connection */
-- char data[packet->datalen + packet->headerlen];
-- int datalen;
--
-- /* create raw data buffer */
-- memcpy( data, packet->header, packet->headerlen );
-- memcpy( data + packet->headerlen, packet->data, packet->datalen );
-- datalen = packet->headerlen + packet->datalen;
--
-- res = mxit_write_sock_packet( session->fd, data, datalen );
-- if ( res < 0 ) {
-- /* we must have lost the connection, so terminate it so that we can reconnect */
-- purple_connection_error( session->con, _( "We have lost the connection to MXit. Please reconnect." ) );
-- }
-- }
-- else {
-- /* http connection */
--
-- if ( packet->cmd == CP_CMD_MEDIA ) {
-- /* multimedia packets must be send with a HTTP POST */
-- mxit_write_http_post( session, packet );
-- }
-- else {
-- mxit_write_http_get( session, packet );
-- }
-- }
--
-- /* update the timestamp of the last-transmitted packet */
-- session->last_tx = mxit_now_milli();
--
-- /*
-- * we need to remember that we are still waiting for the ACK from
-- * the server on this request
-- */
-- session->outack = packet->cmd;
--
-- /* free up the packet resources */
-- free_tx_packet( packet );
--}
--
--
--/*------------------------------------------------------------------------
-- * TX Step 1: Create a new Tx packet and queue it for sending.
-- *
-- * @param session The MXit session object
-- * @param data The packet data (payload)
-- * @param datalen The length of the packet data
-- * @param cmd The MXit command for this packet
-- */
--static void mxit_queue_packet( struct MXitSession* session, const char* data, int datalen, int cmd )
--{
-- struct tx_packet* packet;
-- char header[256];
-- int hlen;
--
-- /* create a packet for sending */
-- packet = g_new0( struct tx_packet, 1 );
-- packet->data = g_malloc0( datalen );
-- packet->cmd = cmd;
-- packet->headerlen = 0;
--
-- /* create generic packet header */
-- hlen = snprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc ), CP_REC_TERM ); /* client msisdn */
--
-- if ( session->http ) {
-- /* http connection only */
-- hlen += sprintf( header + hlen, "s=" );
-- if ( session->http_sesid > 0 ) {
-- hlen += sprintf( header + hlen, "%u%c", session->http_sesid, CP_FLD_TERM ); /* http session id */
-- }
-- session->http_seqno++;
-- hlen += sprintf( header + hlen, "%u%c", session->http_seqno, CP_REC_TERM ); /* http request sequence id */
-- }
--
-- hlen += sprintf( header + hlen, "cm=%i%c", cmd, CP_REC_TERM ); /* packet command */
--
-- if ( !session->http ) {
-- /* socket connection only */
-- packet->headerlen += sprintf( packet->header, "ln=%i%c", ( datalen + hlen ), CP_REC_TERM ); /* packet length */
-- }
--
-- /* copy the header to packet */
-- memcpy( packet->header + packet->headerlen, header, hlen );
-- packet->headerlen += hlen;
--
-- /* copy payload to packet */
-- if ( datalen > 0 )
-- memcpy( packet->data, data, datalen );
-- packet->datalen = datalen;
--
--
-- /* shortcut */
-- if ( ( session->queue.count == 0 ) && ( session->outack == 0 ) ) {
-- /* the queue is empty and there are no outstanding acks so we can write it directly */
-- mxit_send_packet( session, packet );
-- }
-- else {
-- /* we need to queue this packet */
--
-- if ( ( packet->cmd == CP_CMD_PING ) || ( packet->cmd == CP_CMD_POLL ) ) {
-- /* we do NOT queue HTTP poll nor socket ping packets */
-- free_tx_packet( packet );
-- return;
-- }
--
-- purple_debug_info( MXIT_PLUGIN_ID, "queueing packet for later sending cmd=%i\n", cmd );
-- if ( !push_tx_packet( session, packet ) ) {
-- /* packet could not be queued for transmission */
-- mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Message Send Error" ), _( "Unable to process your request at this time" ) );
-- free_tx_packet( packet );
-- }
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Manage the packet send queue (send next packet, timeout's, etc).
-- *
-- * @param session The MXit session object
-- */
--static void mxit_manage_queue( struct MXitSession* session )
--{
-- struct tx_packet* packet = NULL;
-- gint64 now = mxit_now_milli();
--
-- if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) {
-- /* we are not connected, so ignore the queue */
-- return;
-- }
-- else if ( session->outack > 0 ) {
-- /* we are still waiting for an outstanding ACK from the MXit server */
-- if ( session->last_tx <= mxit_now_milli() - ( MXIT_ACK_TIMEOUT * 1000 ) ) {
-- /* ack timeout! so we close the connection here */
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_manage_queue: Timeout awaiting ACK for command '%i'\n", session->outack );
-- purple_connection_error( session->con, _( "Timeout while waiting for a response from the MXit server." ) );
-- }
-- return;
-- }
--
-- /*
-- * the mxit server has flood detection and it prevents you from sending messages to fast.
-- * this is a self defense mechanism, a very annoying feature. so the client must ensure that
-- * it does not send messages too fast otherwise mxit will ignore the user for 30 seconds.
-- * this is what we are trying to avoid here..
-- */
-- if ( session->q_fast_timer_id == 0 ) {
-- /* the fast timer has not been set yet */
-- if ( session->last_tx > ( now - MXIT_TX_DELAY ) ) {
-- /* we need to wait a little before sending the next packet, so schedule a wakeup call */
-- gint64 tdiff = now - ( session->last_tx );
-- guint delay = ( MXIT_TX_DELAY - tdiff ) + 9;
-- if ( delay <= 0 )
-- delay = MXIT_TX_DELAY;
-- session->q_fast_timer_id = purple_timeout_add( delay, mxit_manage_queue_fast, session );
-- }
-- else {
-- /* get the next packet from the queue to send */
-- packet = pop_tx_packet( session );
-- if ( packet != NULL ) {
-- /* there was a packet waiting to be sent to the server, now is the time to do something about it */
--
-- /* send the packet to MXit server */
-- mxit_send_packet( session, packet );
-- }
-- }
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Slow callback to manage the packet send queue.
-- *
-- * @param session The MXit session object
-- */
--gboolean mxit_manage_queue_slow( gpointer user_data )
--{
-- struct MXitSession* session = (struct MXitSession*) user_data;
--
-- mxit_manage_queue( session );
--
-- /* continue running */
-- return TRUE;
--}
--
--
--/*------------------------------------------------------------------------
-- * Fast callback to manage the packet send queue.
-- *
-- * @param session The MXit session object
-- */
--gboolean mxit_manage_queue_fast( gpointer user_data )
--{
-- struct MXitSession* session = (struct MXitSession*) user_data;
--
-- session->q_fast_timer_id = 0;
-- mxit_manage_queue( session );
--
-- /* stop running */
-- return FALSE;
--}
--
--
--/*------------------------------------------------------------------------
-- * Callback to manage HTTP server polling (HTTP connections ONLY)
-- *
-- * @param session The MXit session object
-- */
--gboolean mxit_manage_polling( gpointer user_data )
--{
-- struct MXitSession* session = (struct MXitSession*) user_data;
-- gboolean poll = FALSE;
-- gint64 now = mxit_now_milli();
-- int polldiff;
-- gint64 rxdiff;
--
-- if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) {
-- /* we only poll if we are actually logged in */
-- return TRUE;
-- }
--
-- /* calculate the time differences */
-- rxdiff = now - session->last_rx;
-- polldiff = now - session->http_last_poll;
--
-- if ( rxdiff < MXIT_HTTP_POLL_MIN ) {
-- /* we received some reply a few moments ago, so reset the poll interval */
-- session->http_interval = MXIT_HTTP_POLL_MIN;
-- }
-- else if ( session->http_last_poll < ( now - session->http_interval ) ) {
-- /* time to poll again */
-- poll = TRUE;
--
-- /* back-off some more with the polling */
-- session->http_interval = session->http_interval + ( session->http_interval / 2 );
-- if ( session->http_interval > MXIT_HTTP_POLL_MAX )
-- session->http_interval = MXIT_HTTP_POLL_MAX;
-- }
--
-- /* debugging */
-- //purple_debug_info( MXIT_PLUGIN_ID, "POLL TIMER: %i (%i,%i)\n", session->http_interval, rxdiff, polldiff );
--
-- if ( poll ) {
-- /* send poll request */
-- session->http_last_poll = mxit_now_milli();
-- mxit_send_poll( session );
-- }
--
-- return TRUE;
--}
--
--
--/*========================================================================================================================
-- * Send MXit operations.
-- */
--
--/*------------------------------------------------------------------------
-- * Send a ping/keepalive packet to MXit server.
-- *
-- * @param session The MXit session object
-- */
--void mxit_send_ping( struct MXitSession* session )
--{
-- /* queue packet for transmission */
-- mxit_queue_packet( session, NULL, 0, CP_CMD_PING );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a poll request to the HTTP server (HTTP connections ONLY).
-- *
-- * @param session The MXit session object
-- */
--void mxit_send_poll( struct MXitSession* session )
--{
-- /* queue packet for transmission */
-- mxit_queue_packet( session, NULL, 0, CP_CMD_POLL );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a logout packet to the MXit server.
-- *
-- * @param session The MXit session object
-- */
--void mxit_send_logout( struct MXitSession* session )
--{
-- /* queue packet for transmission */
-- mxit_queue_packet( session, NULL, 0, CP_CMD_LOGOUT );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a register packet to the MXit server.
-- *
-- * @param session The MXit session object
-- */
--void mxit_send_register( struct MXitSession* session )
--{
-- struct MXitProfile* profile = session->profile;
-- const char* locale;
-- char data[CP_MAX_PACKET];
-- int datalen;
-- char* clientVersion;
-- unsigned int features = MXIT_CP_FEATURES;
--
-- locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
--
-- /* Voice and Video supported */
-- if (mxit_audio_enabled() && mxit_video_enabled())
-- features |= (MXIT_CF_VOICE | MXIT_CF_VIDEO);
-- else if (mxit_audio_enabled())
-- features |= MXIT_CF_VOICE;
--
-- /* generate client version string (eg, P-2.7.10-Y-PURPLE) */
-- clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM );
--
-- /* convert the packet to a byte stream */
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%s%c%s%c%i%c%s%c" /* "ms"=password\1version\1maxreplyLen\1name\1 */
-- "%s%c%i%c%s%c%s%c" /* dateOfBirth\1gender\1location\1capabilities\1 */
-- "%s%c%i%c%s%c%s" /* dc\1features\1dialingcode\1locale */
-- "%c%i%c%i", /* \1protocolVer\1lastRosterUpdate */
-- session->encpwd, CP_FLD_TERM, clientVersion, CP_FLD_TERM, CP_MAX_FILESIZE, CP_FLD_TERM, profile->nickname, CP_FLD_TERM,
-- profile->birthday, CP_FLD_TERM, ( profile->male ) ? 1 : 0, CP_FLD_TERM, MXIT_DEFAULT_LOC, CP_FLD_TERM, MXIT_CP_CAP, CP_FLD_TERM,
-- session->distcode, CP_FLD_TERM, features, CP_FLD_TERM, session->dialcode, CP_FLD_TERM, locale,
-- CP_FLD_TERM, MXIT_CP_PROTO_VESION, CP_FLD_TERM, 0
-- );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_REGISTER );
--
-- g_free( clientVersion );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a login packet to the MXit server.
-- *
-- * @param session The MXit session object
-- */
--void mxit_send_login( struct MXitSession* session )
--{
-- const char* splashId;
-- const char* locale;
-- char data[CP_MAX_PACKET];
-- int datalen;
-- char* clientVersion;
-- unsigned int features = MXIT_CP_FEATURES;
--
-- locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
--
-- /* Voice and Video supported */
-- if (mxit_audio_enabled() && mxit_video_enabled())
-- features |= (MXIT_CF_VOICE | MXIT_CF_VIDEO);
-- else if (mxit_audio_enabled())
-- features |= MXIT_CF_VOICE;
--
-- /* generate client version string (eg, P-2.7.10-Y-PURPLE) */
-- clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM );
--
-- /* convert the packet to a byte stream */
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%s%c%s%c%i%c" /* "ms"=password\1version\1getContacts\1 */
-- "%s%c%s%c%i%c" /* capabilities\1dc\1features\1 */
-- "%s%c%s%c" /* dialingcode\1locale\1 */
-- "%i%c%i%c%i", /* maxReplyLen\1protocolVer\1lastRosterUpdate */
-- session->encpwd, CP_FLD_TERM, clientVersion, CP_FLD_TERM, 1, CP_FLD_TERM,
-- MXIT_CP_CAP, CP_FLD_TERM, session->distcode, CP_FLD_TERM, features, CP_FLD_TERM,
-- session->dialcode, CP_FLD_TERM, locale, CP_FLD_TERM,
-- CP_MAX_FILESIZE, CP_FLD_TERM, MXIT_CP_PROTO_VESION, CP_FLD_TERM, 0
-- );
--
-- /* include "custom resource" information */
-- splashId = splash_current( session );
-- if ( splashId != NULL )
-- datalen += sprintf( data + datalen, "%ccr=%s", CP_REC_TERM, splashId );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_LOGIN );
--
-- g_free( clientVersion );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a chat message packet to the MXit server.
-- *
-- * @param session The MXit session object
-- * @param to The username of the recipient
-- * @param msg The message text
-- */
--void mxit_send_message( struct MXitSession* session, const char* to, const char* msg, gboolean parse_markup, gboolean is_command )
--{
-- char data[CP_MAX_PACKET];
-- char* markuped_msg;
-- int datalen;
-- int msgtype = ( is_command ? CP_MSGTYPE_COMMAND : CP_MSGTYPE_NORMAL );
--
-- /* first we need to convert the markup from libPurple to MXit format */
-- if ( parse_markup )
-- markuped_msg = mxit_convert_markup_tx( msg, &msgtype );
-- else
-- markuped_msg = g_strdup( msg );
--
-- /* convert the packet to a byte stream */
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%s%c%s%c%i%c%i", /* "ms"=jid\1msg\1type\1flags */
-- to, CP_FLD_TERM, markuped_msg, CP_FLD_TERM, msgtype, CP_FLD_TERM, CP_MSG_MARKUP | CP_MSG_EMOTICON
-- );
--
-- /* free the resources */
-- g_free( markuped_msg );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_TX_MSG );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a extended profile request packet to the MXit server.
-- *
-- * @param session The MXit session object
-- * @param username Username who's profile is being requested (NULL = our own)
-- * @param nr_attribs Number of attributes being requested
-- * @param attribute The names of the attributes
-- */
--void mxit_send_extprofile_request( struct MXitSession* session, const char* username, unsigned int nr_attrib, const char* attribute[] )
--{
-- char data[CP_MAX_PACKET];
-- int datalen;
-- unsigned int i;
--
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%s%c%i", /* "ms="mxitid\1nr_attributes */
-- ( username ? username : "" ), CP_FLD_TERM, nr_attrib
-- );
--
-- /* add attributes */
-- for ( i = 0; i < nr_attrib; i++ )
-- datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_GET );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send an update profile packet to the MXit server.
-- *
-- * @param session The MXit session object
-- * @param password The new password to be used for logging in (optional)
-- * @param nr_attrib The number of attributes
-- * @param attributes String containing the attribute-name, attribute-type and value (seperated by '\01')
-- */
--void mxit_send_extprofile_update( struct MXitSession* session, const char* password, unsigned int nr_attrib, const char* attributes )
--{
-- char data[CP_MAX_PACKET];
-- gchar** parts = NULL;
-- int datalen;
-- unsigned int i;
--
-- if ( attributes )
-- parts = g_strsplit( attributes, "\01", 1 + ( nr_attrib * 3 ) );
--
-- /* convert the packet to a byte stream */
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%s%c%i", /* "ms"=password\1nr_attibutes */
-- ( password ) ? password : "", CP_FLD_TERM, nr_attrib
-- );
--
-- /* add attributes */
-- for ( i = 1; i < nr_attrib * 3; i+=3 )
-- datalen += sprintf( data + datalen, "%c%s%c%s%c%s", /* \1name\1type\1value */
-- CP_FLD_TERM, parts[i], CP_FLD_TERM, parts[i + 1], CP_FLD_TERM, parts[i + 2] );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_SET );
--
-- /* freeup the memory */
-- g_strfreev( parts );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send packet to request list of suggested friends.
-- *
-- * @param session The MXit session object
-- * @param max Maximum number of results to return
-- * @param nr_attribs Number of attributes being requested
-- * @param attribute The names of the attributes
-- */
--void mxit_send_suggest_friends( struct MXitSession* session, int max, unsigned int nr_attrib, const char* attribute[] )
--{
-- char data[CP_MAX_PACKET];
-- int datalen;
-- unsigned int i;
--
-- /* convert the packet to a byte stream */
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
-- CP_SUGGEST_FRIENDS, CP_FLD_TERM, "", CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
--
-- /* add attributes */
-- for ( i = 0; i < nr_attrib; i++ )
-- datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send packet to perform a search for users.
-- *
-- * @param session The MXit session object
-- * @param max Maximum number of results to return
-- * @param text The search text
-- * @param nr_attribs Number of attributes being requested
-- * @param attribute The names of the attributes
-- */
--void mxit_send_suggest_search( struct MXitSession* session, int max, const char* text, unsigned int nr_attrib, const char* attribute[] )
--{
-- char data[CP_MAX_PACKET];
-- int datalen;
-- unsigned int i;
--
-- /* convert the packet to a byte stream */
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
-- CP_SUGGEST_SEARCH, CP_FLD_TERM, text, CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
--
-- /* add attributes */
-- for ( i = 0; i < nr_attrib; i++ )
-- datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a presence update packet to the MXit server.
-- *
-- * @param session The MXit session object
-- * @param presence The presence (as per MXit types)
-- * @param statusmsg The status message (can be NULL)
-- */
--void mxit_send_presence( struct MXitSession* session, int presence, const char* statusmsg )
--{
-- char data[CP_MAX_PACKET];
-- int datalen;
--
-- /* convert the packet to a byte stream */
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%i%c", /* "ms"=show\1status */
-- presence, CP_FLD_TERM
-- );
--
-- /* append status message (if one is set) */
-- if ( statusmsg )
-- datalen += sprintf( data + datalen, "%s", statusmsg );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_STATUS );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a mood update packet to the MXit server.
-- *
-- * @param session The MXit session object
-- * @param mood The mood (as per MXit types)
-- */
--void mxit_send_mood( struct MXitSession* session, int mood )
--{
-- char data[CP_MAX_PACKET];
-- int datalen;
--
-- /* convert the packet to a byte stream */
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%i", /* "ms"=mood */
-- mood
-- );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_MOOD );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send an invite contact packet to the MXit server.
-- *
-- * @param session The MXit session object
-- * @param username The username of the contact being invited
-- * @param mxitid Indicates the username is a MXitId.
-- * @param alias Our alias for the contact
-- * @param groupname Group in which contact should be stored.
-- * @param message Invite message
-- */
--void mxit_send_invite( struct MXitSession* session, const char* username, gboolean mxitid, const char* alias, const char* groupname, const char* message )
--{
-- char data[CP_MAX_PACKET];
-- int datalen;
--
-- /* convert the packet to a byte stream */
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%s%c%s%c%s%c%i%c%s%c%i", /* "ms"=group \1 username \1 alias \1 type \1 msg \1 isuserid */
-- groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias,
-- CP_FLD_TERM, MXIT_TYPE_MXIT, CP_FLD_TERM,
-- ( message ? message : "" ), CP_FLD_TERM,
-- ( mxitid ? 0 : 1 )
-- );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_INVITE );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a remove contact packet to the MXit server.
-- *
-- * @param session The MXit session object
-- * @param username The username of the contact being removed
-- */
--void mxit_send_remove( struct MXitSession* session, const char* username )
--{
-- char data[CP_MAX_PACKET];
-- int datalen;
--
-- /* convert the packet to a byte stream */
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%s", /* "ms"=username */
-- username
-- );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_REMOVE );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send an accept subscription (invite) packet to the MXit server.
-- *
-- * @param session The MXit session object
-- * @param username The username of the contact being accepted
-- * @param alias Our alias for the contact
-- */
--void mxit_send_allow_sub( struct MXitSession* session, const char* username, const char* alias )
--{
-- char data[CP_MAX_PACKET];
-- int datalen;
--
-- /* convert the packet to a byte stream */
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%s%c%s%c%s", /* "ms"=username\1group\1alias */
-- username, CP_FLD_TERM, "", CP_FLD_TERM, alias
-- );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_ALLOW );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send an deny subscription (invite) packet to the MXit server.
-- *
-- * @param session The MXit session object
-- * @param username The username of the contact being denied
-- * @param reason The message describing the reason for the rejection (can be NULL).
-- */
--void mxit_send_deny_sub( struct MXitSession* session, const char* username, const char* reason )
--{
-- char data[CP_MAX_PACKET];
-- int datalen;
--
-- /* convert the packet to a byte stream */
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%s", /* "ms"=username */
-- username
-- );
--
-- /* append reason (if one is set) */
-- if ( reason )
-- datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, reason );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_DENY );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send an update contact packet to the MXit server.
-- *
-- * @param session The MXit session object
-- * @param username The username of the contact being denied
-- * @param alias Our alias for the contact
-- * @param groupname Group in which contact should be stored.
-- */
--void mxit_send_update_contact( struct MXitSession* session, const char* username, const char* alias, const char* groupname )
--{
-- char data[CP_MAX_PACKET];
-- int datalen;
--
-- /* convert the packet to a byte stream */
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%s%c%s%c%s", /* "ms"=groupname\1username\1alias */
-- groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias
-- );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_UPDATE );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a splash-screen click event packet.
-- *
-- * @param session The MXit session object
-- * @param splashid The identifier of the splash-screen
-- */
--void mxit_send_splashclick( struct MXitSession* session, const char* splashid )
--{
-- char data[CP_MAX_PACKET];
-- int datalen;
--
-- /* convert the packet to a byte stream */
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%s", /* "ms"=splashId */
-- splashid
-- );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_SPLASHCLICK );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a message event packet.
-- *
-- * @param session The MXit session object
-- * @param to The username of the original sender (ie, recipient of the event)
-- * @param id The identifier of the event (received in message)
-- * @param event Identified the type of event
-- */
--void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event)
--{
-- char data[CP_MAX_PACKET];
-- int datalen;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_msgevent: to=%s id=%s event=%i\n", to, id, event );
--
-- /* convert the packet to a byte stream */
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%s%c%s%c%i", /* "ms"=contactAddress \1 id \1 event */
-- to, CP_FLD_TERM, id, CP_FLD_TERM, event
-- );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_MSGEVENT );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send packet to create a MultiMX room.
-- *
-- * @param session The MXit session object
-- * @param groupname Name of the room to create
-- * @param nr_usernames Number of users in initial invite
-- * @param usernames The usernames of the users in the initial invite
-- */
--void mxit_send_groupchat_create( struct MXitSession* session, const char* groupname, int nr_usernames, const char* usernames[] )
--{
-- char data[CP_MAX_PACKET];
-- int datalen;
-- int i;
--
-- /* convert the packet to a byte stream */
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%s%c%i", /* "ms"=roomname\1nr_jids\1jid0\1..\1jidN */
-- groupname, CP_FLD_TERM, nr_usernames
-- );
--
-- /* add usernames */
-- for ( i = 0; i < nr_usernames; i++ )
-- datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, usernames[i] );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_CREATE );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send packet to invite users to existing MultiMX room.
-- *
-- * @param session The MXit session object
-- * @param roomid The unique RoomID for the MultiMx room.
-- * @param nr_usernames Number of users being invited
-- * @param usernames The usernames of the users being invited
-- */
--void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid, int nr_usernames, const char* usernames[] )
--{
-- char data[CP_MAX_PACKET];
-- int datalen;
-- int i;
--
-- /* convert the packet to a byte stream */
-- datalen = snprintf( data, sizeof( data ),
-- "ms=%s%c%i", /* "ms"=roomid\1nr_jids\1jid0\1..\1jidN */
-- roomid, CP_FLD_TERM, nr_usernames
-- );
--
-- /* add usernames */
-- for ( i = 0; i < nr_usernames; i++ )
-- datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, usernames[i] );
--
-- /* queue packet for transmission */
-- mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_INVITE );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a "send file direct" multimedia packet.
-- *
-- * @param session The MXit session object
-- * @param username The username of the recipient
-- * @param filename The name of the file being sent
-- * @param buf The content of the file
-- * @param buflen The length of the file contents
-- */
--void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen )
--{
-- char data[CP_MAX_PACKET];
-- int datalen = 0;
-- gchar* chunk;
-- int size;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %i bytes to user '%s'\n", filename, buflen, username );
--
-- /* convert the packet to a byte stream */
-- datalen = sprintf( data, "ms=" );
--
-- /* map chunk header over data buffer */
-- chunk = &data[datalen];
--
-- size = mxit_chunk_create_senddirect( chunk_data( chunk ), username, filename, buf, buflen );
-- if ( size < 0 ) {
-- purple_debug_error( MXIT_PLUGIN_ID, "Error creating senddirect chunk (%i)\n", size );
-- return;
-- }
--
-- set_chunk_type( chunk, CP_CHUNK_DIRECT_SND );
-- set_chunk_length( chunk, size );
-- datalen += MXIT_CHUNK_HEADER_SIZE + size;
--
-- /* send the byte stream to the mxit server */
-- mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a "reject file" multimedia packet.
-- *
-- * @param session The MXit session object
-- * @param fileid A unique ID that identifies this file
-- */
--void mxit_send_file_reject( struct MXitSession* session, const char* fileid )
--{
-- char data[CP_MAX_PACKET];
-- int datalen = 0;
-- gchar* chunk;
-- int size;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_reject\n" );
--
-- /* convert the packet to a byte stream */
-- datalen = sprintf( data, "ms=" );
--
-- /* map chunk header over data buffer */
-- chunk = &data[datalen];
--
-- size = mxit_chunk_create_reject( chunk_data( chunk ), fileid );
-- if ( size < 0 ) {
-- purple_debug_error( MXIT_PLUGIN_ID, "Error creating reject chunk (%i)\n", size );
-- return;
-- }
--
-- set_chunk_type( chunk, CP_CHUNK_REJECT );
-- set_chunk_length( chunk, size );
-- datalen += MXIT_CHUNK_HEADER_SIZE + size;
--
-- /* send the byte stream to the mxit server */
-- mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a "get file" multimedia packet.
-- *
-- * @param session The MXit session object
-- * @param fileid A unique ID that identifies this file
-- * @param filesize The number of bytes to retrieve
-- * @param offset Offset in file at which to start retrieving
-- */
--void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset )
--{
-- char data[CP_MAX_PACKET];
-- int datalen = 0;
-- gchar* chunk;
-- int size;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_accept\n" );
--
-- /* convert the packet to a byte stream */
-- datalen = sprintf( data, "ms=" );
--
-- /* map chunk header over data buffer */
-- chunk = &data[datalen];
--
-- size = mxit_chunk_create_get( chunk_data(chunk), fileid, filesize, offset );
-- if ( size < 0 ) {
-- purple_debug_error( MXIT_PLUGIN_ID, "Error creating getfile chunk (%i)\n", size );
-- return;
-- }
--
-- set_chunk_type( chunk, CP_CHUNK_GET );
-- set_chunk_length( chunk, size );
-- datalen += MXIT_CHUNK_HEADER_SIZE + size;
--
-- /* send the byte stream to the mxit server */
-- mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a "received file" multimedia packet.
-- *
-- * @param session The MXit session object
-- * @param status The status of the file-transfer
-- */
--void mxit_send_file_received( struct MXitSession* session, const char* fileid, short status )
--{
-- char data[CP_MAX_PACKET];
-- int datalen = 0;
-- gchar* chunk;
-- int size;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_received\n" );
--
-- /* convert the packet to a byte stream */
-- datalen = sprintf( data, "ms=" );
--
-- /* map chunk header over data buffer */
-- chunk = &data[datalen];
--
-- size = mxit_chunk_create_received( chunk_data(chunk), fileid, status );
-- if ( size < 0 ) {
-- purple_debug_error( MXIT_PLUGIN_ID, "Error creating received chunk (%i)\n", size );
-- return;
-- }
--
-- set_chunk_type( chunk, CP_CHUNK_RECEIVED );
-- set_chunk_length( chunk, size );
-- datalen += MXIT_CHUNK_HEADER_SIZE + size;
--
-- /* send the byte stream to the mxit server */
-- mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a "set avatar" multimedia packet.
-- *
-- * @param session The MXit session object
-- * @param data The avatar data
-- * @param buflen The length of the avatar data
-- */
--void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen )
--{
-- char data[CP_MAX_PACKET];
-- int datalen = 0;
-- gchar* chunk;
-- int size;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %i bytes\n", avatarlen );
--
-- /* convert the packet to a byte stream */
-- datalen = sprintf( data, "ms=" );
--
-- /* map chunk header over data buffer */
-- chunk = &data[datalen];
--
-- size = mxit_chunk_create_set_avatar( chunk_data(chunk), avatar, avatarlen );
-- if ( size < 0 ) {
-- purple_debug_error( MXIT_PLUGIN_ID, "Error creating set avatar chunk (%i)\n", size );
-- return;
-- }
--
-- set_chunk_type( chunk, CP_CHUNK_SET_AVATAR );
-- set_chunk_length( chunk, size );
-- datalen += MXIT_CHUNK_HEADER_SIZE + size;
--
-- /* send the byte stream to the mxit server */
-- mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
--}
--
--
--/*------------------------------------------------------------------------
-- * Send a "get avatar" multimedia packet.
-- *
-- * @param session The MXit session object
-- * @param mxitId The username who's avatar to request
-- * @param avatarId The id of the avatar image (as string)
-- * @param data The avatar data
-- * @param buflen The length of the avatar data
-- */
--void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const char* avatarId )
--{
-- char data[CP_MAX_PACKET];
-- int datalen = 0;
-- gchar* chunk;
-- int size;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_avatar: %s\n", mxitId );
--
-- /* convert the packet to a byte stream */
-- datalen = sprintf( data, "ms=" );
--
-- /* map chunk header over data buffer */
-- chunk = &data[datalen];
--
-- size = mxit_chunk_create_get_avatar( chunk_data(chunk), mxitId, avatarId );
-- if ( size < 0 ) {
-- purple_debug_error( MXIT_PLUGIN_ID, "Error creating get avatar chunk (%i)\n", size );
-- return;
-- }
--
-- set_chunk_type( chunk, CP_CHUNK_GET_AVATAR );
-- set_chunk_length( chunk, size );
-- datalen += MXIT_CHUNK_HEADER_SIZE + size;
--
-- /* send the byte stream to the mxit server */
-- mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
--}
--
--
--/*------------------------------------------------------------------------
-- * Process a login message packet.
-- *
-- * @param session The MXit session object
-- * @param records The packet's data records
-- * @param rcount The number of data records
-- */
--static void mxit_parse_cmd_login( struct MXitSession* session, struct record** records, int rcount )
--{
-- PurpleStatus* status;
-- int presence;
-- const char* statusmsg;
-- const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME,
-- CP_PROFILE_TITLE, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_EMAIL,
-- CP_PROFILE_MOBILENR, CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME, CP_PROFILE_RELATIONSHIP, CP_PROFILE_FLAGS };
--
-- purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
--
-- /* we were not yet logged in so we need to complete the login sequence here */
-- session->flags |= MXIT_FLAG_LOGGEDIN;
-- purple_connection_update_progress( session->con, _( "Successfully Logged In..." ), 3, 4 );
-- purple_connection_set_state( session->con, PURPLE_CONNECTED );
--
-- /* save extra info if this is a HTTP connection */
-- if ( session->http ) {
-- /* save the http server to use for this session */
-- g_strlcpy( session->http_server, records[1]->fields[3]->data, sizeof( session->http_server ) );
--
-- /* save the session id */
-- session->http_sesid = atoi( records[0]->fields[0]->data );
-- }
--
-- /* extract UserId (from protocol 5.9) */
-- if ( records[1]->fcount >= 9 )
-- session->uid = g_strdup( records[1]->fields[8]->data );
--
-- /* extract VoIP server (from protocol 6.2) */
-- if ( records[1]->fcount >= 11 )
-- g_strlcpy( session->voip_server, records[1]->fields[10]->data, sizeof( session->voip_server ) );
--
-- /* display the current splash-screen */
-- if ( splash_popup_enabled( session ) )
-- splash_display( session );
--
-- /* update presence status */
-- status = purple_account_get_active_status( session->acc );
-- presence = mxit_convert_presence( purple_status_get_id( status ) );
-- statusmsg = purple_status_get_attr_string( status, "message" );
--
-- if ( ( presence != MXIT_PRESENCE_ONLINE ) || ( statusmsg ) ) {
-- /* when logging into MXit, your default presence is online. but with the UI, one can change
-- * the presence to whatever. in the case where its changed to a different presence setting
-- * we need to send an update to the server, otherwise the user's presence will be out of
-- * sync between the UI and MXit.
-- */
-- char* statusmsg1 = purple_markup_strip_html( statusmsg );
-- char* statusmsg2 = g_strndup( statusmsg1, CP_MAX_STATUS_MSG );
--
-- mxit_send_presence( session, presence, statusmsg2 );
--
-- g_free( statusmsg1 );
-- g_free( statusmsg2 );
-- }
--
-- /* retrieve our MXit profile */
-- mxit_send_extprofile_request( session, NULL, ARRAY_SIZE( profilelist ), profilelist );
--}
--
--
--/*------------------------------------------------------------------------
-- * Process a received message packet.
-- *
-- * @param session The MXit session object
-- * @param records The packet's data records
-- * @param rcount The number of data records
-- */
--static void mxit_parse_cmd_message( struct MXitSession* session, struct record** records, int rcount )
--{
-- struct RXMsgData* mx = NULL;
-- char* message = NULL;
-- char* sender = NULL;
-- int msglen = 0;
-- int msgflags = 0;
-- int msgtype = 0;
--
-- if ( ( rcount == 1 ) || ( records[0]->fcount < 2 ) || ( records[1]->fcount == 0 ) || ( records[1]->fields[0]->len == 0 ) ) {
-- /* packet contains no message or an empty message */
-- return;
-- }
--
-- message = records[1]->fields[0]->data;
-- msglen = strlen( message );
--
-- /* strip off dummy domain */
-- sender = records[0]->fields[0]->data;
-- mxit_strip_domain( sender );
--
--#ifdef DEBUG_PROTOCOL
-- purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", sender );
--#endif
--
-- /* decode message flags (if any) */
-- if ( records[0]->fcount >= 5 )
-- msgflags = atoi( records[0]->fields[4]->data );
-- msgtype = atoi( records[0]->fields[2]->data );
--
-- if ( msgflags & CP_MSG_PWD_ENCRYPTED ) {
-- /* this is a password encrypted message. we do not currently support those so ignore it */
-- PurpleBuddy* buddy;
-- const char* name;
-- char msg[128];
--
-- buddy = purple_find_buddy( session->acc, sender );
-- if ( buddy )
-- name = purple_buddy_get_alias( buddy );
-- else
-- name = sender;
-- g_snprintf( msg, sizeof( msg ), _( "%s sent you an encrypted message, but it is not supported on this client." ), name );
-- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), msg );
-- return;
-- }
-- else if ( msgflags & CP_MSG_TL_ENCRYPTED ) {
-- /* this is a transport-layer encrypted message. */
-- message = mxit_decrypt_message( session, message );
-- if ( !message ) {
-- /* could not be decrypted */
-- serv_got_im( session->con, sender, _( "An encrypted message was received which could not be decrypted." ), PURPLE_MESSAGE_ERROR, time( NULL ) );
-- return;
-- }
-- }
--
-- if ( msgflags & CP_MSG_NOTIFY_DELIVERY ) {
-- /* delivery notification is requested */
-- if ( records[0]->fcount >= 4 )
-- mxit_send_msgevent( session, sender, records[0]->fields[3]->data, CP_MSGEVENT_DELIVERED );
-- }
--
-- /* create and initialise new markup struct */
-- mx = g_new0( struct RXMsgData, 1 );
-- mx->msg = g_string_sized_new( msglen );
-- mx->session = session;
-- mx->from = g_strdup( sender );
-- mx->timestamp = atoi( records[0]->fields[1]->data );
-- mx->got_img = FALSE;
-- mx->chatid = -1;
-- mx->img_count = 0;
--
-- /* update list of active chats */
-- if ( !find_active_chat( session->active_chats, mx->from ) ) {
-- session->active_chats = g_list_append( session->active_chats, g_strdup( mx->from ) );
-- }
--
-- if ( is_multimx_contact( session, mx->from ) ) {
-- /* this is a MultiMx chatroom message */
-- multimx_message_received( mx, message, msglen, msgtype, msgflags );
-- }
-- else {
-- mxit_parse_markup( mx, message, msglen, msgtype, msgflags );
-- }
--
-- /* we are now done parsing the message */
-- mx->converted = TRUE;
-- if ( mx->img_count == 0 ) {
-- /* we have all the data we need for this message to be displayed now. */
-- mxit_show_message( mx );
-- }
-- else {
-- /* this means there are still images outstanding for this message and
-- * still need to wait for them before we can display the message.
-- * so the image received callback function will eventually display
-- * the message. */
-- }
--
-- /* cleanup */
-- if ( msgflags & CP_MSG_TL_ENCRYPTED )
-- g_free( message );
--}
--
--
--/*------------------------------------------------------------------------
-- * Process a received subscription request packet.
-- *
-- * @param session The MXit session object
-- * @param records The packet's data records
-- * @param rcount The number of data records
-- */
--static void mxit_parse_cmd_new_sub( struct MXitSession* session, struct record** records, int rcount )
--{
-- struct contact* contact;
-- struct record* rec;
-- int i;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_new_sub (%i recs)\n", rcount );
--
-- for ( i = 0; i < rcount; i++ ) {
-- rec = records[i];
--
-- if ( rec->fcount < 4 ) {
-- purple_debug_error( MXIT_PLUGIN_ID, "BAD SUBSCRIPTION RECORD! %i fields\n", rec->fcount );
-- break;
-- }
--
-- /* build up a new contact info struct */
-- contact = g_new0( struct contact, 1 );
--
-- g_strlcpy( contact->username, rec->fields[0]->data, sizeof( contact->username ) );
-- mxit_strip_domain( contact->username ); /* remove dummy domain */
-- g_strlcpy( contact->alias, rec->fields[1]->data, sizeof( contact->alias ) );
-- contact->type = atoi( rec->fields[2]->data );
--
-- if ( rec->fcount >= 5 ) {
-- /* there is a personal invite message attached */
-- if ( ( rec->fields[4]->data ) && ( strlen( rec->fields[4]->data ) > 0 ) )
-- contact->msg = strdup( rec->fields[4]->data );
-- }
--
-- /* handle the subscription */
-- if ( contact-> type == MXIT_TYPE_MULTIMX ) { /* subscription to a MultiMX room */
-- char* creator = NULL;
--
-- if ( rec->fcount >= 6 )
-- creator = rec->fields[5]->data;
--
-- multimx_invite( session, contact, creator );
-- }
-- else
-- mxit_new_subscription( session, contact );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Process a received contact update packet.
-- *
-- * @param session The MXit session object
-- * @param records The packet's data records
-- * @param rcount The number of data records
-- */
--static void mxit_parse_cmd_contact( struct MXitSession* session, struct record** records, int rcount )
--{
-- struct contact* contact = NULL;
-- struct record* rec;
-- int i;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_contact (%i recs)\n", rcount );
--
-- for ( i = 0; i < rcount; i++ ) {
-- rec = records[i];
--
-- if ( rec->fcount < 6 ) {
-- purple_debug_error( MXIT_PLUGIN_ID, "BAD CONTACT RECORD! %i fields\n", rec->fcount );
-- break;
-- }
--
-- /* build up a new contact info struct */
-- contact = g_new0( struct contact, 1 );
--
-- g_strlcpy( contact->groupname, rec->fields[0]->data, sizeof( contact->groupname ) );
-- g_strlcpy( contact->username, rec->fields[1]->data, sizeof( contact->username ) );
-- mxit_strip_domain( contact->username ); /* remove dummy domain */
-- g_strlcpy( contact->alias, rec->fields[2]->data, sizeof( contact->alias ) );
--
-- contact->presence = atoi( rec->fields[3]->data );
-- contact->type = atoi( rec->fields[4]->data );
-- contact->mood = atoi( rec->fields[5]->data );
--
-- if ( rec->fcount > 6 ) {
-- /* added in protocol 5.9 - flags & subtype */
-- contact->flags = atoi( rec->fields[6]->data );
-- contact->subtype = rec->fields[7]->data[0];
-- }
-- if ( rec->fcount > 8 ) {
-- /* added in protocol 6.0 - reject message */
-- contact->msg = g_strdup( rec->fields[8]->data );
-- }
--
-- /* add the contact to the buddy list */
-- if ( contact-> type == MXIT_TYPE_MULTIMX ) /* contact is a MultiMX room */
-- multimx_created( session, contact );
-- else
-- mxit_update_contact( session, contact );
-- }
--
-- if ( !( session->flags & MXIT_FLAG_FIRSTROSTER ) ) {
-- session->flags |= MXIT_FLAG_FIRSTROSTER;
-- mxit_update_blist( session );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Process a received presence update packet.
-- *
-- * @param session The MXit session object
-- * @param records The packet's data records
-- * @param rcount The number of data records
-- */
--static void mxit_parse_cmd_presence( struct MXitSession* session, struct record** records, int rcount )
--{
-- int i;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_presence (%i recs)\n", rcount );
--
-- for ( i = 0; i < rcount; i++ ) {
-- struct record* rec = records[i];
-- int flags = 0;
--
-- if ( rec->fcount < 6 ) {
-- purple_debug_error( MXIT_PLUGIN_ID, "BAD PRESENCE RECORD! %i fields\n", rec->fcount );
-- break;
-- }
--
-- /*
-- * The format of the record is:
-- * contactAddressN \1 presenceN \1 moodN \1 customMoodN \1 statusMsgN \1 avatarIdN [ \1 flagsN ]
-- */
-- mxit_strip_domain( rec->fields[0]->data ); /* contactAddress */
--
-- if ( rec->fcount >= 7 ) /* flags field is included */
-- flags = atoi( rec->fields[6]->data );
--
-- mxit_update_buddy_presence( session, rec->fields[0]->data, atoi( rec->fields[1]->data ), atoi( rec->fields[2]->data ),
-- rec->fields[3]->data, rec->fields[4]->data, flags );
-- mxit_update_buddy_avatar( session, rec->fields[0]->data, rec->fields[5]->data );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Process a received extended profile packet.
-- *
-- * @param session The MXit session object
-- * @param records The packet's data records
-- * @param rcount The number of data records
-- */
--static void mxit_parse_cmd_extprofile( struct MXitSession* session, struct record** records, int rcount )
--{
-- const char* mxitId = records[0]->fields[0]->data;
-- struct MXitProfile* profile = NULL;
-- int count;
-- int i;
-- const char* avatarId = NULL;
-- char* statusMsg = NULL;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_extprofile: profile for '%s'\n", mxitId );
--
-- if ( ( records[0]->fields[0]->len == 0 ) || ( session->uid && ( strcmp( session->uid, records[0]->fields[0]->data ) == 0 ) ) ) {
-- /* No UserId or Our UserId provided, so this must be our own profile information */
-- if ( session->profile == NULL )
-- session->profile = g_new0( struct MXitProfile, 1 );
-- profile = session->profile;
-- }
-- else {
-- /* is a buddy's profile */
-- profile = g_new0( struct MXitProfile, 1 );
-- }
--
-- /* set the count for attributes */
-- count = atoi( records[0]->fields[1]->data );
--
-- for ( i = 0; i < count; i++ ) {
-- char* fname;
-- char* fvalue;
-- char* fstatus;
-- int f = ( i * 3 ) + 2;
--
-- fname = records[0]->fields[f]->data; /* field name */
-- fvalue = records[0]->fields[f + 1]->data; /* field value */
-- fstatus = records[0]->fields[f + 2]->data; /* field status */
--
-- /* first check the status on the returned attribute */
-- if ( fstatus[0] != '0' ) {
-- /* error: attribute requested was NOT found */
-- purple_debug_error( MXIT_PLUGIN_ID, "Bad profile status on attribute '%s' \n", fname );
-- continue;
-- }
--
-- if ( strcmp( CP_PROFILE_BIRTHDATE, fname ) == 0 ) {
-- /* birthdate */
-- if ( records[0]->fields[f + 1]->len > 10 ) {
-- fvalue[10] = '\0';
-- records[0]->fields[f + 1]->len = 10;
-- }
-- memcpy( profile->birthday, fvalue, records[0]->fields[f + 1]->len );
-- }
-- else if ( strcmp( CP_PROFILE_GENDER, fname ) == 0 ) {
-- /* gender */
-- profile->male = ( fvalue[0] == '1' );
-- }
-- else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) {
-- /* nickname */
-- g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) );
-- }
-- else if ( strcmp( CP_PROFILE_STATUS, fname ) == 0 ) {
-- /* status message - just keep a reference to the value */
-- statusMsg = g_markup_escape_text( fvalue, -1 );
-- }
-- else if ( strcmp( CP_PROFILE_AVATAR, fname ) == 0 ) {
-- /* avatar id - just keep a reference to the value */
-- avatarId = fvalue;
-- }
-- else if ( strcmp( CP_PROFILE_TITLE, fname ) == 0 ) {
-- /* title */
-- g_strlcpy( profile->title, fvalue, sizeof( profile->title ) );
-- }
-- else if ( strcmp( CP_PROFILE_FIRSTNAME, fname ) == 0 ) {
-- /* first name */
-- g_strlcpy( profile->firstname, fvalue, sizeof( profile->firstname ) );
-- }
-- else if ( strcmp( CP_PROFILE_LASTNAME, fname ) == 0 ) {
-- /* last name */
-- g_strlcpy( profile->lastname, fvalue, sizeof( profile->lastname ) );
-- }
-- else if ( strcmp( CP_PROFILE_EMAIL, fname ) == 0 ) {
-- /* email address */
-- g_strlcpy( profile->email, fvalue, sizeof( profile->email ) );
-- }
-- else if ( strcmp( CP_PROFILE_MOBILENR, fname ) == 0 ) {
-- /* mobile number */
-- g_strlcpy( profile->mobilenr, fvalue, sizeof( profile->mobilenr ) );
-- }
-- else if ( strcmp( CP_PROFILE_REGCOUNTRY, fname ) == 0 ) {
-- /* registered country */
-- g_strlcpy( profile->regcountry, fvalue, sizeof( profile->regcountry ) );
-- }
-- else if ( strcmp( CP_PROFILE_FLAGS, fname ) == 0 ) {
-- /* profile flags */
-- profile->flags = strtoll( fvalue, NULL, 10 );
-- }
-- else if ( strcmp( CP_PROFILE_LASTSEEN, fname ) == 0 ) {
-- /* last seen online */
-- profile->lastonline = strtoll( fvalue, NULL, 10 );
-- }
-- else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) {
-- /* where am I */
-- g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) );
-- }
-- else if ( strcmp( CP_PROFILE_ABOUTME, fname ) == 0) {
-- /* about me */
-- g_strlcpy( profile->aboutme, fvalue, sizeof( profile->aboutme ) );
-- }
-- else if ( strcmp( CP_PROFILE_RELATIONSHIP, fname ) == 0) {
-- /* relatinship status */
-- profile->relationship = strtol( fvalue, NULL, 10 );
-- }
-- else {
-- /* invalid profile attribute */
-- purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile attribute received '%s' \n", fname );
-- }
-- }
--
-- if ( profile != session->profile ) {
-- /* not our own profile */
-- struct contact* contact = NULL;
--
-- contact = get_mxit_invite_contact( session, mxitId );
-- if ( contact ) {
-- /* this is an invite, so update its profile info */
-- if ( ( statusMsg ) && ( strlen( statusMsg ) > 0 ) ) {
-- /* update the status message */
-- if ( contact->statusMsg )
-- g_free( contact->statusMsg );
-- contact->statusMsg = strdup( statusMsg );
-- }
-- else
-- contact->statusMsg = NULL;
-- if ( contact->profile )
-- g_free( contact->profile );
-- contact->profile = profile;
-- if ( ( avatarId ) && ( strlen( avatarId ) > 0 ) ) {
-- /* avatar must be requested for this invite before we can display it */
-- mxit_get_avatar( session, mxitId, avatarId );
-- if ( contact->avatarId )
-- g_free( contact->avatarId );
-- contact->avatarId = strdup( avatarId );
-- }
-- else {
-- /* display what we have */
-- contact->avatarId = NULL;
-- mxit_show_profile( session, mxitId, profile );
-- }
-- }
-- else {
-- /* this is a contact */
-- if ( avatarId )
-- mxit_update_buddy_avatar( session, mxitId, avatarId );
--
-- if ( ( statusMsg ) && ( strlen( statusMsg ) > 0 ) ) {
-- /* update the status message */
-- PurpleBuddy* buddy = NULL;
--
-- buddy = purple_find_buddy( session->acc, mxitId );
-- if ( buddy ) {
-- contact = purple_buddy_get_protocol_data( buddy );
-- if ( contact ) {
-- if ( contact->statusMsg )
-- g_free( contact->statusMsg );
-- contact->statusMsg = strdup( statusMsg );
-- }
-- }
-- }
--
-- /* show the profile */
-- mxit_show_profile( session, mxitId, profile );
-- g_free( profile );
-- }
-- }
--
-- g_free( statusMsg );
--}
--
--
--/*------------------------------------------------------------------------
-- * Process a received suggest-contacts packet.
-- *
-- * @param session The MXit session object
-- * @param records The packet's data records
-- * @param rcount The number of data records
-- */
--static void mxit_parse_cmd_suggestcontacts( struct MXitSession* session, struct record** records, int rcount )
--{
-- GList* entries = NULL;
-- int searchType;
-- int maxResults;
-- int count;
-- int i;
--
-- /*
-- * searchType \1 numSuggestions \1 total \1 numAttributes \1 name0 \1 name1 \1 ... \1 nameN \0
-- * userid \1 contactType \1 value0 \1 value1 ... valueN \0
-- * ...
-- * userid \1 contactType \1 value0 \1 value1 ... valueN
-- */
--
-- /* the type of results */
-- searchType = atoi( records[0]->fields[0]->data );
--
-- /* the maximum number of results */
-- maxResults = atoi( records[0]->fields[2]->data );
--
-- /* set the count for attributes */
-- count = atoi( records[0]->fields[3]->data );
--
-- for ( i = 1; i < rcount; i ++ ) {
-- struct record* rec = records[i];
-- struct MXitProfile* profile = g_new0( struct MXitProfile, 1 );
-- int j;
--
-- g_strlcpy( profile->userid, rec->fields[0]->data, sizeof( profile->userid ) );
-- // TODO: ContactType - User or Service
--
-- for ( j = 0; j < count; j++ ) {
-- char* fname;
-- char* fvalue = "";
--
-- fname = records[0]->fields[4 + j]->data; /* field name */
-- if ( records[i]->fcount > ( 2 + j ) )
-- fvalue = records[i]->fields[2 + j]->data; /* field value */
--
-- purple_debug_info( MXIT_PLUGIN_ID, " %s: field='%s' value='%s'\n", profile->userid, fname, fvalue );
--
-- if ( strcmp( CP_PROFILE_BIRTHDATE, fname ) == 0 ) {
-- /* birthdate */
-- g_strlcpy( profile->birthday, fvalue, sizeof( profile->birthday ) );
-- }
-- else if ( strcmp( CP_PROFILE_FIRSTNAME, fname ) == 0 ) {
-- /* first name */
-- g_strlcpy( profile->firstname, fvalue, sizeof( profile->firstname ) );
-- }
-- else if ( strcmp( CP_PROFILE_LASTNAME, fname ) == 0 ) {
-- /* last name */
-- g_strlcpy( profile->lastname, fvalue, sizeof( profile->lastname ) );
-- }
-- else if ( strcmp( CP_PROFILE_GENDER, fname ) == 0 ) {
-- /* gender */
-- profile->male = ( fvalue[0] == '1' );
-- }
-- else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) {
-- /* nickname */
-- g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) );
-- }
-- else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) {
-- /* where am I */
-- g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) );
-- }
-- /* ignore other attibutes */
-- }
--
-- entries = g_list_append( entries, profile );
-- }
--
-- /* display */
-- mxit_show_search_results( session, searchType, maxResults, entries );
--
-- /* cleanup */
-- g_list_foreach( entries, (GFunc)g_free, NULL );
--}
--
--/*------------------------------------------------------------------------
-- * Process a received message event packet.
-- *
-- * @param session The MXit session object
-- * @param records The packet's data records
-- * @param rcount The number of data records
-- */
--static void mxit_parse_cmd_msgevent( struct MXitSession* session, struct record** records, int rcount )
--{
-- int event;
--
-- /*
-- * contactAddress \1 dateTime \1 id \1 event
-- */
--
-- /* strip off dummy domain */
-- mxit_strip_domain( records[0]->fields[0]->data );
--
-- event = atoi( records[0]->fields[3]->data );
--
-- switch ( event ) {
-- case CP_MSGEVENT_TYPING : /* user is typing */
-- case CP_MSGEVENT_ANGRY : /* user is typing angrily */
-- serv_got_typing( session->con, records[0]->fields[0]->data, 0, PURPLE_TYPING );
-- break;
--
-- case CP_MSGEVENT_STOPPED : /* user has stopped typing */
-- serv_got_typing_stopped( session->con, records[0]->fields[0]->data );
-- break;
--
-- case CP_MSGEVENT_ERASING : /* user is erasing text */
-- case CP_MSGEVENT_DELIVERED : /* message was delivered */
-- case CP_MSGEVENT_DISPLAYED : /* message was viewed */
-- /* these are currently not supported by libPurple */
-- break;
--
-- default:
-- purple_debug_error( MXIT_PLUGIN_ID, "Unknown message event received (%i)\n", event );
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Return the length of a multimedia chunk
-- *
-- * @return The actual chunk data length in bytes
-- */
--static int get_chunk_len( const char* chunkdata )
--{
-- int* sizeptr;
--
-- sizeptr = (int*) &chunkdata[1]; /* we skip the first byte (type field) */
--
-- return ntohl( *sizeptr );
--}
--
--
--/*------------------------------------------------------------------------
-- * Process a received multimedia packet.
-- *
-- * @param session The MXit session object
-- * @param records The packet's data records
-- * @param rcount The number of data records
-- */
--static void mxit_parse_cmd_media( struct MXitSession* session, struct record** records, int rcount )
--{
-- char type;
-- int size;
--
-- type = records[0]->fields[0]->data[0];
-- size = get_chunk_len( records[0]->fields[0]->data );
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i bytes)\n", rcount, size );
--
-- /* supported chunked data types */
-- switch ( type ) {
-- case CP_CHUNK_CUSTOM : /* custom resource */
-- {
-- struct cr_chunk chunk;
--
-- /* decode the chunked data */
-- memset( &chunk, 0, sizeof( struct cr_chunk ) );
-- mxit_chunk_parse_cr( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
--
-- purple_debug_info( MXIT_PLUGIN_ID, "chunk info id=%s handle=%s op=%i\n", chunk.id, chunk.handle, chunk.operation );
--
-- /* this is a splash-screen operation */
-- if ( strcmp( chunk.handle, HANDLE_SPLASH2 ) == 0 ) {
-- if ( chunk.operation == CR_OP_UPDATE ) { /* update the splash-screen */
-- struct splash_chunk *splash = chunk.resources->data; // TODO: Fix - assuming 1st resource is splash
-- gboolean clickable = ( g_list_length( chunk.resources ) > 1 ); // TODO: Fix - if 2 resources, then is clickable
--
-- if ( splash != NULL )
-- splash_update( session, chunk.id, splash->data, splash->datalen, clickable );
-- }
-- else if ( chunk.operation == CR_OP_REMOVE ) /* remove the splash-screen */
-- splash_remove( session );
-- }
--
-- /* cleanup custom resources */
-- g_list_foreach( chunk.resources, (GFunc)g_free, NULL );
--
-- }
-- break;
--
-- case CP_CHUNK_OFFER : /* file offer */
-- {
-- struct offerfile_chunk chunk;
--
-- /* decode the chunked data */
-- memset( &chunk, 0, sizeof( struct offerfile_chunk ) );
-- mxit_chunk_parse_offer( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
--
-- /* process the offer */
-- mxit_xfer_rx_offer( session, chunk.username, chunk.filename, chunk.filesize, chunk.fileid );
-- }
-- break;
--
-- case CP_CHUNK_GET : /* get file response */
-- {
-- struct getfile_chunk chunk;
--
-- /* decode the chunked data */
-- memset( &chunk, 0, sizeof( struct getfile_chunk ) );
-- mxit_chunk_parse_get( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
--
-- /* process the getfile */
-- mxit_xfer_rx_file( session, chunk.fileid, chunk.data, chunk.length );
-- }
-- break;
--
-- case CP_CHUNK_GET_AVATAR : /* get avatars */
-- {
-- struct getavatar_chunk chunk;
-- struct contact* contact = NULL;
--
-- /* decode the chunked data */
-- memset( &chunk, 0, sizeof( struct getavatar_chunk ) );
-- mxit_chunk_parse_get_avatar( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
--
-- /* update avatar image */
-- if ( chunk.data ) {
-- purple_debug_info( MXIT_PLUGIN_ID, "updating avatar for contact '%s'\n", chunk.mxitid );
--
-- contact = get_mxit_invite_contact( session, chunk.mxitid );
-- if ( contact ) {
-- /* this is an invite (add image to the internal image store) */
-- contact->imgid = purple_imgstore_add_with_id( g_memdup( chunk.data, chunk.length ), chunk.length, NULL );
-- /* show the profile */
-- mxit_show_profile( session, chunk.mxitid, contact->profile );
-- }
-- else {
-- /* this is a contact's avatar, so update it */
-- purple_buddy_icons_set_for_user( session->acc, chunk.mxitid, g_memdup( chunk.data, chunk.length), chunk.length, chunk.avatarid );
-- }
-- }
-- }
-- break;
--
-- case CP_CHUNK_SET_AVATAR :
-- /* this is a reply packet to a set avatar request. no action is required */
-- break;
--
-- case CP_CHUNK_DIRECT_SND :
-- /* this is a ack for a file send. */
-- {
-- struct sendfile_chunk chunk;
--
-- memset( &chunk, 0, sizeof( struct sendfile_chunk ) );
-- mxit_chunk_parse_sendfile( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
--
-- purple_debug_info( MXIT_PLUGIN_ID, "file-send send to '%s' [status=%i message='%s']\n", chunk.username, chunk.status, chunk.statusmsg );
--
-- if ( chunk.status != 0 ) /* not success */
-- mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "File Send Failed" ), chunk.statusmsg );
-- }
-- break;
--
-- case CP_CHUNK_RECEIVED :
-- /* this is a ack for a file received. no action is required */
-- break;
--
-- default :
-- purple_debug_error( MXIT_PLUGIN_ID, "Unsupported chunked data packet type received (%i)\n", type );
-- break;
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Handle a redirect sent from the MXit server.
-- *
-- * @param session The MXit session object
-- * @param url The redirect information
-- */
--static void mxit_perform_redirect( struct MXitSession* session, const char* url )
--{
-- gchar** parts;
-- gchar** host;
-- int type;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_perform_redirect: %s\n", url );
--
-- /* tokenize the URL string */
-- parts = g_strsplit( url, ";", 0 );
--
-- /* Part 1: protocol://host:port */
-- host = g_strsplit( parts[0], ":", 4 );
-- if ( strcmp( host[0], "socket" ) == 0 ) {
-- /* redirect to a MXit socket proxy */
-- g_strlcpy( session->server, &host[1][2], sizeof( session->server ) );
-- session->port = atoi( host[2] );
-- }
-- else {
-- purple_connection_error( session->con, _( "Cannot perform redirect using the specified protocol" ) );
-- goto redirect_fail;
-- }
--
-- /* Part 2: type of redirect */
-- type = atoi( parts[1] );
-- if ( type == CP_REDIRECT_PERMANENT ) {
-- /* permanent redirect, so save new MXit server and port */
-- purple_account_set_string( session->acc, MXIT_CONFIG_SERVER_ADDR, session->server );
-- purple_account_set_int( session->acc, MXIT_CONFIG_SERVER_PORT, session->port );
-- }
--
-- /* Part 3: message (optional) */
-- if ( parts[2] != NULL )
-- purple_connection_notice( session->con, parts[2] );
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_perform_redirect: %s redirect to %s:%i\n",
-- ( type == CP_REDIRECT_PERMANENT ) ? "Permanent" : "Temporary", session->server, session->port );
--
-- /* perform the re-connect to the new MXit server */
-- mxit_reconnect( session );
--
--redirect_fail:
-- g_strfreev( parts );
-- g_strfreev( host );
--}
--
--
--/*------------------------------------------------------------------------
-- * Process a success response received from the MXit server.
-- *
-- * @param session The MXit session object
-- * @param packet The received packet
-- */
--static int process_success_response( struct MXitSession* session, struct rx_packet* packet )
--{
-- /* ignore ping/poll packets */
-- if ( ( packet->cmd != CP_CMD_PING ) && ( packet->cmd != CP_CMD_POLL ) )
-- session->last_rx = mxit_now_milli();
--
-- /*
-- * when we pass the packet records to the next level for parsing
-- * we minus 3 records because 1) the first record is the packet
-- * type 2) packet reply status 3) the last record is bogus
-- */
--
-- /* packet command */
-- switch ( packet->cmd ) {
--
-- case CP_CMD_REGISTER :
-- /* fall through, when registeration successful, MXit will auto login */
-- case CP_CMD_LOGIN :
-- /* login response */
-- if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) {
-- mxit_parse_cmd_login( session, &packet->records[2], packet->rcount - 3 );
-- }
-- break;
--
-- case CP_CMD_LOGOUT :
-- /* logout response */
-- session->flags &= ~MXIT_FLAG_LOGGEDIN;
-- purple_account_disconnect( session->acc );
--
-- /* note:
-- * we do not prompt the user here for a reconnect, because this could be the user
-- * logging in with his phone. so we just disconnect the account otherwise
-- * mxit will start to bounce between the phone and pidgin. also could be a valid
-- * disconnect selected by the user.
-- */
-- return -1;
--
-- case CP_CMD_CONTACT :
-- /* contact update */
-- mxit_parse_cmd_contact( session, &packet->records[2], packet->rcount - 3 );
-- break;
--
-- case CP_CMD_PRESENCE :
-- /* presence update */
-- mxit_parse_cmd_presence(session, &packet->records[2], packet->rcount - 3 );
-- break;
--
-- case CP_CMD_RX_MSG :
-- /* incoming message (no bogus record) */
-- mxit_parse_cmd_message( session, &packet->records[2], packet->rcount - 2 );
-- break;
--
-- case CP_CMD_NEW_SUB :
-- /* new subscription request */
-- mxit_parse_cmd_new_sub( session, &packet->records[2], packet->rcount - 3 );
-- break;
--
-- case CP_CMD_MEDIA :
-- /* multi-media message */
-- mxit_parse_cmd_media( session, &packet->records[2], packet->rcount - 2 );
-- break;
--
-- case CP_CMD_EXTPROFILE_GET :
-- /* profile update */
-- mxit_parse_cmd_extprofile( session, &packet->records[2], packet->rcount - 2 );
-- break;
--
-- case CP_CMD_SUGGESTCONTACTS :
-- /* suggest contacts */
-- mxit_parse_cmd_suggestcontacts( session, &packet->records[2], packet->rcount - 2 );
-- break;
--
-- case CP_CMD_GOT_MSGEVENT :
-- /* received message event */
-- mxit_parse_cmd_msgevent( session, &packet->records[2], packet->rcount - 2 );
-- break;
--
-- case CP_CMD_MOOD :
-- /* mood update */
-- case CP_CMD_UPDATE :
-- /* update contact information */
-- case CP_CMD_ALLOW :
-- /* allow subscription ack */
-- case CP_CMD_DENY :
-- /* deny subscription ack */
-- case CP_CMD_INVITE :
-- /* invite contact ack */
-- case CP_CMD_REMOVE :
-- /* remove contact ack */
-- case CP_CMD_TX_MSG :
-- /* outgoing message ack */
-- case CP_CMD_STATUS :
-- /* presence update ack */
-- case CP_CMD_GRPCHAT_CREATE :
-- /* create groupchat */
-- case CP_CMD_GRPCHAT_INVITE :
-- /* groupchat invite */
-- case CP_CMD_PING :
-- /* ping reply */
-- case CP_CMD_POLL :
-- /* HTTP poll reply */
-- case CP_CMD_EXTPROFILE_SET :
-- /* profile update */
-- // TODO: Protocol 6.2 indicates status for each attribute, and current value.
-- case CP_CMD_SPLASHCLICK :
-- /* splash-screen clickthrough */
-- case CP_CMD_MSGEVENT :
-- /* event message */
-- break;
--
-- default :
-- /* unknown packet */
-- purple_debug_error( MXIT_PLUGIN_ID, "Received unknown client packet (cmd = %i)\n", packet->cmd );
-- }
--
-- return 0;
--}
--
--
--/*------------------------------------------------------------------------
-- * Process an error response received from the MXit server.
-- *
-- * @param session The MXit session object
-- * @param packet The received packet
-- */
--static int process_error_response( struct MXitSession* session, struct rx_packet* packet )
--{
-- char errmsg[256];
-- const char* errdesc;
--
-- /* set the error description to be shown to the user */
-- if ( packet->errmsg )
-- errdesc = packet->errmsg;
-- else
-- errdesc = _( "An internal MXit server error occurred." );
--
-- purple_debug_info( MXIT_PLUGIN_ID, "Error Reply %i:%s\n", packet->errcode, errdesc );
--
-- if ( packet->errcode == MXIT_ERRCODE_LOGGEDOUT ) {
-- /* we are not currently logged in, so we need to reconnect */
-- purple_connection_error( session->con, _( errdesc ) );
-- }
--
-- /* packet command */
-- switch ( packet->cmd ) {
--
-- case CP_CMD_REGISTER :
-- case CP_CMD_LOGIN :
-- if ( packet->errcode == MXIT_ERRCODE_REDIRECT ) {
-- mxit_perform_redirect( session, packet->errmsg );
-- return 0;
-- }
-- else {
-- snprintf( errmsg, sizeof( errmsg ), _( "Login error: %s (%i)" ), errdesc, packet->errcode );
-- purple_connection_error( session->con, errmsg );
-- return -1;
-- }
-- case CP_CMD_LOGOUT :
-- snprintf( errmsg, sizeof( errmsg ), _( "Logout error: %s (%i)" ), errdesc, packet->errcode );
-- purple_connection_error_reason( session->con, PURPLE_CONNECTION_ERROR_NAME_IN_USE, _( errmsg ) );
-- return -1;
-- case CP_CMD_CONTACT :
-- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Error" ), _( errdesc ) );
-- break;
-- case CP_CMD_RX_MSG :
-- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), _( errdesc ) );
-- break;
-- case CP_CMD_TX_MSG :
-- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Sending Error" ), _( errdesc ) );
-- break;
-- case CP_CMD_STATUS :
-- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Status Error" ), _( errdesc ) );
-- break;
-- case CP_CMD_MOOD :
-- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Mood Error" ), _( errdesc ) );
-- break;
-- case CP_CMD_KICK :
-- /*
-- * the MXit server sends this packet if we were idle for too long.
-- * to stop the server from closing this connection we need to resend
-- * the login packet.
-- */
-- mxit_send_login( session );
-- break;
-- case CP_CMD_INVITE :
-- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Invitation Error" ), _( errdesc ) );
-- break;
-- case CP_CMD_REMOVE :
-- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Removal Error" ), _( errdesc ) );
-- break;
-- case CP_CMD_ALLOW :
-- case CP_CMD_DENY :
-- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Subscription Error" ), _( errdesc ) );
-- break;
-- case CP_CMD_UPDATE :
-- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Update Error" ), _( errdesc ) );
-- break;
-- case CP_CMD_MEDIA :
-- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "File Transfer Error" ), _( errdesc ) );
-- break;
-- case CP_CMD_GRPCHAT_CREATE :
-- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Cannot create MultiMx room" ), _( errdesc ) );
-- break;
-- case CP_CMD_GRPCHAT_INVITE :
-- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "MultiMx Invitation Error" ), _( errdesc ) );
-- break;
-- case CP_CMD_EXTPROFILE_GET :
-- case CP_CMD_EXTPROFILE_SET :
-- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Profile Error" ), _( errdesc ) );
-- break;
-- case CP_CMD_SPLASHCLICK :
-- case CP_CMD_MSGEVENT :
-- /* ignore error */
-- break;
-- case CP_CMD_PING :
-- case CP_CMD_POLL :
-- break;
-- default :
-- mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Error" ), _( errdesc ) );
-- break;
-- }
--
-- return 0;
--}
--
--
--/*========================================================================================================================
-- * Low-level Packet receive
-- */
--
--#ifdef DEBUG_PROTOCOL
--/*------------------------------------------------------------------------
-- * Dump a received packet structure.
-- *
-- * @param p The received packet
-- */
--static void dump_packet( struct rx_packet* p )
--{
-- struct record* r = NULL;
-- struct field* f = NULL;
-- int i;
-- int j;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "PACKET DUMP: (%i records)\n", p->rcount );
--
-- for ( i = 0; i < p->rcount; i++ ) {
-- r = p->records[i];
-- purple_debug_info( MXIT_PLUGIN_ID, "RECORD: (%i fields)\n", r->fcount );
--
-- for ( j = 0; j < r->fcount; j++ ) {
-- f = r->fields[j];
-- purple_debug_info( MXIT_PLUGIN_ID, "\tFIELD: (len=%i) '%s' \n", f->len, f->data );
-- }
-- }
--}
--#endif
--
--
--/*------------------------------------------------------------------------
-- * Free up memory used by a packet structure.
-- *
-- * @param p The received packet
-- */
--static void free_rx_packet( struct rx_packet* p )
--{
-- struct record* r = NULL;
-- struct field* f = NULL;
-- int i;
-- int j;
--
-- for ( i = 0; i < p->rcount; i++ ) {
-- r = p->records[i];
--
-- for ( j = 0; j < r->fcount; j++ ) {
-- g_free( f );
-- }
-- g_free( r->fields );
-- g_free( r );
-- }
-- g_free( p->records );
--}
--
--
--/*------------------------------------------------------------------------
-- * Add a new field to a record.
-- *
-- * @param r Parent record object
-- * @return The newly created field
-- */
--static struct field* add_field( struct record* r )
--{
-- struct field* field;
--
-- field = g_new0( struct field, 1 );
--
-- r->fields = g_realloc( r->fields, sizeof( struct field* ) * ( r->fcount + 1 ) );
-- r->fields[r->fcount] = field;
-- r->fcount++;
--
-- return field;
--}
--
--
--/*------------------------------------------------------------------------
-- * Add a new record to a packet.
-- *
-- * @param p The packet object
-- * @return The newly created record
-- */
--static struct record* add_record( struct rx_packet* p )
--{
-- struct record* rec;
--
-- rec = g_new0( struct record, 1 );
--
-- p->records = g_realloc( p->records, sizeof( struct record* ) * ( p->rcount + 1 ) );
-- p->records[p->rcount] = rec;
-- p->rcount++;
--
-- return rec;
--}
--
--
--/*------------------------------------------------------------------------
-- * Parse the received byte stream into a proper client protocol packet.
-- *
-- * @param session The MXit session object
-- * @return Success (0) or Failure (!0)
-- */
--int mxit_parse_packet( struct MXitSession* session )
--{
-- struct rx_packet packet;
-- struct record* rec;
-- struct field* field;
-- gboolean pbreak;
-- unsigned int i;
-- int res = 0;
--
--#ifdef DEBUG_PROTOCOL
-- purple_debug_info( MXIT_PLUGIN_ID, "Received packet (%i bytes)\n", session->rx_i );
-- dump_bytes( session, session->rx_dbuf, session->rx_i );
--#endif
--
-- i = 0;
-- while ( i < session->rx_i ) {
--
-- /* create first record and field */
-- rec = NULL;
-- field = NULL;
-- memset( &packet, 0x00, sizeof( struct rx_packet ) );
-- rec = add_record( &packet );
-- pbreak = FALSE;
--
-- /* break up the received packet into fields and records for easy parsing */
-- while ( ( i < session->rx_i ) && ( !pbreak ) ) {
--
-- switch ( session->rx_dbuf[i] ) {
-- case CP_SOCK_REC_TERM :
-- /* new record */
-- if ( packet.rcount == 1 ) {
-- /* packet command */
-- packet.cmd = atoi( packet.records[0]->fields[0]->data );
-- }
-- else if ( packet.rcount == 2 ) {
-- /* special case: binary multimedia packets should not be parsed here */
-- if ( packet.cmd == CP_CMD_MEDIA ) {
-- /* add the chunked to new record */
-- rec = add_record( &packet );
-- field = add_field( rec );
-- field->data = &session->rx_dbuf[i + 1];
-- field->len = session->rx_i - i;
-- /* now skip the binary data */
-- res = get_chunk_len( field->data );
-- /* determine if we have more packets */
-- if ( res + 6 + i < session->rx_i ) {
-- /* we have more than one packet in this stream */
-- i += res + 6;
-- pbreak = TRUE;
-- }
-- else {
-- i = session->rx_i;
-- }
-- }
-- }
-- else if ( !field ) {
-- field = add_field( rec );
-- field->data = &session->rx_dbuf[i];
-- }
-- session->rx_dbuf[i] = '\0';
-- rec = add_record( &packet );
-- field = NULL;
--
-- break;
-- case CP_FLD_TERM :
-- /* new field */
-- session->rx_dbuf[i] = '\0';
-- if ( !field ) {
-- field = add_field( rec );
-- field->data = &session->rx_dbuf[i];
-- }
-- field = NULL;
-- break;
-- case CP_PKT_TERM :
-- /* packet is done! */
-- session->rx_dbuf[i] = '\0';
-- pbreak = TRUE;
-- break;
-- default :
-- /* skip non special characters */
-- if ( !field ) {
-- field = add_field( rec );
-- field->data = &session->rx_dbuf[i];
-- }
-- field->len++;
-- break;
-- }
--
-- i++;
-- }
--
-- if ( packet.rcount < 2 ) {
-- /* bad packet */
-- purple_connection_error( session->con, _( "Invalid packet received from MXit." ) );
-- free_rx_packet( &packet );
-- continue;
-- }
--
-- session->rx_dbuf[session->rx_i] = '\0';
-- packet.errcode = atoi( packet.records[1]->fields[0]->data );
--
-- purple_debug_info( MXIT_PLUGIN_ID, "Packet received CMD:%i (%i)\n", packet.cmd, packet.errcode );
--#ifdef DEBUG_PROTOCOL
-- /* debug */
-- dump_packet( &packet );
--#endif
--
-- /* reset the out ack */
-- if ( session->outack == packet.cmd ) {
-- /* outstanding ack received from mxit server */
-- session->outack = 0;
-- }
--
-- /* check packet status */
-- if ( packet.errcode != MXIT_ERRCODE_SUCCESS ) {
-- /* error reply! */
-- if ( ( packet.records[1]->fcount > 1 ) && ( packet.records[1]->fields[1]->data ) )
-- packet.errmsg = packet.records[1]->fields[1]->data;
-- else
-- packet.errmsg = NULL;
--
-- res = process_error_response( session, &packet );
-- }
-- else {
-- /* success reply! */
-- res = process_success_response( session, &packet );
-- }
--
-- /* free up the packet resources */
-- free_rx_packet( &packet );
-- }
--
-- if ( session->outack == 0 )
-- mxit_manage_queue( session );
--
-- return res;
--}
--
--
--/*------------------------------------------------------------------------
-- * Callback when data is received from the MXit server.
-- *
-- * @param user_data The MXit session object
-- * @param source The file-descriptor on which data was received
-- * @param cond Condition which caused the callback (PURPLE_INPUT_READ)
-- */
--void mxit_cb_rx( gpointer user_data, gint source, PurpleInputCondition cond )
--{
-- struct MXitSession* session = (struct MXitSession*) user_data;
-- char ch;
-- int res;
-- int len;
--
-- if ( session->rx_state == RX_STATE_RLEN ) {
-- /* we are reading in the packet length */
-- len = read( session->fd, &ch, 1 );
-- if ( len < 0 ) {
-- /* connection error */
-- purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x01)" ) );
-- return;
-- }
-- else if ( len == 0 ) {
-- /* connection closed */
-- purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x02)" ) );
-- return;
-- }
-- else {
-- /* byte read */
-- if ( ch == CP_REC_TERM ) {
-- /* the end of the length record found */
-- session->rx_lbuf[session->rx_i] = '\0';
-- session->rx_res = atoi( &session->rx_lbuf[3] );
-- if ( session->rx_res > CP_MAX_PACKET ) {
-- purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x03)" ) );
-- }
-- session->rx_state = RX_STATE_DATA;
-- session->rx_i = 0;
-- }
-- else {
-- /* still part of the packet length record */
-- session->rx_lbuf[session->rx_i] = ch;
-- session->rx_i++;
-- if ( session->rx_i >= sizeof( session->rx_lbuf ) ) {
-- /* malformed packet length record (too long) */
-- purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x04)" ) );
-- return;
-- }
-- }
-- }
-- }
-- else if ( session->rx_state == RX_STATE_DATA ) {
-- /* we are reading in the packet data */
-- len = read( session->fd, &session->rx_dbuf[session->rx_i], session->rx_res );
-- if ( len < 0 ) {
-- /* connection error */
-- purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x05)" ) );
-- return;
-- }
-- else if ( len == 0 ) {
-- /* connection closed */
-- purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x06)" ) );
-- return;
-- }
-- else {
-- /* data read */
-- session->rx_i += len;
-- session->rx_res -= len;
--
-- if ( session->rx_res == 0 ) {
-- /* ok, so now we have read in the whole packet */
-- session->rx_state = RX_STATE_PROC;
-- }
-- }
-- }
--
-- if ( session->rx_state == RX_STATE_PROC ) {
-- /* we have a full packet, which we now need to process */
-- res = mxit_parse_packet( session );
--
-- if ( res == 0 ) {
-- /* we are still logged in */
-- session->rx_state = RX_STATE_RLEN;
-- session->rx_res = 0;
-- session->rx_i = 0;
-- }
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Log the user off MXit and close the connection
-- *
-- * @param session The MXit session object
-- */
--void mxit_close_connection( struct MXitSession* session )
--{
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_close_connection\n" );
--
-- if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) {
-- /* we are already closed */
-- return;
-- }
-- else if ( session->flags & MXIT_FLAG_LOGGEDIN ) {
-- /* we are currently logged in so we need to send a logout packet */
-- if ( !session->http ) {
-- mxit_send_logout( session );
-- }
-- session->flags &= ~MXIT_FLAG_LOGGEDIN;
-- }
-- session->flags &= ~MXIT_FLAG_CONNECTED;
--
-- /* cancel outstanding HTTP request */
-- if ( ( session->http ) && ( session->http_out_req ) ) {
-- purple_util_fetch_url_cancel( (PurpleUtilFetchUrlData*) session->http_out_req );
-- session->http_out_req = NULL;
-- }
--
-- /* remove the input cb function */
-- if ( session->con->inpa ) {
-- purple_input_remove( session->con->inpa );
-- session->con->inpa = 0;
-- }
--
-- /* remove HTTP poll timer */
-- if ( session->http_timer_id > 0 )
-- purple_timeout_remove( session->http_timer_id );
--
-- /* remove slow queue manager timer */
-- if ( session->q_slow_timer_id > 0 )
-- purple_timeout_remove( session->q_slow_timer_id );
--
-- /* remove fast queue manager timer */
-- if ( session->q_fast_timer_id > 0 )
-- purple_timeout_remove( session->q_fast_timer_id );
--
-- /* remove all groupchat rooms */
-- while ( session->rooms != NULL ) {
-- struct multimx* multimx = (struct multimx *) session->rooms->data;
--
-- session->rooms = g_list_remove( session->rooms, multimx );
--
-- free( multimx );
-- }
-- g_list_free( session->rooms );
-- session->rooms = NULL;
--
-- /* remove all rx chats names */
-- while ( session->active_chats != NULL ) {
-- char* chat = (char*) session->active_chats->data;
--
-- session->active_chats = g_list_remove( session->active_chats, chat );
--
-- g_free( chat );
-- }
-- g_list_free( session->active_chats );
-- session->active_chats = NULL;
--
-- /* clear the internal invites */
-- while ( session->invites != NULL ) {
-- struct contact* contact = (struct contact*) session->invites->data;
--
-- session->invites = g_list_remove( session->invites, contact );
--
-- if ( contact->msg )
-- g_free( contact->msg );
-- if ( contact->statusMsg )
-- g_free( contact->statusMsg );
-- if ( contact->profile )
-- g_free( contact->profile );
-- g_free( contact );
-- }
-- g_list_free( session->invites );
-- session->invites = NULL;
--
-- /* free profile information */
-- if ( session->profile )
-- free( session->profile );
--
-- /* free custom emoticons */
-- mxit_free_emoticon_cache( session );
--
-- /* free allocated memory */
-- if ( session->uid )
-- g_free( session->uid );
-- g_free( session->encpwd );
-- session->encpwd = NULL;
--
-- /* flush all the commands still in the queue */
-- flush_queue( session );
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/protocol.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/protocol.h
---- pidgin-2.10.7/libpurple/protocols/mxit/protocol.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/protocol.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,352 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- MXit client protocol implementation --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MXIT_PROTO_H_
--#define _MXIT_PROTO_H_
--
--
--/* Client protocol constants */
--#define CP_SOCK_REC_TERM '\x00' /* socket record terminator */
--#define CP_HTTP_REC_TERM '\x26' /* http record terminator '&' */
--#define CP_FLD_TERM '\x01' /* field terminator */
--#define CP_PKT_TERM '\x02' /* packet terminator */
--
--
--#define CP_MAX_PACKET ( 1 * 1000 * 1000 ) /* maximum client protocol packet size (1 MB) */
--#define CP_MAX_FILESIZE ( CP_MAX_PACKET - 1000 ) /* maximum file size (reserve some space for packet headers) */
--#define MXIT_EMOTICON_SIZE 18 /* icon size for custom emoticons */
--#define CP_MAX_STATUS_MSG 250 /* maximum status message length (in characters) */
--
--/* Avatars */
--#define MXIT_AVATAR_SIZE 96 /* default avatar image size 96x96 */
--#define MXIT_AVATAR_TYPE "PNG" /* request avatars in this file type (only a suggestion) */
--#define MXIT_AVATAR_BITDEPT 24 /* request avatars with this bit depth (only a suggestion) */
--
--/* Protocol error codes */
--#define MXIT_ERRCODE_SUCCESS 0
--#define MXIT_ERRCODE_REDIRECT 16
--#define MXIT_ERRCODE_LOGGEDOUT 42
--
--/* MXit client features */
--#define MXIT_CF_NONE 0x000000
--#define MXIT_CF_FORMS 0x000001
--#define MXIT_CF_FILE_TRANSFER 0x000002
--#define MXIT_CF_CAMERA 0x000004
--#define MXIT_CF_COMMANDS 0x000008
--#define MXIT_CF_SMS 0x000010
--#define MXIT_CF_FILE_ACCESS 0x000020
--#define MXIT_CF_MIDP2 0x000040
--#define MXIT_CF_SKINS 0x000080
--#define MXIT_CF_AUDIO 0x000100
--#define MXIT_CF_ENCRYPTION 0x000200
--#define MXIT_CF_VOICE_REC 0x000400
--#define MXIT_CF_VECTOR_GFX 0x000800
--#define MXIT_CF_IMAGES 0x001000
--#define MXIT_CF_MARKUP 0x002000
--#define MXIT_CF_VIBES 0x004000
--#define MXIT_CF_SELECT_CONTACT 0x008000
--#define MXIT_CF_CUSTOM_EMO 0x010000
--#define MXIT_CF_ALERT_PROFILES 0x020000
--#define MXIT_CF_EXT_MARKUP 0x040000
--#define MXIT_CF_PLAIN_PWD 0x080000
--#define MXIT_CF_NO_GATEWAYS 0x100000
--#define MXIT_CF_NO_AVATARS 0x200000
--#define MXIT_CF_GAMING 0x400000
--#define MXIT_CF_GAMING_UPDATE 0x800000
--#define MXIT_CF_VOICE 0x1000000
--#define MXIT_CF_VIDEO 0x2000000
--#define MXIT_CF_TOUCHSCREEN 0x4000000
--#define MXIT_CF_SVC_CONNECTION 0x8000000
--#define MXIT_CF_MXML 0x10000000
--#define MXIT_CF_TYPING_NOTIFY 0x20000000
--
--/* Client features supported by this implementation */
--#define MXIT_CP_FEATURES ( MXIT_CF_FILE_TRANSFER | MXIT_CF_FILE_ACCESS | MXIT_CF_AUDIO | MXIT_CF_MARKUP | MXIT_CF_EXT_MARKUP | MXIT_CF_NO_GATEWAYS | MXIT_CF_IMAGES | MXIT_CF_COMMANDS | MXIT_CF_VIBES | MXIT_CF_MIDP2 | MXIT_CF_TYPING_NOTIFY )
--
--
--#define MXIT_PING_INTERVAL ( 5 * 60 ) /* ping the server after X seconds of being idle (5 minutes) */
--#define MXIT_ACK_TIMEOUT ( 30 ) /* timeout after waiting X seconds for an ack from the server (30 seconds) */
--#define MXIT_TX_DELAY ( 100 ) /* delay between sending consecutive packets (100 ms) */
--
--/* MXit client version */
--#define MXIT_CP_DISTCODE 'P' /* client distribution code (magic, do not touch!) */
--#define MXIT_CP_ARCH "Y" /* client architecture series (Y not for Yoda but for PC-client) */
--#define MXIT_CLIENT_ID "LP" /* client ID as specified by MXit */
--#define MXIT_CP_PLATFORM "PURPLE" /* client platform */
--#define MXIT_CP_PROTO_VESION 63 /* client protocol version */
--
--/* set operating system name */
--#if defined( __APPLE__ )
--#define MXIT_CP_OS "apple"
--#elif defined( _WIN32 )
--#define MXIT_CP_OS "windows"
--#elif defined( __linux__ )
--#define MXIT_CP_OS "linux"
--#else
--#define MXIT_CP_OS "unknown"
--#endif
--
--/* Client capabilities */
--#define MXIT_CP_CAP "utf8=true;cid="MXIT_CLIENT_ID
--
--/* Client settings */
--#define MAX_QUEUE_SIZE ( 1 << 5 ) /* tx queue size (32 packets) */
--#define MXIT_POPUP_WIN_NAME "MXit Notification" /* popup window name */
--#define MXIT_DEFAULT_LOCALE "en" /* default locale setting */
--#define MXIT_DEFAULT_LOC "planetpurple" /* the default location for registration */
--
--/* Client protocol commands */
--#define CP_CMD_LOGIN 0x0001 /* (1) login */
--#define CP_CMD_LOGOUT 0x0002 /* (2) logout */
--#define CP_CMD_CONTACT 0x0003 /* (3) get contacts */
--#define CP_CMD_UPDATE 0x0005 /* (5) update contact information */
--#define CP_CMD_INVITE 0x0006 /* (6) subscribe to new contact */
--#define CP_CMD_PRESENCE 0x0007 /* (7) get presence */
--#define CP_CMD_REMOVE 0x0008 /* (8) remove contact */
--#define CP_CMD_RX_MSG 0x0009 /* (9) get new messages */
--#define CP_CMD_TX_MSG 0x000A /* (10) send new message */
--#define CP_CMD_REGISTER 0x000B /* (11) register */
--//#define CP_CMD_PROFILE_SET 0x000C /* (12) set profile (DEPRECATED see CP_CMD_EXTPROFILE_SET) */
--#define CP_CMD_SUGGESTCONTACTS 0x000D /* (13) suggest contacts */
--#define CP_CMD_POLL 0x0011 /* (17) poll the HTTP server for an update */
--//#define CP_CMD_PROFILE_GET 0x001A /* (26) get profile (DEPRECATED see CP_CMD_EXTPROFILE_GET) */
--#define CP_CMD_MEDIA 0x001B /* (27) get multimedia message */
--#define CP_CMD_SPLASHCLICK 0x001F /* (31) splash-screen clickthrough */
--#define CP_CMD_STATUS 0x0020 /* (32) set shown presence & status */
--#define CP_CMD_MSGEVENT 0x0023 /* (35) Raise message event */
--#define CP_CMD_GOT_MSGEVENT 0x0024 /* (36) Get message event */
--#define CP_CMD_MOOD 0x0029 /* (41) set mood */
--#define CP_CMD_KICK 0x002B /* (43) login kick */
--#define CP_CMD_GRPCHAT_CREATE 0x002C /* (44) create new groupchat */
--#define CP_CMD_GRPCHAT_INVITE 0x002D /* (45) add new groupchat member */
--#define CP_CMD_NEW_SUB 0x0033 /* (51) get new subscription */
--#define CP_CMD_ALLOW 0x0034 /* (52) allow subscription */
--#define CP_CMD_DENY 0x0037 /* (55) deny subscription */
--#define CP_CMD_EXTPROFILE_GET 0x0039 /* (57) get extended profile */
--#define CP_CMD_EXTPROFILE_SET 0x003A /* (58) set extended profile */
--#define CP_CMD_PING 0x03E8 /* (1000) ping (keepalive) */
--
--/* HTTP connection */
--#define MXIT_HTTP_POLL_MIN 7 /* minimum time between HTTP polls (seconds) */
--#define MXIT_HTTP_POLL_MAX ( 10 * 60 ) /* maximum time between HTTP polls (seconds) */
--
--/* receiver states */
--#define RX_STATE_RLEN 0x01 /* reading packet length section */
--#define RX_STATE_DATA 0x02 /* reading packet data section */
--#define RX_STATE_PROC 0x03 /* process read data */
--
--/* message flags */
--#define CP_MSG_NOTIFY_DELIVERY 0x0002 /* request delivery notification */
--#define CP_MSG_NOTIFY_READ 0x0004 /* request read notification */
--#define CP_MSG_PWD_ENCRYPTED 0x0010 /* message is password encrypted */
--#define CP_MSG_TL_ENCRYPTED 0x0020 /* message is transport encrypted */
--#define CP_MSG_RPLY_PWD_ENCRYPT 0x0040 /* reply should be password encrypted */
--#define CP_MSG_RPLY_TL_ENCRYPT 0x0080 /* reply should be transport encrypted */
--#define CP_MSG_MARKUP 0x0200 /* message may contain markup */
--#define CP_MSG_EMOTICON 0x0400 /* message may contain custom emoticons */
--#define CP_MSG_FAREWELL 0x0800 /* this is a farewell message */
--
--/* redirect types */
--#define CP_REDIRECT_PERMANENT 1 /* permanent redirect */
--#define CP_REDIRECT_TEMPORARY 2 /* temporary redirect */
--
--/* message tx types */
--#define CP_MSGTYPE_NORMAL 0x01 /* normal message */
--#define CP_MSGTYPE_CHAT 0x02 /* chat message */
--#define CP_MSGTYPE_HEADLINE 0x03 /* headline message */
--#define CP_MSGTYPE_ERROR 0x04 /* error message */
--#define CP_MSGTYPE_GROUPCHAT 0x05 /* groupchat message */
--#define CP_MSGTYPE_FORM 0x06 /* mxit custom form */
--#define CP_MSGTYPE_COMMAND 0x07 /* mxit command */
--
--/* message event types */
--#define CP_MSGEVENT_DELIVERED 0x02 /* message was delivered */
--#define CP_MSGEVENT_DISPLAYED 0x04 /* message was viewed */
--#define CP_MSGEVENT_TYPING 0x10 /* user is typing */
--#define CP_MSGEVENT_STOPPED 0x20 /* user has stopped typing */
--#define CP_MSGEVENT_ANGRY 0x40 /* user is typing angrily */
--#define CP_MSGEVENT_ERASING 0x80 /* user is erasing text */
--
--/* extended profile attribute fields */
--#define CP_PROFILE_BIRTHDATE "birthdate" /* Birthdate (String - ISO 8601 format) */
--#define CP_PROFILE_GENDER "gender" /* Gender (Boolean - 0=female, 1=male) */
--// #define CP_PROFILE_HIDENUMBER "hidenumber" /* Hide Number (Boolean - 0=false, 1=true) (DEPRECATED) */
--#define CP_PROFILE_FULLNAME "fullname" /* Fullname (UTF8 String) */
--#define CP_PROFILE_STATUS "statusmsg" /* Status Message (UTF8 String) */
--#define CP_PROFILE_PREVSTATUS "prevstatusmsgs" /* Previous Status Messages (UTF8 String) */
--#define CP_PROFILE_AVATAR "avatarid" /* Avatar ID (String) */
--#define CP_PROFILE_MODIFIED "lastmodified" /* Last-Modified timestamp */
--#define CP_PROFILE_TITLE "title" /* Title (UTF8 String) */
--#define CP_PROFILE_FIRSTNAME "firstname" /* First name (UTF8 String) */
--#define CP_PROFILE_LASTNAME "lastname" /* Last name (UTF8 String) */
--#define CP_PROFILE_EMAIL "email" /* Email address (UTF8 String) */
--#define CP_PROFILE_MOBILENR "mobilenumber" /* Mobile Number (UTF8 String) */
--#define CP_PROFILE_REGCOUNTRY "registeredcountry" /* Registered Country Code (UTF8 String) */
--#define CP_PROFILE_FLAGS "flags" /* Profile flags (Bitset) */
--#define CP_PROFILE_LASTSEEN "lastseen" /* Last-Online timestamp */
--#define CP_PROFILE_WHEREAMI "whereami" /* Where am I / Where I live */
--#define CP_PROFILE_ABOUTME "aboutme" /* About me */
--#define CP_PROFILE_RELATIONSHIP "relationship" /* Relationship Status */
--
--/* extended profile field types */
--#define CP_PROFILE_TYPE_BOOL 0x02 /* boolean (0 or 1) */
--#define CP_PROFILE_TYPE_SHORT 0x04 /* short (16-bit) */
--#define CP_PROFILE_TYPE_INT 0x05 /* integer (32-bit) */
--#define CP_PROFILE_TYPE_LONG 0x06 /* long (64-bit) */
--#define CP_PROFILE_TYPE_UTF8 0x0A /* UTF8 string */
--#define CP_PROFILE_TYPE_DATE 0x0B /* date-time (ISO 8601 format) */
--
--/* profile flags */
--#define CP_PROF_NOT_SEARCHABLE 0x02 /* user cannot be searched for */
--#define CP_PROF_NOT_SUGGESTABLE 0x08 /* user cannot be suggested as friend */
--#define CP_PROF_DOBLOCKED 0x40 /* date-of-birth cannot be changed */
--
--/* suggestion types */
--#define CP_SUGGEST_ADDRESSBOOK 0 /* address book search */
--#define CP_SUGGEST_FRIENDS 1 /* suggested friends */
--#define CP_SUGGEST_SEARCH 2 /* free-text search */
--#define CP_SUGGEST_MXITID 3 /* MXitId search */
--
--/* define this to enable protocol debugging (very verbose logging) */
--#define DEBUG_PROTOCOL
--
--
--/* ======================================================================================= */
--
--struct MXitSession;
--
--/*------------------------------------------*/
--
--struct field {
-- char* data;
-- int len;
--};
--
--struct record {
-- struct field** fields;
-- int fcount;
--};
--
--struct rx_packet {
-- int cmd;
-- int errcode;
-- char* errmsg;
-- struct record** records;
-- int rcount;
--};
--
--struct tx_packet {
-- int cmd;
-- char header[256];
-- int headerlen;
-- char* data;
-- int datalen;
--};
--
--/*------------------------------------------*/
--
--
--/*
-- * A received message data object
-- */
--struct RXMsgData {
-- struct MXitSession* session; /* MXit session object */
-- char* from; /* the sender's name */
-- time_t timestamp; /* time at which the message was sent */
-- GString* msg; /* newly created message converted to libPurple formatting */
-- gboolean got_img; /* flag to say if this message got any images/emoticons embedded */
-- short img_count; /* the amount of images/emoticons still outstanding for the message */
-- int chatid; /* multimx chatroom id */
-- int flags; /* libPurple conversation flags */
-- gboolean converted; /* true if the message has been completely parsed and converted to libPurple markup */
-- gboolean processed; /* the message has been processed completely and should be freed up */
--};
--
--
--
--/*
-- * The packet transmission queue.
-- */
--struct tx_queue {
-- struct tx_packet* packets[MAX_QUEUE_SIZE]; /* array of packet pointers */
-- int count; /* number of packets queued */
-- int rd_i; /* queue current read index (queue offset for reading a packet) */
-- int wr_i; /* queue current write index (queue offset for adding new packet) */
--};
--
--
--/* ======================================================================================= */
--
--void mxit_popup( int type, const char* heading, const char* message );
--void mxit_strip_domain( char* username );
--gboolean find_active_chat( const GList* chats, const char* who );
--
--void mxit_cb_rx( gpointer data, gint source, PurpleInputCondition cond );
--gboolean mxit_manage_queue_slow( gpointer user_data );
--gboolean mxit_manage_queue_fast( gpointer user_data );
--gboolean mxit_manage_polling( gpointer user_data );
--
--void mxit_send_register( struct MXitSession* session );
--void mxit_send_login( struct MXitSession* session );
--void mxit_send_logout( struct MXitSession* session );
--void mxit_send_ping( struct MXitSession* session );
--void mxit_send_poll( struct MXitSession* session );
--
--void mxit_send_presence( struct MXitSession* session, int presence, const char* statusmsg );
--void mxit_send_mood( struct MXitSession* session, int mood );
--void mxit_send_message( struct MXitSession* session, const char* to, const char* msg, gboolean parse_markup, gboolean is_command );
--
--void mxit_send_extprofile_update( struct MXitSession* session, const char* password, unsigned int nr_attrib, const char* attributes );
--void mxit_send_extprofile_request( struct MXitSession* session, const char* username, unsigned int nr_attrib, const char* attribute[] );
--
--void mxit_send_suggest_friends( struct MXitSession* session, int max, unsigned int nr_attrib, const char* attribute[] );
--void mxit_send_suggest_search( struct MXitSession* session, int max, const char* text, unsigned int nr_attrib, const char* attribute[] );
--
--void mxit_send_invite( struct MXitSession* session, const char* username, gboolean mxitid, const char* alias, const char* groupname, const char* message );
--void mxit_send_remove( struct MXitSession* session, const char* username );
--void mxit_send_allow_sub( struct MXitSession* session, const char* username, const char* alias );
--void mxit_send_deny_sub( struct MXitSession* session, const char* username, const char* reason );
--void mxit_send_update_contact( struct MXitSession* session, const char* username, const char* alias, const char* groupname );
--void mxit_send_splashclick( struct MXitSession* session, const char* splashid );
--void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event);
--
--void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen );
--void mxit_send_file_reject( struct MXitSession* session, const char* fileid );
--void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset );
--void mxit_send_file_received( struct MXitSession* session, const char* fileid, short status );
--void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen );
--void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const char* avatarId );
--
--void mxit_send_groupchat_create( struct MXitSession* session, const char* groupname, int nr_usernames, const char* usernames[] );
--void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid, int nr_usernames, const char* usernames[] );
--
--int mxit_parse_packet( struct MXitSession* session );
--void dump_bytes( struct MXitSession* session, const char* buf, int len );
--void mxit_close_connection( struct MXitSession* session );
--gint64 mxit_now_milli( void );
--
--
--#endif /* _MXIT_PROTO_H_ */
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/roster.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/roster.c
---- pidgin-2.10.7/libpurple/protocols/mxit/roster.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/roster.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,902 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- user roster management (mxit contacts) --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "purple.h"
--
--#include "protocol.h"
--#include "mxit.h"
--#include "roster.h"
--
--
--struct contact_invite {
-- struct MXitSession* session; /* MXit session object */
-- struct contact* contact; /* The contact performing the invite */
--};
--
--
--/*========================================================================================================================
-- * Presence / Status
-- */
--
--/* statuses (reference: libpurple/status.h) */
--static struct status
--{
-- PurpleStatusPrimitive primitive;
-- int mxit;
-- const char* id;
-- const char* name;
--} const mxit_statuses[] = {
-- /* primitive, no, id, name */
-- { PURPLE_STATUS_OFFLINE, MXIT_PRESENCE_OFFLINE, "offline", N_( "Offline" ) }, /* 0 */
-- { PURPLE_STATUS_AVAILABLE, MXIT_PRESENCE_ONLINE, "online", N_( "Available" ) }, /* 1 */
-- { PURPLE_STATUS_AWAY, MXIT_PRESENCE_AWAY, "away", N_( "Away" ) }, /* 2 */
-- { PURPLE_STATUS_AVAILABLE, MXIT_PRESENCE_AVAILABLE, "chat", N_( "Chatty" ) }, /* 3 */
-- { PURPLE_STATUS_UNAVAILABLE, MXIT_PRESENCE_DND, "dnd", N_( "Do Not Disturb" ) } /* 4 */
--};
--
--
--/*------------------------------------------------------------------------
-- * Return list of supported statuses. (see status.h)
-- *
-- * @param account The MXit account object
-- * @return List of PurpleStatusType
-- */
--GList* mxit_status_types( PurpleAccount* account )
--{
-- GList* statuslist = NULL;
-- PurpleStatusType* type;
-- unsigned int i;
--
-- for ( i = 0; i < ARRAY_SIZE( mxit_statuses ); i++ ) {
-- const struct status* status = &mxit_statuses[i];
--
-- /* add mxit status (reference: "libpurple/status.h") */
-- type = purple_status_type_new_with_attrs( status->primitive, status->id, _( status->name ), TRUE, TRUE, FALSE,
-- "message", _( "Message" ), purple_value_new( PURPLE_TYPE_STRING ),
-- NULL );
--
-- statuslist = g_list_append( statuslist, type );
-- }
--
-- /* add Mood option */
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_MOOD, "mood", NULL, FALSE, TRUE, TRUE,
-- PURPLE_MOOD_NAME, _("Mood Name"), purple_value_new( PURPLE_TYPE_STRING ),
-- NULL);
-- statuslist = g_list_append( statuslist, type );
--
-- return statuslist;
--}
--
--
--/*------------------------------------------------------------------------
-- * Returns the MXit presence code, given the unique status ID.
-- *
-- * @param id The status ID
-- * @return The MXit presence code
-- */
--int mxit_convert_presence( const char* id )
--{
-- unsigned int i;
--
-- for ( i = 0; i < ARRAY_SIZE( mxit_statuses ); i++ ) {
-- if ( strcmp( mxit_statuses[i].id, id ) == 0 ) /* status found! */
-- return mxit_statuses[i].mxit;
-- }
--
-- return -1;
--}
--
--
--/*------------------------------------------------------------------------
-- * Returns the MXit presence as a string, given the MXit presence ID.
-- *
-- * @param no The MXit presence I (see above)
-- * @return The presence as a text string
-- */
--const char* mxit_convert_presence_to_name( short no )
--{
-- unsigned int i;
--
-- for ( i = 0; i < ARRAY_SIZE( mxit_statuses ); i++ ) {
-- if ( mxit_statuses[i].mxit == no ) /* status found! */
-- return _( mxit_statuses[i].name );
-- }
--
-- return "";
--}
--
--
--/*========================================================================================================================
-- * Moods
-- */
--
--/* moods (reference: libpurple/status.h) */
--static PurpleMood mxit_moods[] = {
-- {"angry", N_("Angry"), NULL},
-- {"excited", N_("Excited"), NULL},
-- {"grumpy", N_("Grumpy"), NULL},
-- {"happy", N_("Happy"), NULL},
-- {"in_love", N_("In love"), NULL},
-- {"invincible", N_("Invincible"), NULL},
-- {"sad", N_("Sad"), NULL},
-- {"hot", N_("Hot"), NULL},
-- {"sick", N_("Sick"), NULL},
-- {"sleepy", N_("Sleepy"), NULL},
-- {"bored", N_("Bored"), NULL},
-- {"cold", N_("Cold"), NULL},
-- {"confused", N_("Confused"), NULL},
-- {"hungry", N_("Hungry"), NULL},
-- {"stressed", N_("Stressed"), NULL},
-- /* Mark the last record. */
-- { NULL, NULL, NULL }
--};
--
--
--/*------------------------------------------------------------------------
-- * Returns the MXit mood code, given the unique mood ID.
-- *
-- * @param id The mood ID
-- * @return The MXit mood code
-- */
--int mxit_convert_mood( const char* id )
--{
-- unsigned int i;
--
-- /* Mood is being unset */
-- if ( id == NULL )
-- return MXIT_MOOD_NONE;
--
-- for ( i = 0; i < ARRAY_SIZE( mxit_moods ) - 1; i++ ) {
-- if ( strcmp( mxit_moods[i].mood, id ) == 0 ) /* mood found! */
-- return i + 1; /* because MXIT_MOOD_NONE is 0 */
-- }
--
-- return -1;
--}
--
--
--/*------------------------------------------------------------------------
-- * Return the list of MXit-supported moods.
-- *
-- * @param account The MXit account object
-- */
--PurpleMood* mxit_get_moods(PurpleAccount *account)
--{
-- return mxit_moods;
--}
--
--
--/*------------------------------------------------------------------------
-- * Returns the MXit mood as a string, given the MXit mood's ID.
-- *
-- * @param id The MXit mood ID (see roster.h)
-- * @return The mood as a text string
-- */
--const char* mxit_convert_mood_to_name( short id )
--{
-- switch ( id ) {
-- case MXIT_MOOD_ANGRY :
-- return _( "Angry" );
-- case MXIT_MOOD_EXCITED :
-- return _( "Excited" );
-- case MXIT_MOOD_GRUMPY :
-- return _( "Grumpy" );
-- case MXIT_MOOD_HAPPY :
-- return _( "Happy" );
-- case MXIT_MOOD_INLOVE :
-- return _( "In Love" );
-- case MXIT_MOOD_INVINCIBLE :
-- return _( "Invincible" );
-- case MXIT_MOOD_SAD :
-- return _( "Sad" );
-- case MXIT_MOOD_HOT :
-- return _( "Hot" );
-- case MXIT_MOOD_SICK :
-- return _( "Sick" );
-- case MXIT_MOOD_SLEEPY :
-- return _( "Sleepy" );
-- case MXIT_MOOD_BORED :
-- return _( "Bored" );
-- case MXIT_MOOD_COLD :
-- return _( "Cold" );
-- case MXIT_MOOD_CONFUSED :
-- return _( "Confused" );
-- case MXIT_MOOD_HUNGRY :
-- return _( "Hungry" );
-- case MXIT_MOOD_STRESSED :
-- return _( "Stressed" );
-- case MXIT_MOOD_NONE :
-- default :
-- return "";
-- }
--}
--
--
--/*========================================================================================================================
-- * Subscription Types
-- */
--
--/*------------------------------------------------------------------------
-- * Returns a Contact subscription type as a string.
-- *
-- * @param subtype The subscription type
-- * @return The subscription type as a text string
-- */
--const char* mxit_convert_subtype_to_name( short subtype )
--{
-- switch ( subtype ) {
-- case MXIT_SUBTYPE_BOTH :
-- return _( "Both" );
-- case MXIT_SUBTYPE_PENDING :
-- return _( "Pending" );
-- case MXIT_SUBTYPE_ASK :
-- return _( "Invited" );
-- case MXIT_SUBTYPE_REJECTED :
-- return _( "Rejected" );
-- case MXIT_SUBTYPE_DELETED :
-- return _( "Deleted" );
-- case MXIT_SUBTYPE_NONE :
-- return _( "None" );
-- default :
-- return "";
-- }
--}
--
--
--/*========================================================================================================================
-- * Calls from the MXit Protocol layer
-- */
--
--#if 0
--/*------------------------------------------------------------------------
-- * Dump a contact's info the the debug console.
-- *
-- * @param contact The contact
-- */
--static void dump_contact( struct contact* contact )
--{
-- purple_debug_info( MXIT_PLUGIN_ID, "CONTACT: name='%s', alias='%s', group='%s', type='%i', presence='%i', mood='%i'\n",
-- contact->username, contact->alias, contact->groupname, contact->type, contact->presence, contact->mood );
--}
--#endif
--
--
--#if 0
--/*------------------------------------------------------------------------
-- * Move a buddy from one group to another
-- *
-- * @param buddy the buddy to move between groups
-- * @param group the new group to move the buddy to
-- */
--static PurpleBuddy* mxit_update_buddy_group( struct MXitSession* session, PurpleBuddy* buddy, PurpleGroup* group )
--{
-- struct contact* contact = NULL;
-- PurpleGroup* current_group = purple_buddy_get_group( buddy );
-- PurpleBuddy* newbuddy = NULL;
--
-- /* make sure the groups actually differs */
-- if ( strcmp( current_group->name, group->name ) != 0 ) {
-- /* groupnames does not match, so we need to make the update */
--
-- purple_debug_info( MXIT_PLUGIN_ID, "Moving '%s' from group '%s' to '%s'\n", buddy->alias, current_group->name, group->name );
--
-- /*
-- * XXX: libPurple does not currently provide an API to change or rename the group name
-- * for a specific buddy. One option is to remove the buddy from the list and re-adding
-- * him in the new group, but by doing that makes the buddy go offline and then online
-- * again. This is really not ideal and very irritating, but how else then?
-- */
--
-- /* create new buddy */
-- newbuddy = purple_buddy_new( session->acc, buddy->name, buddy->alias );
-- newbuddy->proto_data = buddy->proto_data;
-- buddy->proto_data = NULL;
--
-- /* remove the buddy */
-- purple_blist_remove_buddy( buddy );
--
-- /* add buddy */
-- purple_blist_add_buddy( newbuddy, NULL, group, NULL );
--
-- /* now re-instate his presence again */
-- contact = newbuddy->proto_data;
-- if ( contact ) {
--
-- /* update the buddy's status (reference: "libpurple/prpl.h") */
-- if ( contact->statusMsg )
-- purple_prpl_got_user_status( session->acc, newbuddy->name, mxit_statuses[contact->presence].id, "message", contact->statusMsg, NULL );
-- else
-- purple_prpl_got_user_status( session->acc, newbuddy->name, mxit_statuses[contact->presence].id, NULL );
--
-- /* update the buddy's mood */
-- if ( contact->mood == MXIT_MOOD_NONE )
-- purple_prpl_got_user_status_deactive( session->acc, newbuddy->name, "mood" );
-- else
-- purple_prpl_got_user_status( session->acc, newbuddy->name, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
--
-- /* update avatar */
-- if ( contact->avatarId ) {
-- mxit_get_avatar( session, newbuddy->name, contact->avatarId );
-- g_free( contact->avatarId );
-- contact->avatarId = NULL;
-- }
-- }
--
-- return newbuddy;
-- }
-- else
-- return buddy;
--}
--#endif
--
--
--/*------------------------------------------------------------------------
-- * A contact update packet was received from the MXit server, so update the buddy's
-- * information.
-- *
-- * @param session The MXit session object
-- * @param contact The contact
-- */
--void mxit_update_contact( struct MXitSession* session, struct contact* contact )
--{
-- PurpleBuddy* buddy = NULL;
-- PurpleGroup* group = NULL;
-- const char* id = NULL;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_update_contact: user='%s' alias='%s' group='%s'\n", contact->username, contact->alias, contact->groupname );
--
-- /*
-- * libPurple requires all contacts to be in a group.
-- * So if this MXit contact isn't in a group, pretend it is.
-- */
-- if ( *contact->groupname == '\0' ) {
-- g_strlcpy( contact->groupname, MXIT_DEFAULT_GROUP, sizeof( contact->groupname ) );
-- }
--
-- /* find or create a group for this contact */
-- group = purple_find_group( contact->groupname );
-- if ( !group )
-- group = purple_group_new( contact->groupname );
--
-- /* see if the buddy is not in the group already */
-- buddy = purple_find_buddy_in_group( session->acc, contact->username, group );
-- if ( !buddy ) {
-- /* buddy not found in the group */
--
-- /* lets try finding him in all groups */
-- buddy = purple_find_buddy( session->acc, contact->username );
-- if ( buddy ) {
-- /* ok, so we found him in another group. to switch him between groups we must delete him and add him again. */
-- purple_blist_remove_buddy( buddy );
-- buddy = NULL;
-- }
--
-- /* create new buddy */
-- buddy = purple_buddy_new( session->acc, contact->username, contact->alias );
-- purple_buddy_set_protocol_data(buddy, contact);
--
-- /* add new buddy to list */
-- purple_blist_add_buddy( buddy, NULL, group, NULL );
-- }
-- else {
-- /* buddy was found in the group */
--
-- gpointer data = NULL;
--
-- /* now update the buddy's alias */
-- purple_blist_alias_buddy( buddy, contact->alias );
--
-- /* replace the buddy's contact struct */
-- if ( ( data = purple_buddy_get_protocol_data( buddy ) ) )
-- free( data );
-- purple_buddy_set_protocol_data( buddy, contact );
-- }
--
-- /* load buddy's avatar id */
-- id = purple_buddy_icons_get_checksum_for_user( buddy );
-- if ( id )
-- contact->avatarId = g_strdup( id );
-- else
-- contact->avatarId = NULL;
--
-- /* update the buddy's status (reference: "libpurple/prpl.h") */
-- purple_prpl_got_user_status( session->acc, contact->username, mxit_statuses[contact->presence].id, NULL );
--
-- /* update the buddy's mood */
-- if ( contact->mood == MXIT_MOOD_NONE )
-- purple_prpl_got_user_status_deactive( session->acc, contact->username, "mood" );
-- else
-- purple_prpl_got_user_status( session->acc, contact->username, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
--}
--
--
--/*------------------------------------------------------------------------
-- * A presence update packet was received from the MXit server, so update the buddy's
-- * information.
-- *
-- * @param session The MXit session object
-- * @param username The contact which presence to update
-- * @param presence The new presence state for the contact
-- * @param mood The new mood for the contact
-- * @param customMood The custom mood identifier
-- * @param statusMsg This is the contact's status message
-- * @param flags The contact's presence flags.
-- */
--void mxit_update_buddy_presence( struct MXitSession* session, const char* username, short presence, short mood, const char* customMood, const char* statusMsg, int flags )
--{
-- PurpleBuddy* buddy = NULL;
-- struct contact* contact = NULL;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: user='%s' presence=%i mood=%i customMood='%s' statusMsg='%s'\n",
-- username, presence, mood, customMood, statusMsg );
--
-- if ( ( presence < MXIT_PRESENCE_OFFLINE ) || ( presence > MXIT_PRESENCE_DND ) ) {
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: invalid presence state %i\n", presence );
-- return; /* ignore packet */
-- }
--
-- /* find the buddy information for this contact (reference: "libpurple/blist.h") */
-- buddy = purple_find_buddy( session->acc, username );
-- if ( !buddy ) {
-- purple_debug_warning( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: unable to find the buddy '%s'\n", username );
-- return;
-- }
--
-- contact = purple_buddy_get_protocol_data( buddy );
-- if ( !contact )
-- return;
--
-- contact->presence = presence;
-- contact->mood = mood;
-- contact->capabilities = flags;
--
-- /* validate mood */
-- if ( ( contact->mood < MXIT_MOOD_NONE ) || ( contact->mood > MXIT_MOOD_STRESSED ) )
-- contact->mood = MXIT_MOOD_NONE;
--
-- g_strlcpy( contact->customMood, customMood, sizeof( contact->customMood ) );
-- // TODO: Download custom mood frame.
--
-- /* update status message */
-- if ( contact->statusMsg ) {
-- g_free( contact->statusMsg );
-- contact->statusMsg = NULL;
-- }
-- if ( ( statusMsg ) && ( statusMsg[0] != '\0' ) )
-- contact->statusMsg = g_markup_escape_text( statusMsg, -1 );
--
-- /* update the buddy's status (reference: "libpurple/prpl.h") */
-- if ( contact->statusMsg )
-- purple_prpl_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, "message", contact->statusMsg, NULL );
-- else
-- purple_prpl_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, NULL );
--
-- /* update the buddy's mood */
-- if ( contact->mood == MXIT_MOOD_NONE )
-- purple_prpl_got_user_status_deactive( session->acc, username, "mood" );
-- else
-- purple_prpl_got_user_status( session->acc, username, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
--}
--
--
--/*------------------------------------------------------------------------
-- * Update the buddy's avatar.
-- * Either a presence update packet was received from the MXit server, or a profile response.
-- *
-- * @param session The MXit session object
-- * @param username The contact which presence to update
-- * @param avatarId This is the contact's avatar id
-- */
--void mxit_update_buddy_avatar( struct MXitSession* session, const char* username, const char* avatarId )
--{
-- PurpleBuddy* buddy = NULL;
-- struct contact* contact = NULL;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_update_buddy_avatar: user='%s' avatar='%s'\n", username, avatarId );
--
-- /* find the buddy information for this contact (reference: "libpurple/blist.h") */
-- buddy = purple_find_buddy( session->acc, username );
-- if ( !buddy ) {
-- purple_debug_warning( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: unable to find the buddy '%s'\n", username );
-- return;
-- }
--
-- contact = purple_buddy_get_protocol_data( buddy );
-- if ( !contact )
-- return;
--
-- if ( ( contact->avatarId ) && ( g_ascii_strcasecmp( contact->avatarId, avatarId ) == 0 ) ) {
-- /* avatar has not changed - do nothing */
-- }
-- else if ( avatarId[0] != '\0' ) { /* avatar has changed */
-- if ( contact->avatarId )
-- g_free( contact->avatarId );
-- contact->avatarId = g_strdup( avatarId );
--
-- /* Send request to download new avatar image */
-- mxit_get_avatar( session, username, avatarId );
-- }
-- else /* clear current avatar */
-- purple_buddy_icons_set_for_user( session->acc, username, NULL, 0, NULL );
--}
--
--
--/*------------------------------------------------------------------------
-- * update the blist cached by libPurple. We need to do this to keep
-- * libPurple and MXit's rosters in sync with each other.
-- *
-- * @param session The MXit session object
-- */
--void mxit_update_blist( struct MXitSession* session )
--{
-- PurpleBuddy* buddy = NULL;
-- GSList* list = NULL;
-- unsigned int i;
--
-- /* remove all buddies we did not receive a roster update for.
-- * these contacts must have been removed from another client */
-- list = purple_find_buddies( session->acc, NULL );
--
-- for ( i = 0; i < g_slist_length( list ); i++ ) {
-- buddy = g_slist_nth_data( list, i );
--
-- if ( !purple_buddy_get_protocol_data( buddy ) ) {
-- const gchar* alias = purple_buddy_get_alias( buddy );
-- const gchar* name = purple_buddy_get_name( buddy );
--
-- /* this buddy should be removed, because we did not receive him in our roster update from MXit */
-- purple_debug_info( MXIT_PLUGIN_ID, "Removed 'old' buddy from the blist '%s' (%s)\n", alias, name );
-- purple_blist_remove_buddy( buddy );
-- }
-- }
--
-- /* tell the UI to update the blist */
-- purple_blist_add_account( session->acc );
--}
--
--
--/*------------------------------------------------------------------------
-- * The user authorized an invite (subscription request).
-- *
-- * @param user_data Object associated with the invite
-- */
--static void mxit_cb_buddy_auth( gpointer user_data )
--{
-- struct contact_invite* invite = (struct contact_invite*) user_data;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_buddy_auth '%s'\n", invite->contact->username );
--
-- /* send a allow subscription packet to MXit */
-- mxit_send_allow_sub( invite->session, invite->contact->username, invite->contact->alias );
--
-- /* remove the invite from our internal invites list */
-- invite->session->invites = g_list_remove( invite->session->invites, invite->contact );
--
-- /* freeup invite object */
-- if ( invite->contact->msg )
-- g_free( invite->contact->msg );
-- if ( invite->contact->statusMsg )
-- g_free( invite->contact->statusMsg );
-- if ( invite->contact->profile )
-- g_free( invite->contact->profile );
-- g_free( invite->contact );
-- g_free( invite );
--}
--
--
--/*------------------------------------------------------------------------
-- * The user rejected an invite (subscription request).
-- *
-- * @param user_data Object associated with the invite
-- */
--static void mxit_cb_buddy_deny( gpointer user_data )
--{
-- struct contact_invite* invite = (struct contact_invite*) user_data;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_buddy_deny '%s'\n", invite->contact->username );
--
-- /* send a deny subscription packet to MXit */
-- mxit_send_deny_sub( invite->session, invite->contact->username, NULL );
--
-- /* remove the invite from our internal invites list */
-- invite->session->invites = g_list_remove( invite->session->invites, invite->contact );
--
-- /* freeup invite object */
-- if ( invite->contact->msg )
-- g_free( invite->contact->msg );
-- if ( invite->contact->statusMsg )
-- g_free( invite->contact->statusMsg );
-- if ( invite->contact->profile )
-- g_free( invite->contact->profile );
-- g_free( invite->contact );
-- g_free( invite );
--}
--
--
--/*------------------------------------------------------------------------
-- * A new subscription request packet was received from the MXit server.
-- * Prompt user to accept or reject it.
-- *
-- * @param session The MXit session object
-- * @param contact The contact performing the invite
-- */
--void mxit_new_subscription( struct MXitSession* session, struct contact* contact )
--{
-- struct contact_invite* invite;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_new_subscription from '%s' (%s)\n", contact->username, contact->alias );
--
-- invite = g_new0( struct contact_invite, 1 );
-- invite->session = session;
-- invite->contact = contact;
--
-- /* add the invite to our internal invites list */
-- invite->session->invites = g_list_append( invite->session->invites, invite->contact );
--
-- /* (reference: "libpurple/account.h") */
-- purple_account_request_authorization( session->acc, contact->username, NULL, contact->alias, contact->msg, FALSE, mxit_cb_buddy_auth, mxit_cb_buddy_deny, invite );
--}
--
--
--/*------------------------------------------------------------------------
-- * Return the contact object for a mxit invite
-- *
-- * @param session The MXit session object
-- * @param username The username of the contact
-- * @return The contact object for the inviting user
-- */
--struct contact* get_mxit_invite_contact( struct MXitSession* session, const char* username )
--{
-- struct contact* con = NULL;
-- struct contact* match = NULL;
-- int i;
--
-- /* run through all the invites and try and find the match */
-- for ( i = 0; i < g_list_length( session->invites ); i++ ) {
-- con = g_list_nth_data( session->invites, i );
-- if ( strcmp( con->username, username ) == 0 ) {
-- /* invite found */
-- match = con;
-- break;
-- }
-- }
--
-- return match;
--}
--
--
--/*------------------------------------------------------------------------
-- * Return TRUE if this is a MXit Chatroom contact.
-- *
-- * @param session The MXit session object
-- * @param username The username of the contact
-- */
--gboolean is_mxit_chatroom_contact( struct MXitSession* session, const char* username )
--{
-- PurpleBuddy* buddy;
-- struct contact* contact = NULL;
--
-- /* find the buddy */
-- buddy = purple_find_buddy( session->acc, username );
-- if ( !buddy ) {
-- purple_debug_warning( MXIT_PLUGIN_ID, "is_mxit_chatroom_contact: unable to find the buddy '%s'\n", username );
-- return FALSE;
-- }
--
-- contact = purple_buddy_get_protocol_data( buddy );
-- if ( !contact )
-- return FALSE;
--
-- return ( contact->type == MXIT_TYPE_CHATROOM );
--}
--
--
--/*========================================================================================================================
-- * Callbacks from libpurple
-- */
--
--/*------------------------------------------------------------------------
-- * The user has added a buddy to the list, so send an invite request.
-- *
-- * @param gc The connection object
-- * @param buddy The new buddy
-- * @param group The group of the new buddy
-- * @param message The invite message
-- */
--void mxit_add_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group, const char* message )
--{
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
-- GSList* list = NULL;
-- PurpleBuddy* mxbuddy = NULL;
-- unsigned int i;
-- const gchar * buddy_name = purple_buddy_get_name( buddy );
-- const gchar * buddy_alias = purple_buddy_get_alias( buddy );
-- const gchar * group_name = purple_group_get_name( group );
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_add_buddy '%s' (group='%s')\n", buddy_name, group_name );
--
-- list = purple_find_buddies( session->acc, buddy_name );
-- if ( g_slist_length( list ) == 1 ) {
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_add_buddy (scenario 1) (list:%i)\n", g_slist_length( list ) );
-- /*
-- * we only send an invite to MXit when the user is not already inside our
-- * blist. this is done because purple does an add_buddy() call when
-- * you accept an invite. so in that case the user is already
-- * in our blist and ready to be chatted to.
-- */
--
-- if ( buddy_name[0] == '#' ) {
-- gchar *tmp = (gchar*) purple_base64_decode( buddy_name + 1, NULL );
-- mxit_send_invite( session, tmp, FALSE, buddy_alias, group_name, message );
-- g_free( tmp );
-- }
-- else
-- mxit_send_invite( session, buddy_name, TRUE, buddy_alias, group_name, message );
-- }
-- else {
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_add_buddy (scenario 2) (list:%i)\n", g_slist_length( list ) );
-- /*
-- * we already have the buddy in our list, so we will only update
-- * his information here and not send another invite message
-- */
--
-- /* find the correct buddy */
-- for ( i = 0; i < g_slist_length( list ); i++ ) {
-- mxbuddy = g_slist_nth_data( list, i );
--
-- if ( purple_buddy_get_protocol_data( mxbuddy ) != NULL ) {
-- /* this is our REAL MXit buddy! */
--
-- /* now update the buddy's alias */
-- purple_blist_alias_buddy( mxbuddy, buddy_alias );
--
-- /* now update the buddy's group */
--// mxbuddy = mxit_update_buddy_group( session, mxbuddy, group );
--
-- /* send the update to the MXit server */
-- mxit_send_update_contact( session, purple_buddy_get_name( mxbuddy ), purple_buddy_get_alias( mxbuddy ), group_name );
-- }
-- }
-- }
--
-- /*
-- * we remove the buddy here from the buddy list because the MXit server
-- * will send us a proper contact update packet if this succeeds. now
-- * we do not have to worry about error handling in case of adding an
-- * invalid contact. so the user will still see the contact as offline
-- * until he eventually accepts the invite.
-- */
-- purple_blist_remove_buddy( buddy );
--
-- g_slist_free( list );
--}
--
--
--/*------------------------------------------------------------------------
-- * The user has removed a buddy from the list.
-- *
-- * @param gc The connection object
-- * @param buddy The buddy being removed
-- * @param group The group the buddy was in
-- */
--void mxit_remove_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group )
--{
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
-- const gchar * buddy_name = purple_buddy_get_name( buddy );
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_remove_buddy '%s'\n", buddy_name );
--
-- mxit_send_remove( session, buddy_name );
--}
--
--
--/*------------------------------------------------------------------------
-- * The user changed the buddy's alias.
-- *
-- * @param gc The connection object
-- * @param who The username of the buddy
-- * @param alias The new alias
-- */
--void mxit_buddy_alias( PurpleConnection* gc, const char* who, const char* alias )
--{
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
-- PurpleBuddy* buddy = NULL;
-- PurpleGroup* group = NULL;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_buddy_alias '%s' to '%s\n", who, alias );
--
-- /* find the buddy */
-- buddy = purple_find_buddy( session->acc, who );
-- if ( !buddy ) {
-- purple_debug_warning( MXIT_PLUGIN_ID, "mxit_buddy_alias: unable to find the buddy '%s'\n", who );
-- return;
-- }
--
-- /* find buddy group */
-- group = purple_buddy_get_group( buddy );
-- if ( !group ) {
-- purple_debug_warning( MXIT_PLUGIN_ID, "mxit_buddy_alias: unable to find the group for buddy '%s'\n", who );
-- return;
-- }
--
-- mxit_send_update_contact( session, who, alias, purple_group_get_name( group ) );
--}
--
--
--/*------------------------------------------------------------------------
-- * The user changed the group for a single buddy.
-- *
-- * @param gc The connection object
-- * @param who The username of the buddy
-- * @param old_group The old group's name
-- * @param new_group The new group's name
-- */
--void mxit_buddy_group( PurpleConnection* gc, const char* who, const char* old_group, const char* new_group )
--{
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
-- PurpleBuddy* buddy = NULL;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_buddy_group from '%s' to '%s'\n", old_group, new_group );
--
-- /* find the buddy */
-- buddy = purple_find_buddy( session->acc, who );
-- if ( !buddy ) {
-- purple_debug_warning( MXIT_PLUGIN_ID, "mxit_buddy_group: unable to find the buddy '%s'\n", who );
-- return;
-- }
--
-- mxit_send_update_contact( session, who, purple_buddy_get_alias( buddy ), new_group );
--}
--
--
--/*------------------------------------------------------------------------
-- * The user has selected to rename a group, so update all contacts in that
-- * group.
-- *
-- * @param gc The connection object
-- * @param old_name The old group name
-- * @param group The updated group object
-- * @param moved_buddies The buddies affected by the rename
-- */
--void mxit_rename_group( PurpleConnection* gc, const char* old_name, PurpleGroup* group, GList* moved_buddies )
--{
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
-- PurpleBuddy* buddy = NULL;
-- GList* item = NULL;
--
-- purple_debug_info( MXIT_PLUGIN_ID, "mxit_rename_group from '%s' to '%s\n", old_name, purple_group_get_name( group ) );
--
-- // TODO: Might be more efficient to use the "rename group" command (cmd=29).
--
-- /* loop through all the contacts in the group and send updates */
-- item = moved_buddies;
-- while ( item ) {
-- buddy = item->data;
-- mxit_send_update_contact( session, purple_buddy_get_name( buddy ), purple_buddy_get_alias( buddy ), purple_group_get_name( group ) );
-- item = g_list_next( item );
-- }
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/roster.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/roster.h
---- pidgin-2.10.7/libpurple/protocols/mxit/roster.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/roster.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,159 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- user roster management (mxit contacts) --
-- *
-- * Pieter Loubser <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MXIT_ROSTER_H_
--#define _MXIT_ROSTER_H_
--
--
--/* MXit contact presence states */
--#define MXIT_PRESENCE_OFFLINE 0x00
--#define MXIT_PRESENCE_ONLINE 0x01
--#define MXIT_PRESENCE_AWAY 0x02
--#define MXIT_PRESENCE_AVAILABLE 0x03
--#define MXIT_PRESENCE_DND 0x04
--
--
--/* MXit contact types */
--#define MXIT_TYPE_MXIT 0x00
--#define MXIT_TYPE_JABBER 0x01
--#define MXIT_TYPE_MSN 0x02
--#define MXIT_TYPE_YAHOO 0x03
--#define MXIT_TYPE_ICQ 0x04
--#define MXIT_TYPE_AIM 0x05
--#define MXIT_TYPE_QQ 0x06
--#define MXIT_TYPE_WV 0x07
--#define MXIT_TYPE_BOT 0x08
--#define MXIT_TYPE_CHATROOM 0x09
--#define MXIT_TYPE_SMS 0x0A
--#define MXIT_TYPE_GROUP 0x0B
--#define MXIT_TYPE_GALLERY 0x0C
--#define MXIT_TYPE_INFO 0x0D
--#define MXIT_TYPE_MULTIMX 0x0E
--#define MXIT_TYPE_HYBRID 0x0F
--
--
--/* MXit contact moods */
--#define MXIT_MOOD_NONE 0x00
--#define MXIT_MOOD_ANGRY 0x01
--#define MXIT_MOOD_EXCITED 0x02
--#define MXIT_MOOD_GRUMPY 0x03
--#define MXIT_MOOD_HAPPY 0x04
--#define MXIT_MOOD_INLOVE 0x05
--#define MXIT_MOOD_INVINCIBLE 0x06
--#define MXIT_MOOD_SAD 0x07
--#define MXIT_MOOD_HOT 0x08
--#define MXIT_MOOD_SICK 0x09
--#define MXIT_MOOD_SLEEPY 0x0A
--#define MXIT_MOOD_BORED 0x0B
--#define MXIT_MOOD_COLD 0x0C
--#define MXIT_MOOD_CONFUSED 0x0D
--#define MXIT_MOOD_HUNGRY 0x0E
--#define MXIT_MOOD_STRESSED 0x0F
--
--
--/* MXit contact flags */
--//#define MXIT_CFLAG_HIDDEN 0x02 /* (DEPRECATED) */
--#define MXIT_CFLAG_GATEWAY 0x04
--#define MXIT_CFLAG_FOCUS_SEND_BLANK 0x20000
--
--
--/* MXit presence flags */
--#define MXIT_PFLAG_VOICE 0x1
--#define MXIT_PFLAG_VIDEO 0x2
--#define MXIT_PFLAG_TYPING 0x4
--
--
--/* Subscription types */
--#define MXIT_SUBTYPE_BOTH 'B'
--#define MXIT_SUBTYPE_PENDING 'P'
--#define MXIT_SUBTYPE_ASK 'A'
--#define MXIT_SUBTYPE_REJECTED 'R'
--#define MXIT_SUBTYPE_DELETED 'D'
--#define MXIT_SUBTYPE_NONE 'N'
--
--
--/* client protocol constants */
--#define MXIT_CP_MAX_JID_LEN 64
--#define MXIT_CP_MAX_GROUP_LEN 32
--#define MXIT_CP_MAX_ALIAS_LEN 100
--
--#define MXIT_DEFAULT_GROUP "MXit"
--
--
--/*
-- * a MXit contact
-- */
--struct contact {
-- char username[MXIT_CP_MAX_JID_LEN+1]; /* unique contact name (with domain) */
-- char alias[MXIT_CP_MAX_ALIAS_LEN+1]; /* contact alias (what will be seen) */
-- char groupname[MXIT_CP_MAX_GROUP_LEN+1]; /* contact group name */
--
-- short type; /* contact type */
-- short mood; /* contact current mood */
-- int flags; /* contact flags */
-- short presence; /* presence state */
-- int capabilities; /* contact capabilities */
-- short subtype; /* subscription type */
--
-- char* msg; /* invite/rejection message */
--
-- char customMood[16]; /* custom mood */
-- char* statusMsg; /* status message */
-- char* avatarId; /* avatarId */
--
-- /* invites only */
-- void* profile; /* user's profile (if available) */
-- int imgid; /* avatar image id in the imgstore */
--};
--
--/* Presence / Status */
--GList* mxit_status_types( PurpleAccount* account );
--int mxit_convert_presence( const char* id );
--const char* mxit_convert_presence_to_name( short no );
--const char* mxit_convert_subtype_to_name( short subtype );
--
--/* Moods */
--int mxit_convert_mood( const char* id );
--const char* mxit_convert_mood_to_name( short id );
--
--/* MXit Protocol callbacks */
--void mxit_update_contact( struct MXitSession* session, struct contact* contact );
--void mxit_update_buddy_presence( struct MXitSession* session, const char* username, short presence, short mood, const char* customMood, const char* statusMsg, int flags );
--void mxit_update_buddy_avatar( struct MXitSession* session, const char* username, const char* avatarId );
--void mxit_new_subscription( struct MXitSession* session, struct contact* contact );
--void mxit_update_blist( struct MXitSession* session );
--gboolean is_mxit_chatroom_contact( struct MXitSession* session, const char* username );
--struct contact* get_mxit_invite_contact( struct MXitSession* session, const char* username );
--
--/* libPurple callbacks */
--void mxit_add_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group, const char* message );
--void mxit_remove_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group );
--void mxit_buddy_alias( PurpleConnection* gc, const char* who, const char* alias );
--void mxit_buddy_group( PurpleConnection* gc, const char* who, const char* old_group, const char* new_group );
--void mxit_rename_group( PurpleConnection* gc, const char* old_name, PurpleGroup* group, GList* moved_buddies );
--PurpleMood* mxit_get_moods(PurpleAccount *account);
--
--
--#endif /* _MXIT_ROSTER_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/splashscreen.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/splashscreen.c
---- pidgin-2.10.7/libpurple/protocols/mxit/splashscreen.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/splashscreen.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,222 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- splash screens --
-- *
-- * Andrew Victor <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--
--#include "purple.h"
--#include "imgstore.h"
--
--#include "protocol.h"
--#include "mxit.h"
--#include "splashscreen.h"
--
--
--/*------------------------------------------------------------------------
-- * Return the ID of the current splash-screen.
-- *
-- * @param session The MXit session object
-- * @return The ID of the splash-screen (or NULL if no splash-screen)
-- */
--const char* splash_current(struct MXitSession* session)
--{
-- const char* splashId = purple_account_get_string(session->acc, MXIT_CONFIG_SPLASHID, NULL);
--
-- if ((splashId != NULL) && (*splashId != '\0')) {
-- purple_debug_info(MXIT_PLUGIN_ID, "Current splashId: '%s'\n", splashId);
-- return splashId;
-- }
-- else
-- return NULL;
--}
--
--
--/*------------------------------------------------------------------------
-- * Indicate if splash-screen popups are enabled.
-- *
-- * @param session The MXit session object
-- * @return TRUE if the popup is enabled.
-- */
--gboolean splash_popup_enabled(struct MXitSession* session)
--{
-- return purple_account_get_bool(session->acc, MXIT_CONFIG_SPLASHPOPUP, DEFAULT_SPLASH_POPUP);
--}
--
--
--/*------------------------------------------------------------------------
-- * Return if the current splash-screen is clickable.
-- *
-- * @param session The MXit session object
-- * @return TRUE or FALSE
-- */
--static gboolean splash_clickable(struct MXitSession* session)
--{
-- return purple_account_get_bool(session->acc, MXIT_CONFIG_SPLASHCLICK, FALSE);
--}
--
--
--/*------------------------------------------------------------------------
-- * Remove the stored splash-screen (if it exists).
-- *
-- * @param session The MXit session object
-- */
--void splash_remove(struct MXitSession* session)
--{
-- const char* splashId = NULL;
-- char* filename;
--
-- /* Get current splash ID */
-- splashId = splash_current(session);
--
-- if (splashId != NULL) {
-- purple_debug_info(MXIT_PLUGIN_ID, "Removing splashId: '%s'\n", splashId);
--
-- /* Delete stored splash image */
-- filename = g_strdup_printf("%s/mxit/%s.png", purple_user_dir(), splashId);
-- g_unlink(filename);
-- g_free(filename);
--
-- /* Clear current splash ID from settings */
-- purple_account_set_string(session->acc, MXIT_CONFIG_SPLASHID, "");
-- purple_account_set_bool(session->acc, MXIT_CONFIG_SPLASHCLICK, FALSE);
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Save a new splash-screen for later display.
-- *
-- * @param session The MXit session object
-- * @param splashID The ID of the splash-screen
-- * @param data Splash-screen image data (PNG format)
-- * @param datalen Splash-screen image data size
-- */
--void splash_update(struct MXitSession* session, const char* splashId, const char* data, int datalen, gboolean clickable)
--{
-- char* dir;
-- char* filename;
--
-- /* Remove the current splash-screen */
-- splash_remove(session);
--
-- /* Save the new splash image */
-- dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "mxit", purple_user_dir());
-- purple_build_dir(dir, S_IRUSR | S_IWUSR | S_IXUSR); /* ensure directory exists */
--
-- filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s.png", dir, purple_escape_filename(splashId));
-- if (purple_util_write_data_to_file_absolute(filename, data, datalen)) {
-- /* Store new splash-screen ID to settings */
-- purple_account_set_string(session->acc, MXIT_CONFIG_SPLASHID, splashId);
-- purple_account_set_bool(session->acc, MXIT_CONFIG_SPLASHCLICK, clickable );
-- }
--
-- g_free(dir);
-- g_free(filename);
--}
--
--
--/*------------------------------------------------------------------------
-- * The user has clicked OK on the Splash request form.
-- *
-- * @param gc The connection object
-- * @param fields The list of fields in the accepted form
-- */
--static void splash_click_ok(PurpleConnection* gc, PurpleRequestFields* fields)
--{
-- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
-- const char* splashId;
--
-- /* Get current splash ID */
-- splashId = splash_current(session);
-- if (splashId == NULL) /* no splash-screen */
-- return;
--
-- /* if is clickable, then send click event */
-- if (splash_clickable(session))
-- mxit_send_splashclick(session, splashId);
--}
--
--
--/*------------------------------------------------------------------------
-- * Display the current splash-screen.
-- *
-- * @param session The MXit session object
-- */
--void splash_display(struct MXitSession* session)
--{
-- const char* splashId = NULL;
-- char* filename;
-- gchar* imgdata;
-- gsize imglen;
-- int imgid = -1;
--
-- /* Get current splash ID */
-- splashId = splash_current(session);
-- if (splashId == NULL) /* no splash-screen */
-- return;
--
-- purple_debug_info(MXIT_PLUGIN_ID, "Display Splash: '%s'\n", splashId);
--
-- /* Load splash-screen image from file */
-- filename = g_strdup_printf("%s/mxit/%s.png", purple_user_dir(), splashId);
-- if (g_file_get_contents(filename, &imgdata, &imglen, NULL)) {
-- char buf[128];
--
-- /* Add splash-image to imagestore */
-- imgid = purple_imgstore_add_with_id(g_memdup(imgdata, imglen), imglen, NULL);
--
-- /* Generate and display message */
-- g_snprintf(buf, sizeof(buf), "<img id=\"%d\">", imgid);
--
-- /* Open a request-type popup to display the image */
-- {
-- PurpleRequestFields* fields;
-- PurpleRequestFieldGroup* group;
-- PurpleRequestField* field;
--
-- fields = purple_request_fields_new();
-- group = purple_request_field_group_new(NULL);
-- purple_request_fields_add_group(fields, group);
--
-- field = purple_request_field_image_new("splash", "", imgdata, imglen); /* add splash image */
-- purple_request_field_group_add_field(group, field);
--
-- if (splash_clickable(session)) {
-- purple_request_fields(session->con, _("MXit Advertising"), NULL, NULL, fields,
-- _("More Information"), G_CALLBACK(splash_click_ok), _("Close"), NULL, session->acc, NULL, NULL, session->con);
-- }
-- else {
-- purple_request_fields(session->con, _("MXit Advertising"), NULL, NULL, fields,
-- _("Continue"), G_CALLBACK(splash_click_ok), _("Close"), NULL, session->acc, NULL, NULL, session->con);
-- }
-- }
--
-- /* Release reference to image */
-- purple_imgstore_unref_by_id(imgid);
--
-- g_free(imgdata);
-- }
--
-- g_free(filename);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/splashscreen.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/splashscreen.h
---- pidgin-2.10.7/libpurple/protocols/mxit/splashscreen.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/splashscreen.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,59 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- splash screens --
-- *
-- * Andrew Victor <libpurple@mxit.com>
-- *
-- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MXIT_SPLASHSCREEN_H_
--#define _MXIT_SPLASHSCREEN_H_
--
--#define HANDLE_SPLASH1 "plas1.png"
--#define HANDLE_SPLASH2 "plas2.png"
--
--#define DEFAULT_SPLASH_POPUP FALSE /* disabled by default */
--
--/*
-- * Return the ID of the current splash-screen.
-- */
--const char* splash_current(struct MXitSession* session);
--
--/*
-- * Indicate if splash-screen popups are enabled.
-- */
--gboolean splash_popup_enabled(struct MXitSession* session);
--
--/*
-- * Save a new splash-screen.
-- */
--void splash_update(struct MXitSession* session, const char* splashId, const char* data, int datalen, gboolean clickable);
--
--/*
-- * Remove the stored splash-screen (if it exists).
-- */
--void splash_remove(struct MXitSession* session);
--
--/*
-- * Display the current splash-screen.
-- */
--void splash_display(struct MXitSession* session);
--
--#endif /* _MXIT_SPLASHSCREEN_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/voicevideo.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/voicevideo.c
---- pidgin-2.10.7/libpurple/protocols/mxit/voicevideo.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/voicevideo.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,242 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- voice & video --
-- *
-- * Andrew Victor <libpurple@mxit.com>
-- *
-- * (C) Copyright 2010 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "purple.h"
--#include "mxit.h"
--#include "roster.h"
--#include "voicevideo.h"
--
--#if defined(USE_VV) && defined(MXIT_DEV_VV)
--
--#warning "MXit VV support enabled."
--
--/*------------------------------------------------------------------------
-- * Does this client support Voice?
-- */
--gboolean mxit_audio_enabled(void)
--{
-- PurpleMediaManager *manager = purple_media_manager_get();
-- PurpleMediaCaps caps = purple_media_manager_get_ui_caps(manager);
--
-- return (caps & PURPLE_MEDIA_CAPS_AUDIO);
--}
--
--/*------------------------------------------------------------------------
-- * Does this client support Voice and Video?
-- */
--gboolean mxit_video_enabled(void)
--{
-- PurpleMediaManager *manager = purple_media_manager_get();
-- PurpleMediaCaps caps = purple_media_manager_get_ui_caps(manager);
--
-- return (caps & PURPLE_MEDIA_CAPS_VIDEO);
--}
--
--/*------------------------------------------------------------------------
-- * Return the list of media capabilities this contact supports.
-- *
-- * @param account The MXit account object
-- * @param who The username of the contact.
-- * @return The media capabilities supported
-- */
--PurpleMediaCaps mxit_media_caps(PurpleAccount *account, const char *who)
--{
-- struct MXitSession* session = purple_account_get_connection(account)->proto_data;
-- PurpleBuddy* buddy;
-- struct contact* contact;
-- PurpleMediaCaps capa = PURPLE_MEDIA_CAPS_NONE;
--
-- purple_debug_info(MXIT_PLUGIN_ID, "mxit_media_caps: buddy '%s'\n", who);
--
-- /* We need to have a voice/video server */
-- if (strlen(session->voip_server) == 0)
-- return PURPLE_MEDIA_CAPS_NONE;
--
-- /* find the buddy information for this contact (reference: "libpurple/blist.h") */
-- buddy = purple_find_buddy(account, who);
-- if (!buddy) {
-- purple_debug_warning(MXIT_PLUGIN_ID, "mxit_media_caps: unable to find the buddy '%s'\n", who);
-- return PURPLE_MEDIA_CAPS_NONE;
-- }
--
-- contact = purple_buddy_get_protocol_data(buddy);
-- if (!contact)
-- return PURPLE_MEDIA_CAPS_NONE;
--
-- /* can only communicate with MXit users */
-- if (contact->type != MXIT_TYPE_MXIT)
-- return PURPLE_MEDIA_CAPS_NONE;
--
-- /* and only with contacts in the 'Both' subscription state */
-- if (contact->subtype != MXIT_SUBTYPE_BOTH)
-- return PURPLE_MEDIA_CAPS_NONE;
--
-- /* and only when they're online */
-- if (contact->presence == MXIT_PRESENCE_OFFLINE)
-- return MXIT_PRESENCE_OFFLINE;
--
-- /* they support voice-only */
-- if (contact->capabilities & MXIT_PFLAG_VOICE)
-- capa |= PURPLE_MEDIA_CAPS_AUDIO;
--
-- /* they support voice-and-video */
-- if (contact->capabilities & MXIT_PFLAG_VIDEO)
-- capa |= (PURPLE_MEDIA_CAPS_AUDIO | PURPLE_MEDIA_CAPS_VIDEO | PURPLE_MEDIA_CAPS_AUDIO_VIDEO);
--
-- return capa;
--}
--
--
--static void mxit_candidates_prepared_cb(PurpleMedia* media, gchar* sessionid, gchar* who, void* session)
--{
-- purple_debug_info(MXIT_PLUGIN_ID, "mxit_candidates_prepared_cb: buddy '%s', session '%s'\n", who, sessionid);
--
-- if (purple_media_is_initiator(media, sessionid, who)) {
-- // TODO: Send INVITE via SIP.
-- }
-- else {
-- // TODO: ??
-- }
--}
--
--static void mxit_stream_info_cb(PurpleMedia* media, PurpleMediaInfoType type, char* sessionid, gchar* who, gboolean local, void* session)
--{
-- purple_debug_info(MXIT_PLUGIN_ID, "mxit_stream_info_cb: buddy '%s', session '%s', info %d \n", who, sessionid, type);
--
-- switch (type) {
-- case PURPLE_MEDIA_INFO_HANGUP:
-- break;
-- case PURPLE_MEDIA_INFO_ACCEPT:
-- break;
-- case PURPLE_MEDIA_INFO_REJECT:
-- break;
-- case PURPLE_MEDIA_INFO_MUTE:
-- break;
-- case PURPLE_MEDIA_INFO_UNMUTE:
-- break;
-- case PURPLE_MEDIA_INFO_PAUSE:
-- break;
-- case PURPLE_MEDIA_INFO_UNPAUSE:
-- break;
-- case PURPLE_MEDIA_INFO_HOLD:
-- break;
-- case PURPLE_MEDIA_INFO_UNHOLD:
-- break;
-- }
--}
--
--static void mxit_state_changed_cb(PurpleMedia* media, PurpleMediaState state, gchar* sessionid, char* who, void* session)
--{
-- purple_debug_info(MXIT_PLUGIN_ID, "mxit_state_changed_cb: buddy '%s', session '%s', state %d\n", who, sessionid, state);
--
-- switch (state) {
-- case PURPLE_MEDIA_STATE_NEW:
-- break;
-- case PURPLE_MEDIA_STATE_CONNECTED:
-- break;
-- case PURPLE_MEDIA_STATE_END:
-- break;
-- }
--}
--
--
--/*------------------------------------------------------------------------
-- * Initiate a voice/video session with a contact.
-- *
-- * @param account The MXit account object
-- * @param who The username of the contact.
-- * @param type The type of media session to initiate
-- * @return TRUE if session was initiated
-- */
--gboolean mxit_media_initiate(PurpleAccount *account, const char *who, PurpleMediaSessionType type)
--{
-- gchar* transmitter = "rawudp";
-- PurpleMedia* media = NULL;
--
-- purple_debug_info(MXIT_PLUGIN_ID, "mxit_media_initiate: buddy '%s'\n", who);
--
-- media = purple_media_manager_create_media(
-- purple_media_manager_get(),
-- account,
-- "fsrtpconference",
-- who,
-- TRUE
-- );
--
-- if (!media) {
-- purple_debug_info(MXIT_PLUGIN_ID, "mxit_media_initiate: could not create media session\n");
-- return FALSE;
-- }
--
-- /* attach callbacks */
-- g_signal_connect(G_OBJECT(media), "candidates-prepared", G_CALLBACK(mxit_candidates_prepared_cb), NULL);
-- g_signal_connect(G_OBJECT(media), "stream-info", G_CALLBACK(mxit_stream_info_cb), NULL);
-- g_signal_connect(G_OBJECT(media), "state-changed", G_CALLBACK(mxit_state_changed_cb), NULL);
--
-- /* initiate audio session */
-- if ((type & PURPLE_MEDIA_AUDIO) &&
-- (!purple_media_add_stream(media, "audio", who, PURPLE_MEDIA_AUDIO, TRUE, transmitter, 0, NULL))) {
-- purple_media_end(media, NULL, NULL);
-- return FALSE;
-- }
--
-- /* initiate video session */
-- if ((type & PURPLE_MEDIA_VIDEO) &&
-- (!purple_media_add_stream(media, "video", who, PURPLE_MEDIA_VIDEO, TRUE, transmitter, 0, NULL))) {
-- purple_media_end(media, NULL, NULL);
-- return FALSE;
-- }
--
-- return TRUE;
--}
--
--#else
--
--/*
-- * Voice and Video not supported.
-- */
--
--gboolean mxit_audio_enabled(void)
--{
-- return FALSE;
--}
--
--gboolean mxit_video_enabled(void)
--{
-- return FALSE;
--}
--
--PurpleMediaCaps mxit_media_caps(PurpleAccount *account, const char *who)
--{
-- return PURPLE_MEDIA_CAPS_NONE;
--}
--
--gboolean mxit_media_initiate(PurpleAccount *account, const char *who, PurpleMediaSessionType type)
--{
-- return FALSE;
--}
--
--#endif
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/voicevideo.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/voicevideo.h
---- pidgin-2.10.7/libpurple/protocols/mxit/voicevideo.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/voicevideo.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,41 +0,0 @@
--/*
-- * MXit Protocol libPurple Plugin
-- *
-- * -- voice & video --
-- *
-- * Andrew Victor <libpurple@mxit.com>
-- *
-- * (C) Copyright 2010 MXit Lifestyle (Pty) Ltd.
-- * <http://www.mxitlifestyle.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MXIT_VOICEVICEO_H_
--#define _MXIT_VOICEVIDEO_H_
--
--#include "media.h"
--
--
--#undef MXIT_DEV_VV
--
--
--gboolean mxit_audio_enabled(void);
--gboolean mxit_video_enabled(void);
--PurpleMediaCaps mxit_media_caps(PurpleAccount* account, const char* who);
--gboolean mxit_media_initiate(PurpleAccount* account, const char* who, PurpleMediaSessionType type);
--
--
--#endif /* _MXIT_VOICEVIDEO_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/myspace/Makefile.am
---- pidgin-2.10.7/libpurple/protocols/myspace/Makefile.am 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/Makefile.am 1969-12-31 21:00:00.000000000 -0300
-@@ -1,44 +0,0 @@
--EXTRA_DIST = \
-- Makefile.mingw
--
--pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
--
--MSIMSOURCES = markup.c \
-- markup.h \
-- message.c \
-- message.h \
-- myspace.c \
-- myspace.h \
-- persist.h \
-- session.c \
-- session.h \
-- user.c \
-- user.h \
-- zap.c \
-- zap.h
--
--AM_CFLAGS = $(st)
--
--libmyspace_la_LDFLAGS = -module -avoid-version
--
--if STATIC_MYSPACE
--
--st = -DPURPLE_STATIC_PRPL
--noinst_LTLIBRARIES = libmyspace.la
--libmyspace_la_SOURCES = $(MSIMSOURCES)
--libmyspace_la_CFLAGS = $(AM_CFLAGS)
--
--else
--
--st =
--pkg_LTLIBRARIES = libmyspace.la
--libmyspace_la_SOURCES = $(MSIMSOURCES)
--libmyspace_la_LIBADD = $(GLIB_LIBS)
--
--endif
--
--AM_CPPFLAGS = \
-- -I$(top_srcdir)/libpurple \
-- -I$(top_builddir)/libpurple \
-- $(GLIB_CFLAGS) \
-- $(DEBUG_CFLAGS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/myspace/Makefile.in
---- pidgin-2.10.7/libpurple/protocols/myspace/Makefile.in 2013-02-11 07:17:21.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/Makefile.in 1969-12-31 21:00:00.000000000 -0300
-@@ -1,803 +0,0 @@
--# Makefile.in generated by automake 1.11.6 from Makefile.am.
--# @configure_input@
--
--# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
--# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
--# Foundation, Inc.
--# This Makefile.in is free software; the Free Software Foundation
--# gives unlimited permission to copy and/or distribute it,
--# with or without modifications, as long as this notice is preserved.
--
--# This program is distributed in the hope that it will be useful,
--# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
--# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
--# PARTICULAR PURPOSE.
--
--@SET_MAKE@
--
--VPATH = @srcdir@
--am__make_dryrun = \
-- { \
-- am__dry=no; \
-- case $$MAKEFLAGS in \
-- *\\[\ \ ]*) \
-- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
-- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
-- *) \
-- for am__flg in $$MAKEFLAGS; do \
-- case $$am__flg in \
-- *=*|--*) ;; \
-- *n*) am__dry=yes; break;; \
-- esac; \
-- done;; \
-- esac; \
-- test $$am__dry = yes; \
-- }
--pkgdatadir = $(datadir)/@PACKAGE@
--pkgincludedir = $(includedir)/@PACKAGE@
--pkglibdir = $(libdir)/@PACKAGE@
--pkglibexecdir = $(libexecdir)/@PACKAGE@
--am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
--install_sh_DATA = $(install_sh) -c -m 644
--install_sh_PROGRAM = $(install_sh) -c
--install_sh_SCRIPT = $(install_sh) -c
--INSTALL_HEADER = $(INSTALL_DATA)
--transform = $(program_transform_name)
--NORMAL_INSTALL = :
--PRE_INSTALL = :
--POST_INSTALL = :
--NORMAL_UNINSTALL = :
--PRE_UNINSTALL = :
--POST_UNINSTALL = :
--build_triplet = @build@
--host_triplet = @host@
--subdir = libpurple/protocols/myspace
--DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
--ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
--am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
-- $(top_srcdir)/configure.ac
--am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-- $(ACLOCAL_M4)
--mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
--CONFIG_HEADER = $(top_builddir)/config.h
--CONFIG_CLEAN_FILES =
--CONFIG_CLEAN_VPATH_FILES =
--am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
--am__vpath_adj = case $$p in \
-- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
-- *) f=$$p;; \
-- esac;
--am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
--am__install_max = 40
--am__nobase_strip_setup = \
-- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
--am__nobase_strip = \
-- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
--am__nobase_list = $(am__nobase_strip_setup); \
-- for p in $$list; do echo "$$p $$p"; done | \
-- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
-- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
-- if (++n[$$2] == $(am__install_max)) \
-- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
-- END { for (dir in files) print dir, files[dir] }'
--am__base_list = \
-- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
-- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
--am__uninstall_files_from_dir = { \
-- test -z "$$files" \
-- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
-- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
-- $(am__cd) "$$dir" && rm -f $$files; }; \
-- }
--am__installdirs = "$(DESTDIR)$(pkgdir)"
--LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkg_LTLIBRARIES)
--am__DEPENDENCIES_1 =
--@STATIC_MYSPACE_FALSE@libmyspace_la_DEPENDENCIES = \
--@STATIC_MYSPACE_FALSE@ $(am__DEPENDENCIES_1)
--am__libmyspace_la_SOURCES_DIST = markup.c markup.h message.c message.h \
-- myspace.c myspace.h persist.h session.c session.h user.c \
-- user.h zap.c zap.h
--am__objects_1 = libmyspace_la-markup.lo libmyspace_la-message.lo \
-- libmyspace_la-myspace.lo libmyspace_la-session.lo \
-- libmyspace_la-user.lo libmyspace_la-zap.lo
--@STATIC_MYSPACE_FALSE@am_libmyspace_la_OBJECTS = $(am__objects_1)
--@STATIC_MYSPACE_TRUE@am_libmyspace_la_OBJECTS = $(am__objects_1)
--libmyspace_la_OBJECTS = $(am_libmyspace_la_OBJECTS)
--AM_V_lt = $(am__v_lt_@AM_V@)
--am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
--am__v_lt_0 = --silent
--libmyspace_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libmyspace_la_CFLAGS) \
-- $(CFLAGS) $(libmyspace_la_LDFLAGS) $(LDFLAGS) -o $@
--@STATIC_MYSPACE_FALSE@am_libmyspace_la_rpath = -rpath $(pkgdir)
--@STATIC_MYSPACE_TRUE@am_libmyspace_la_rpath =
--DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
--depcomp = $(SHELL) $(top_srcdir)/depcomp
--am__depfiles_maybe = depfiles
--am__mv = mv -f
--COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
--LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-- $(AM_CFLAGS) $(CFLAGS)
--AM_V_CC = $(am__v_CC_@AM_V@)
--am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
--am__v_CC_0 = @echo " CC " $@;
--AM_V_at = $(am__v_at_@AM_V@)
--am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
--am__v_at_0 = @
--CCLD = $(CC)
--LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-- $(AM_LDFLAGS) $(LDFLAGS) -o $@
--AM_V_CCLD = $(am__v_CCLD_@AM_V@)
--am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
--am__v_CCLD_0 = @echo " CCLD " $@;
--AM_V_GEN = $(am__v_GEN_@AM_V@)
--am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
--am__v_GEN_0 = @echo " GEN " $@;
--SOURCES = $(libmyspace_la_SOURCES)
--DIST_SOURCES = $(am__libmyspace_la_SOURCES_DIST)
--am__can_run_installinfo = \
-- case $$AM_UPDATE_INFO_DIR in \
-- n|no|NO) false;; \
-- *) (install-info --version) >/dev/null 2>&1;; \
-- esac
--ETAGS = etags
--CTAGS = ctags
--DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
--ACLOCAL = @ACLOCAL@
--ALLOCA = @ALLOCA@
--ALL_LINGUAS = @ALL_LINGUAS@
--AMTAR = @AMTAR@
--AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
--AR = @AR@
--AUTOCONF = @AUTOCONF@
--AUTOHEADER = @AUTOHEADER@
--AUTOMAKE = @AUTOMAKE@
--AVAHI_CFLAGS = @AVAHI_CFLAGS@
--AVAHI_LIBS = @AVAHI_LIBS@
--AWK = @AWK@
--CATALOGS = @CATALOGS@
--CATOBJEXT = @CATOBJEXT@
--CC = @CC@
--CCDEPMODE = @CCDEPMODE@
--CFLAGS = @CFLAGS@
--CHECK_CFLAGS = @CHECK_CFLAGS@
--CHECK_LIBS = @CHECK_LIBS@
--CPP = @CPP@
--CPPFLAGS = @CPPFLAGS@
--CYGPATH_W = @CYGPATH_W@
--DATADIRNAME = @DATADIRNAME@
--DBUS_CFLAGS = @DBUS_CFLAGS@
--DBUS_LIBS = @DBUS_LIBS@
--DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
--DEBUG_CFLAGS = @DEBUG_CFLAGS@
--DEFS = @DEFS@
--DEPDIR = @DEPDIR@
--DLLTOOL = @DLLTOOL@
--DOT = @DOT@
--DOXYGEN = @DOXYGEN@
--DSYMUTIL = @DSYMUTIL@
--DUMPBIN = @DUMPBIN@
--DYNALOADER_A = @DYNALOADER_A@
--DYNAMIC_PRPLS = @DYNAMIC_PRPLS@
--ECHO_C = @ECHO_C@
--ECHO_N = @ECHO_N@
--ECHO_T = @ECHO_T@
--EGREP = @EGREP@
--EVOLUTION_ADDRESSBOOK_CFLAGS = @EVOLUTION_ADDRESSBOOK_CFLAGS@
--EVOLUTION_ADDRESSBOOK_LIBS = @EVOLUTION_ADDRESSBOOK_LIBS@
--EXEEXT = @EXEEXT@
--FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
--FARSTREAM_LIBS = @FARSTREAM_LIBS@
--FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
--GCONFTOOL = @GCONFTOOL@
--GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
--GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
--GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
--GLIB_CFLAGS = @GLIB_CFLAGS@
--GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
--GLIB_LIBS = @GLIB_LIBS@
--GMOFILES = @GMOFILES@
--GMSGFMT = @GMSGFMT@
--GNT_CFLAGS = @GNT_CFLAGS@
--GNT_LIBS = @GNT_LIBS@
--GNT_LT_VERSION_INFO = @GNT_LT_VERSION_INFO@
--GNT_MAJOR_VERSION = @GNT_MAJOR_VERSION@
--GNT_MICRO_VERSION = @GNT_MICRO_VERSION@
--GNT_MINOR_VERSION = @GNT_MINOR_VERSION@
--GNT_VERSION = @GNT_VERSION@
--GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
--GNUTLS_LIBS = @GNUTLS_LIBS@
--GREP = @GREP@
--GSTINTERFACES_CFLAGS = @GSTINTERFACES_CFLAGS@
--GSTINTERFACES_LIBS = @GSTINTERFACES_LIBS@
--GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
--GSTREAMER_LIBS = @GSTREAMER_LIBS@
--GTKSPELL_CFLAGS = @GTKSPELL_CFLAGS@
--GTKSPELL_LIBS = @GTKSPELL_LIBS@
--GTK_CFLAGS = @GTK_CFLAGS@
--GTK_LIBS = @GTK_LIBS@
--IDN_CFLAGS = @IDN_CFLAGS@
--IDN_LIBS = @IDN_LIBS@
--INSTALL = @INSTALL@
--INSTALL_DATA = @INSTALL_DATA@
--INSTALL_PROGRAM = @INSTALL_PROGRAM@
--INSTALL_SCRIPT = @INSTALL_SCRIPT@
--INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
--INSTOBJEXT = @INSTOBJEXT@
--INTLLIBS = @INTLLIBS@
--INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
--INTLTOOL_MERGE = @INTLTOOL_MERGE@
--INTLTOOL_PERL = @INTLTOOL_PERL@
--INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
--INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
--INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
--INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
--INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
--KRB4_CFLAGS = @KRB4_CFLAGS@
--KRB4_LDFLAGS = @KRB4_LDFLAGS@
--KRB4_LIBS = @KRB4_LIBS@
--LD = @LD@
--LDADD = @LDADD@
--LDFLAGS = @LDFLAGS@
--LIBOBJS = @LIBOBJS@
--LIBPERL_A = @LIBPERL_A@
--LIBS = @LIBS@
--LIBTOOL = @LIBTOOL@
--LIBXML_CFLAGS = @LIBXML_CFLAGS@
--LIBXML_LIBS = @LIBXML_LIBS@
--LIPO = @LIPO@
--LN_S = @LN_S@
--LTLIBOBJS = @LTLIBOBJS@
--MAKEINFO = @MAKEINFO@
--MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
--MKDIR_P = @MKDIR_P@
--MKINSTALLDIRS = @MKINSTALLDIRS@
--MONO_CFLAGS = @MONO_CFLAGS@
--MONO_LIBS = @MONO_LIBS@
--MSGFMT = @MSGFMT@
--MSGFMT_OPTS = @MSGFMT_OPTS@
--MSGMERGE = @MSGMERGE@
--NETWORKMANAGER_CFLAGS = @NETWORKMANAGER_CFLAGS@
--NETWORKMANAGER_LIBS = @NETWORKMANAGER_LIBS@
--NM = @NM@
--NMEDIT = @NMEDIT@
--NSS_CFLAGS = @NSS_CFLAGS@
--NSS_LIBS = @NSS_LIBS@
--OBJDUMP = @OBJDUMP@
--OBJEXT = @OBJEXT@
--OTOOL = @OTOOL@
--OTOOL64 = @OTOOL64@
--PACKAGE = @PACKAGE@
--PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
--PACKAGE_NAME = @PACKAGE_NAME@
--PACKAGE_STRING = @PACKAGE_STRING@
--PACKAGE_TARNAME = @PACKAGE_TARNAME@
--PACKAGE_URL = @PACKAGE_URL@
--PACKAGE_VERSION = @PACKAGE_VERSION@
--PANGO_CFLAGS = @PANGO_CFLAGS@
--PANGO_LIBS = @PANGO_LIBS@
--PATH_SEPARATOR = @PATH_SEPARATOR@
--PERL = @PERL@
--PERL_CFLAGS = @PERL_CFLAGS@
--PERL_LIBS = @PERL_LIBS@
--PKG_CONFIG = @PKG_CONFIG@
--PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
--PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
--PLUGINS_DEFINE = @PLUGINS_DEFINE@
--POFILES = @POFILES@
--POSUB = @POSUB@
--PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
--PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
--PURPLE_LT_VERSION_INFO = @PURPLE_LT_VERSION_INFO@
--PURPLE_MAJOR_VERSION = @PURPLE_MAJOR_VERSION@
--PURPLE_MICRO_VERSION = @PURPLE_MICRO_VERSION@
--PURPLE_MINOR_VERSION = @PURPLE_MINOR_VERSION@
--PURPLE_VERSION = @PURPLE_VERSION@
--PYTHON = @PYTHON@
--PY_CFLAGS = @PY_CFLAGS@
--PY_LIBS = @PY_LIBS@
--RANLIB = @RANLIB@
--SASL_LIBS = @SASL_LIBS@
--SED = @SED@
--SET_MAKE = @SET_MAKE@
--SHELL = @SHELL@
--SILC_CFLAGS = @SILC_CFLAGS@
--SILC_LIBS = @SILC_LIBS@
--SM_LIBS = @SM_LIBS@
--SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
--SQLITE3_LIBS = @SQLITE3_LIBS@
--SSL_CERTIFICATES_DIR = @SSL_CERTIFICATES_DIR@
--STATIC_LINK_LIBS = @STATIC_LINK_LIBS@
--STATIC_PRPLS = @STATIC_PRPLS@
--STRIP = @STRIP@
--TCL_CFLAGS = @TCL_CFLAGS@
--TCL_LIBS = @TCL_LIBS@
--TK_LIBS = @TK_LIBS@
--USE_NLS = @USE_NLS@
--VERSION = @VERSION@
--X11_CFLAGS = @X11_CFLAGS@
--X11_LIBS = @X11_LIBS@
--XGETTEXT = @XGETTEXT@
--XMKMF = @XMKMF@
--XSLTPROC = @XSLTPROC@
--XSS_LIBS = @XSS_LIBS@
--X_CFLAGS = @X_CFLAGS@
--X_EXTRA_LIBS = @X_EXTRA_LIBS@
--X_LIBS = @X_LIBS@
--X_PRE_LIBS = @X_PRE_LIBS@
--ZEPHYR_CFLAGS = @ZEPHYR_CFLAGS@
--ZEPHYR_LDFLAGS = @ZEPHYR_LDFLAGS@
--ZEPHYR_LIBS = @ZEPHYR_LIBS@
--abs_builddir = @abs_builddir@
--abs_srcdir = @abs_srcdir@
--abs_top_builddir = @abs_top_builddir@
--abs_top_srcdir = @abs_top_srcdir@
--ac_ct_AR = @ac_ct_AR@
--ac_ct_CC = @ac_ct_CC@
--ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
--am__include = @am__include@
--am__leading_dot = @am__leading_dot@
--am__quote = @am__quote@
--am__tar = @am__tar@
--am__untar = @am__untar@
--bindir = @bindir@
--build = @build@
--build_alias = @build_alias@
--build_cpu = @build_cpu@
--build_os = @build_os@
--build_vendor = @build_vendor@
--builddir = @builddir@
--datadir = @datadir@
--datarootdir = @datarootdir@
--docdir = @docdir@
--dvidir = @dvidir@
--enable_dbus = @enable_dbus@
--enable_devhelp = @enable_devhelp@
--enable_dot = @enable_dot@
--enable_doxygen = @enable_doxygen@
--exec_prefix = @exec_prefix@
--host = @host@
--host_alias = @host_alias@
--host_cpu = @host_cpu@
--host_os = @host_os@
--host_vendor = @host_vendor@
--htmldir = @htmldir@
--includedir = @includedir@
--infodir = @infodir@
--install_sh = @install_sh@
--intltool__v_merge_options_ = @intltool__v_merge_options_@
--intltool__v_merge_options_0 = @intltool__v_merge_options_0@
--libdir = @libdir@
--libexecdir = @libexecdir@
--localedir = @localedir@
--localstatedir = @localstatedir@
--mandir = @mandir@
--mkdir_p = @mkdir_p@
--oldincludedir = @oldincludedir@
--pdfdir = @pdfdir@
--perlpath = @perlpath@
--pidginpath = @pidginpath@
--prefix = @prefix@
--program_transform_name = @program_transform_name@
--psdir = @psdir@
--sbindir = @sbindir@
--sedpath = @sedpath@
--sharedstatedir = @sharedstatedir@
--srcdir = @srcdir@
--sysconfdir = @sysconfdir@
--target_alias = @target_alias@
--top_build_prefix = @top_build_prefix@
--top_builddir = @top_builddir@
--top_srcdir = @top_srcdir@
--EXTRA_DIST = \
-- Makefile.mingw
--
--pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
--MSIMSOURCES = markup.c \
-- markup.h \
-- message.c \
-- message.h \
-- myspace.c \
-- myspace.h \
-- persist.h \
-- session.c \
-- session.h \
-- user.c \
-- user.h \
-- zap.c \
-- zap.h
--
--AM_CFLAGS = $(st)
--libmyspace_la_LDFLAGS = -module -avoid-version
--@STATIC_MYSPACE_FALSE@st =
--@STATIC_MYSPACE_TRUE@st = -DPURPLE_STATIC_PRPL
--@STATIC_MYSPACE_TRUE@noinst_LTLIBRARIES = libmyspace.la
--@STATIC_MYSPACE_FALSE@libmyspace_la_SOURCES = $(MSIMSOURCES)
--@STATIC_MYSPACE_TRUE@libmyspace_la_SOURCES = $(MSIMSOURCES)
--@STATIC_MYSPACE_TRUE@libmyspace_la_CFLAGS = $(AM_CFLAGS)
--@STATIC_MYSPACE_FALSE@pkg_LTLIBRARIES = libmyspace.la
--@STATIC_MYSPACE_FALSE@libmyspace_la_LIBADD = $(GLIB_LIBS)
--AM_CPPFLAGS = \
-- -I$(top_srcdir)/libpurple \
-- -I$(top_builddir)/libpurple \
-- $(GLIB_CFLAGS) \
-- $(DEBUG_CFLAGS)
--
--all: all-am
--
--.SUFFIXES:
--.SUFFIXES: .c .lo .o .obj
--$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
-- @for dep in $?; do \
-- case '$(am__configure_deps)' in \
-- *$$dep*) \
-- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
-- && { if test -f $@; then exit 0; else break; fi; }; \
-- exit 1;; \
-- esac; \
-- done; \
-- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpurple/protocols/myspace/Makefile'; \
-- $(am__cd) $(top_srcdir) && \
-- $(AUTOMAKE) --gnu libpurple/protocols/myspace/Makefile
--.PRECIOUS: Makefile
--Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-- @case '$?' in \
-- *config.status*) \
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-- *) \
-- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-- esac;
--
--$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--
--$(top_srcdir)/configure: $(am__configure_deps)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--$(ACLOCAL_M4): $(am__aclocal_m4_deps)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--$(am__aclocal_m4_deps):
--
--clean-noinstLTLIBRARIES:
-- -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-- @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
-- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-- test "$$dir" != "$$p" || dir=.; \
-- echo "rm -f \"$${dir}/so_locations\""; \
-- rm -f "$${dir}/so_locations"; \
-- done
--install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES)
-- @$(NORMAL_INSTALL)
-- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
-- list2=; for p in $$list; do \
-- if test -f $$p; then \
-- list2="$$list2 $$p"; \
-- else :; fi; \
-- done; \
-- test -z "$$list2" || { \
-- echo " $(MKDIR_P) '$(DESTDIR)$(pkgdir)'"; \
-- $(MKDIR_P) "$(DESTDIR)$(pkgdir)" || exit 1; \
-- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgdir)'"; \
-- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgdir)"; \
-- }
--
--uninstall-pkgLTLIBRARIES:
-- @$(NORMAL_UNINSTALL)
-- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
-- for p in $$list; do \
-- $(am__strip_dir) \
-- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgdir)/$$f'"; \
-- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgdir)/$$f"; \
-- done
--
--clean-pkgLTLIBRARIES:
-- -test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES)
-- @list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
-- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-- test "$$dir" != "$$p" || dir=.; \
-- echo "rm -f \"$${dir}/so_locations\""; \
-- rm -f "$${dir}/so_locations"; \
-- done
--libmyspace.la: $(libmyspace_la_OBJECTS) $(libmyspace_la_DEPENDENCIES) $(EXTRA_libmyspace_la_DEPENDENCIES)
-- $(AM_V_CCLD)$(libmyspace_la_LINK) $(am_libmyspace_la_rpath) $(libmyspace_la_OBJECTS) $(libmyspace_la_LIBADD) $(LIBS)
--
--mostlyclean-compile:
-- -rm -f *.$(OBJEXT)
--
--distclean-compile:
-- -rm -f *.tab.c
--
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmyspace_la-markup.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmyspace_la-message.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmyspace_la-myspace.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmyspace_la-session.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmyspace_la-user.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmyspace_la-zap.Plo@am__quote@
--
--.c.o:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
--
--.c.obj:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
--
--.c.lo:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
--
--libmyspace_la-markup.lo: markup.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -MT libmyspace_la-markup.lo -MD -MP -MF $(DEPDIR)/libmyspace_la-markup.Tpo -c -o libmyspace_la-markup.lo `test -f 'markup.c' || echo '$(srcdir)/'`markup.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmyspace_la-markup.Tpo $(DEPDIR)/libmyspace_la-markup.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='markup.c' object='libmyspace_la-markup.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -c -o libmyspace_la-markup.lo `test -f 'markup.c' || echo '$(srcdir)/'`markup.c
--
--libmyspace_la-message.lo: message.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -MT libmyspace_la-message.lo -MD -MP -MF $(DEPDIR)/libmyspace_la-message.Tpo -c -o libmyspace_la-message.lo `test -f 'message.c' || echo '$(srcdir)/'`message.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmyspace_la-message.Tpo $(DEPDIR)/libmyspace_la-message.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='message.c' object='libmyspace_la-message.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -c -o libmyspace_la-message.lo `test -f 'message.c' || echo '$(srcdir)/'`message.c
--
--libmyspace_la-myspace.lo: myspace.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -MT libmyspace_la-myspace.lo -MD -MP -MF $(DEPDIR)/libmyspace_la-myspace.Tpo -c -o libmyspace_la-myspace.lo `test -f 'myspace.c' || echo '$(srcdir)/'`myspace.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmyspace_la-myspace.Tpo $(DEPDIR)/libmyspace_la-myspace.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='myspace.c' object='libmyspace_la-myspace.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -c -o libmyspace_la-myspace.lo `test -f 'myspace.c' || echo '$(srcdir)/'`myspace.c
--
--libmyspace_la-session.lo: session.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -MT libmyspace_la-session.lo -MD -MP -MF $(DEPDIR)/libmyspace_la-session.Tpo -c -o libmyspace_la-session.lo `test -f 'session.c' || echo '$(srcdir)/'`session.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmyspace_la-session.Tpo $(DEPDIR)/libmyspace_la-session.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='session.c' object='libmyspace_la-session.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -c -o libmyspace_la-session.lo `test -f 'session.c' || echo '$(srcdir)/'`session.c
--
--libmyspace_la-user.lo: user.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -MT libmyspace_la-user.lo -MD -MP -MF $(DEPDIR)/libmyspace_la-user.Tpo -c -o libmyspace_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmyspace_la-user.Tpo $(DEPDIR)/libmyspace_la-user.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user.c' object='libmyspace_la-user.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -c -o libmyspace_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c
--
--libmyspace_la-zap.lo: zap.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -MT libmyspace_la-zap.lo -MD -MP -MF $(DEPDIR)/libmyspace_la-zap.Tpo -c -o libmyspace_la-zap.lo `test -f 'zap.c' || echo '$(srcdir)/'`zap.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmyspace_la-zap.Tpo $(DEPDIR)/libmyspace_la-zap.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='zap.c' object='libmyspace_la-zap.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -c -o libmyspace_la-zap.lo `test -f 'zap.c' || echo '$(srcdir)/'`zap.c
--
--mostlyclean-libtool:
-- -rm -f *.lo
--
--clean-libtool:
-- -rm -rf .libs _libs
--
--ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- mkid -fID $$unique
--tags: TAGS
--
--TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
-- $(TAGS_FILES) $(LISP)
-- set x; \
-- here=`pwd`; \
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- shift; \
-- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-- test -n "$$unique" || unique=$$empty_fix; \
-- if test $$# -gt 0; then \
-- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-- "$$@" $$unique; \
-- else \
-- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-- $$unique; \
-- fi; \
-- fi
--ctags: CTAGS
--CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
-- $(TAGS_FILES) $(LISP)
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- test -z "$(CTAGS_ARGS)$$unique" \
-- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-- $$unique
--
--GTAGS:
-- here=`$(am__cd) $(top_builddir) && pwd` \
-- && $(am__cd) $(top_srcdir) \
-- && gtags -i $(GTAGS_ARGS) "$$here"
--
--distclean-tags:
-- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
--
--distdir: $(DISTFILES)
-- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-- list='$(DISTFILES)'; \
-- dist_files=`for file in $$list; do echo $$file; done | \
-- sed -e "s|^$$srcdirstrip/||;t" \
-- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-- case $$dist_files in \
-- */*) $(MKDIR_P) `echo "$$dist_files" | \
-- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-- sort -u` ;; \
-- esac; \
-- for file in $$dist_files; do \
-- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-- if test -d $$d/$$file; then \
-- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-- if test -d "$(distdir)/$$file"; then \
-- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-- fi; \
-- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-- fi; \
-- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-- else \
-- test -f "$(distdir)/$$file" \
-- || cp -p $$d/$$file "$(distdir)/$$file" \
-- || exit 1; \
-- fi; \
-- done
--check-am: all-am
--check: check-am
--all-am: Makefile $(LTLIBRARIES)
--installdirs:
-- for dir in "$(DESTDIR)$(pkgdir)"; do \
-- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
-- done
--install: install-am
--install-exec: install-exec-am
--install-data: install-data-am
--uninstall: uninstall-am
--
--install-am: all-am
-- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
--
--installcheck: installcheck-am
--install-strip:
-- if test -z '$(STRIP)'; then \
-- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-- install; \
-- else \
-- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-- fi
--mostlyclean-generic:
--
--clean-generic:
--
--distclean-generic:
-- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
--
--maintainer-clean-generic:
-- @echo "This command is intended for maintainers to use"
-- @echo "it deletes files that may require special tools to rebuild."
--clean: clean-am
--
--clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
-- clean-pkgLTLIBRARIES mostlyclean-am
--
--distclean: distclean-am
-- -rm -rf ./$(DEPDIR)
-- -rm -f Makefile
--distclean-am: clean-am distclean-compile distclean-generic \
-- distclean-tags
--
--dvi: dvi-am
--
--dvi-am:
--
--html: html-am
--
--html-am:
--
--info: info-am
--
--info-am:
--
--install-data-am: install-pkgLTLIBRARIES
--
--install-dvi: install-dvi-am
--
--install-dvi-am:
--
--install-exec-am:
--
--install-html: install-html-am
--
--install-html-am:
--
--install-info: install-info-am
--
--install-info-am:
--
--install-man:
--
--install-pdf: install-pdf-am
--
--install-pdf-am:
--
--install-ps: install-ps-am
--
--install-ps-am:
--
--installcheck-am:
--
--maintainer-clean: maintainer-clean-am
-- -rm -rf ./$(DEPDIR)
-- -rm -f Makefile
--maintainer-clean-am: distclean-am maintainer-clean-generic
--
--mostlyclean: mostlyclean-am
--
--mostlyclean-am: mostlyclean-compile mostlyclean-generic \
-- mostlyclean-libtool
--
--pdf: pdf-am
--
--pdf-am:
--
--ps: ps-am
--
--ps-am:
--
--uninstall-am: uninstall-pkgLTLIBRARIES
--
--.MAKE: install-am install-strip
--
--.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
-- clean-libtool clean-noinstLTLIBRARIES clean-pkgLTLIBRARIES \
-- ctags distclean distclean-compile distclean-generic \
-- distclean-libtool distclean-tags distdir dvi dvi-am html \
-- html-am info info-am install install-am install-data \
-- install-data-am install-dvi install-dvi-am install-exec \
-- install-exec-am install-html install-html-am install-info \
-- install-info-am install-man install-pdf install-pdf-am \
-- install-pkgLTLIBRARIES install-ps install-ps-am install-strip \
-- installcheck installcheck-am installdirs maintainer-clean \
-- maintainer-clean-generic mostlyclean mostlyclean-compile \
-- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-- tags uninstall uninstall-am uninstall-pkgLTLIBRARIES
--
--
--# Tell versions [3.59,3.63) of GNU make to not export all variables.
--# Otherwise a system limit (for SysV at least) may be exceeded.
--.NOEXPORT:
-diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/myspace/Makefile.mingw
---- pidgin-2.10.7/libpurple/protocols/myspace/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,81 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of libmyspace
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = libmyspace
--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)
--
--LIB_PATHS = -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = myspace.c message.c zap.c session.c markup.c user.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lws2_32 \
-- -lintl \
-- -lpurple
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll
--
--install: all $(DLL_INSTALL_DIR)
-- cp $(TARGET).dll $(DLL_INSTALL_DIR)
--
--$(OBJECTS): $(PURPLE_CONFIG_H)
--
--##
--## BUILD DLL
--##
--$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--
--clean:
-- rm -f $(OBJECTS)
-- rm -f $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/markup.c pidgin-2.10.7-nonprism/libpurple/protocols/myspace/markup.c
---- pidgin-2.10.7/libpurple/protocols/myspace/markup.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/markup.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,763 +0,0 @@
--/* MySpaceIM Protocol Plugin - markup
-- *
-- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "myspace.h"
--
--typedef int (*MSIM_XMLNODE_CONVERT)(MsimSession *, xmlnode *, gchar **, gchar **);
--
--/* Globals */
--
--/* The names in in emoticon_names (for <i n=whatever>) map to corresponding
-- * entries in emoticon_symbols (for the ASCII representation of the emoticon).
-- *
-- * Multiple emoticon symbols in Pidgin can map to one name. List the
-- * canonical form, as inserted by the "Smile!" dialog, first. For example,
-- * :) comes before :-), because although both are recognized as 'happy',
-- * the first is inserted by the smiley button (first symbol in theme).
-- *
-- * Note that symbols are case-sensitive in Pidgin -- :-X is not :-x. */
--static struct MSIM_EMOTICON
--{
-- gchar *name;
-- gchar *symbol;
--} msim_emoticons[] = {
-- /* Unfortunately, this list duplicates much of the file
-- * pidgin/pidgin/pixmaps/emotes/default/22/default.theme.in, because
-- * that file is part of Pidgin, but we're part of libpurple.
-- */
-- { "bigsmile", ":D" },
-- { "bigsmile", ":-D" },
-- { "devil", "}:)" },
-- { "frazzled", ":Z" },
-- { "geek", "B)" },
-- { "googles", "%)" },
-- { "growl", ":E" },
-- { "laugh", ":))" }, /* Must be before ':)' */
-- { "happy", ":)" },
-- { "happy", ":-)" },
-- { "happi", ":)" },
-- { "heart", ":X" },
-- { "mohawk", "-:" },
-- { "mad", "X(" },
-- { "messed", "X)" },
-- { "nerd", "Q)" },
-- { "oops", ":G" },
-- { "pirate", "P)" },
-- { "scared", ":O" },
-- { "sidefrown", ":{" },
-- { "sinister", ":B" },
-- { "smirk", ":," },
-- { "straight", ":|" },
-- { "tongue", ":P" },
-- { "tongue", ":p" },
-- { "tongy", ":P" },
-- { "upset", "B|" },
-- { "wink", ";-)" },
-- { "wink", ";)" },
-- { "winc", ";)" },
-- { "worried", ":[" },
-- { "kiss", ":x" },
-- { NULL, NULL }
--};
--
--/* Indexes of this array + 1 map HTML font size to scale of normal font size. *
-- * Based on _point_sizes from libpurple/gtkimhtml.c
-- * 1 2 3 4 5 6 7 */
--static gdouble _font_scale[] = { .85, .95, 1, 1.2, 1.44, 1.728, 2.0736 };
--
--/* Purple maximum font size. Equivalent to sizeof(_font_scale) / sizeof(_font_scale[0]) */
--#define MAX_FONT_SIZE 7
--
--#define POINTS_PER_INCH 72 /* How many pt's in an inch */
--
--/* Text formatting bits for <f s=#> */
--#define MSIM_TEXT_BOLD 1
--#define MSIM_TEXT_ITALIC 2
--#define MSIM_TEXT_UNDERLINE 4
--
--/* Default baseline size of purple's fonts, in points. What is size 3 in points.
-- * _font_scale specifies scaling factor relative to this point size. Note this
-- * is only the default; it is configurable in account options. */
--#define MSIM_BASE_FONT_POINT_SIZE 8
--
--/* Default display's DPI. 96 is common but it can differ. Also configurable
-- * in account options. */
--#define MSIM_DEFAULT_DPI 96
--
--/* round is part of C99, but sometimes is unavailable before then.
-- * Based on http://forums.belution.com/en/cpp/000/050/13.shtml
-- */
--static double msim_round(double value)
--{
-- if (value < 0) {
-- return -(floor(-value + 0.5));
-- } else {
-- return floor( value + 0.5);
-- }
--}
--
--/**
-- * Convert typographical font point size to HTML font size.
-- * Based on libpurple/gtkimhtml.c
-- */
--static guint
--msim_point_to_purple_size(MsimSession *session, guint point)
--{
-- guint size, this_point, base;
--
-- base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
--
-- for (size = 0; size < MAX_FONT_SIZE; ++size) {
-- this_point = (guint)msim_round(base * _font_scale[size]);
--
-- if (this_point >= point) {
-- purple_debug_info("msim", "msim_point_to_purple_size: %d pt -> size=%d\n",
-- point, size);
-- return size;
-- }
-- }
--
-- /* No HTML font size was this big; return largest possible. */
-- return this_point;
--}
--
--/**
-- * Convert HTML font size to point size.
-- */
--static guint
--msim_purple_size_to_point(MsimSession *session, guint size)
--{
-- gdouble scale;
-- guint point;
-- guint base;
--
-- scale = _font_scale[CLAMP(size, 1, MAX_FONT_SIZE) - 1];
--
-- base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
--
-- point = (guint)msim_round(scale * base);
--
-- purple_debug_info("msim", "msim_purple_size_to_point: size=%d -> %d pt\n",
-- size, point);
--
-- return point;
--}
--
--/**
-- * Convert a msim markup font pixel height to the more usual point size, for incoming messages.
-- */
--static guint
--msim_height_to_point(MsimSession *session, guint height)
--{
-- guint dpi;
--
-- dpi = purple_account_get_int(session->account, "dpi", MSIM_DEFAULT_DPI);
--
-- return (guint)msim_round((POINTS_PER_INCH * 1. / dpi) * height);
--
-- /* See also: libpurple/protocols/bonjour/jabber.c
-- * _font_size_ichat_to_purple */
--}
--
--/**
-- * Convert point size to msim pixel height font size specification, for outgoing messages.
-- */
--static guint
--msim_point_to_height(MsimSession *session, guint point)
--{
-- guint dpi;
--
-- dpi = purple_account_get_int(session->account, "dpi", MSIM_DEFAULT_DPI);
--
-- return (guint)msim_round((dpi * 1. / POINTS_PER_INCH) * point);
--}
--
--/**
-- * Convert the msim markup <f> (font) tag into HTML.
-- */
--static void
--msim_markup_f_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
--{
-- const gchar *face, *height_str, *decor_str;
-- GString *gs_end, *gs_begin;
-- guint decor, height;
--
-- face = xmlnode_get_attrib(root, "f");
-- height_str = xmlnode_get_attrib(root, "h");
-- decor_str = xmlnode_get_attrib(root, "s");
--
-- /* Validate the font face, to avoid constructing invalid HTML later */
-- if (face != NULL && strchr(face, '\'') != NULL)
-- face = NULL;
--
-- height = height_str != NULL ? atol(height_str) : 12;
-- decor = decor_str != NULL ? atol(decor_str) : 0;
--
-- /*
-- * The HTML we're constructing here is a bit redudant. Ideally we
-- * would use only the font-family and font-size CSS span, but Pidgin
-- * doesn't support it (it's included for other UIs). For Pidgin we
-- * wrap the whole thing in an ugly font tag, and Pidgin will happily
-- * ignore the <span>.
-- */
-- gs_begin = g_string_new("");
-- if (height && !face) {
-- guint point_size = msim_height_to_point(session, height);
-- g_string_printf(gs_begin,
-- "<font size='%d'><span style='font-size: %dpt'>",
-- msim_point_to_purple_size(session, point_size),
-- point_size);
-- } else if (height && face) {
-- guint point_size = msim_height_to_point(session, height);
-- g_string_printf(gs_begin,
-- "<font face='%s' size='%d'><span style='font-family: %s; font-size: %dpt'>",
-- face, msim_point_to_purple_size(session, point_size),
-- face, point_size);
-- } else {
-- g_string_printf(gs_begin, "<font><span>");
-- }
--
-- gs_end = g_string_new("</span></font>");
--
-- if (decor & MSIM_TEXT_BOLD) {
-- g_string_append(gs_begin, "<b>");
-- g_string_prepend(gs_end, "</b>");
-- }
--
-- if (decor & MSIM_TEXT_ITALIC) {
-- g_string_append(gs_begin, "<i>");
-- g_string_append(gs_end, "</i>");
-- }
--
-- if (decor & MSIM_TEXT_UNDERLINE) {
-- g_string_append(gs_begin, "<u>");
-- g_string_append(gs_end, "</u>");
-- }
--
-- *begin = g_string_free(gs_begin, FALSE);
-- *end = g_string_free(gs_end, FALSE);
--}
--
--/**
-- * Convert a msim markup color to a color suitable for libpurple.
-- *
-- * @param msim Either a color name, or an rgb(x,y,z) code.
-- *
-- * @return A new string, either a color name or #rrggbb code. Must g_free().
-- */
--static char *
--msim_color_to_purple(const char *msim)
--{
-- guint red, green, blue;
--
-- if (!msim) {
-- return g_strdup("black");
-- }
--
-- if (sscanf(msim, "rgb(%d,%d,%d)", &red, &green, &blue) != 3) {
-- /* Color name. */
-- return g_strdup(msim);
-- }
-- /* TODO: rgba (alpha). */
--
-- return g_strdup_printf("#%.2x%.2x%.2x", red, green, blue);
--}
--
--/**
-- * Convert the msim markup <a> (anchor) tag into HTML.
-- */
--static void
--msim_markup_a_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
--{
-- const gchar *href;
--
-- href = xmlnode_get_attrib(root, "h");
-- if (!href) {
-- href = "";
-- }
--
-- *begin = g_strdup_printf("<a href=\"%s\">%s", href, href);
-- *end = g_strdup("</a>");
--}
--
--/**
-- * Convert the msim markup <p> (paragraph) tag into HTML.
-- */
--static void
--msim_markup_p_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
--{
-- /* Just pass through unchanged.
-- *
-- * Note: attributes currently aren't passed, if there are any. */
-- *begin = g_strdup("<p>");
-- *end = g_strdup("</p>");
--}
--
--/**
-- * Convert the msim markup <c> tag (text color) into HTML.
-- */
--static void
--msim_markup_c_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
--{
-- const gchar *color;
-- gchar *purple_color;
--
-- color = xmlnode_get_attrib(root, "v");
-- if (!color) {
-- purple_debug_info("msim", "msim_markup_c_to_html: <c> tag w/o v attr\n");
-- *begin = g_strdup("");
-- *end = g_strdup("");
-- /* TODO: log as unrecognized */
-- return;
-- }
--
-- purple_color = msim_color_to_purple(color);
--
--#ifdef USE_CSS_FORMATTING
-- *begin = g_strdup_printf("<span style='color: %s'>", purple_color);
-- *end = g_strdup("</span>");
--#else
-- *begin = g_strdup_printf("<font color='%s'>", purple_color);
-- *end = g_strdup("</font>");
--#endif
--
-- g_free(purple_color);
--}
--
--/**
-- * Convert the msim markup <b> tag (background color) into HTML.
-- */
--static void
--msim_markup_b_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
--{
-- const gchar *color;
-- gchar *purple_color;
--
-- color = xmlnode_get_attrib(root, "v");
-- if (!color) {
-- *begin = g_strdup("");
-- *end = g_strdup("");
-- purple_debug_info("msim", "msim_markup_b_to_html: <b> w/o v attr\n");
-- /* TODO: log as unrecognized. */
-- return;
-- }
--
-- purple_color = msim_color_to_purple(color);
--
--#ifdef USE_CSS_FORMATTING
-- *begin = g_strdup_printf("<span style='background-color: %s'>", purple_color);
-- *end = g_strdup("</span>");
--#else
-- *begin = g_strdup_printf("<body bgcolor='%s'>", purple_color);
-- *end = g_strdup("</body>");
--#endif
--
-- g_free(purple_color);
--}
--
--/**
-- * Convert the msim markup <i> tag (emoticon image) into HTML.
-- */
--static void
--msim_markup_i_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
--{
-- const gchar *name;
-- guint i;
-- struct MSIM_EMOTICON *emote;
--
-- name = xmlnode_get_attrib(root, "n");
-- if (!name) {
-- purple_debug_info("msim", "msim_markup_i_to_html: <i> w/o n\n");
-- *begin = g_strdup("");
-- *end = g_strdup("");
-- /* TODO: log as unrecognized */
-- return;
-- }
--
-- /* Find and use canonical form of smiley symbol. */
-- for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) {
-- if (g_str_equal(name, emote->name)) {
-- *begin = g_strdup(emote->symbol);
-- *end = g_strdup("");
-- return;
-- }
-- }
--
-- /* Couldn't find it, sorry. Try to degrade gracefully. */
-- *begin = g_strdup_printf("**%s**", name);
-- *end = g_strdup("");
--}
--
--/**
-- * Convert an individual msim markup tag to HTML.
-- */
--static int
--msim_markup_tag_to_html(MsimSession *session, xmlnode *root, gchar **begin,
-- gchar **end)
--{
-- g_return_val_if_fail(root != NULL, 0);
--
-- if (g_str_equal(root->name, "f")) {
-- msim_markup_f_to_html(session, root, begin, end);
-- } else if (g_str_equal(root->name, "a")) {
-- msim_markup_a_to_html(session, root, begin, end);
-- } else if (g_str_equal(root->name, "p")) {
-- msim_markup_p_to_html(session, root, begin, end);
-- } else if (g_str_equal(root->name, "c")) {
-- msim_markup_c_to_html(session, root, begin, end);
-- } else if (g_str_equal(root->name, "b")) {
-- msim_markup_b_to_html(session, root, begin, end);
-- } else if (g_str_equal(root->name, "i")) {
-- msim_markup_i_to_html(session, root, begin, end);
-- } else {
-- purple_debug_info("msim", "msim_markup_tag_to_html: "
-- "unknown tag name=%s, ignoring\n",
-- root->name ? root->name : "(NULL)");
-- *begin = g_strdup("");
-- *end = g_strdup("");
-- }
-- return 0;
--}
--
--/**
-- * Convert an individual HTML tag to msim markup.
-- */
--static int
--html_tag_to_msim_markup(MsimSession *session, xmlnode *root, gchar **begin,
-- gchar **end)
--{
-- int ret = 0;
--
-- if (!purple_utf8_strcasecmp(root->name, "root") ||
-- !purple_utf8_strcasecmp(root->name, "html")) {
-- *begin = g_strdup("");
-- *end = g_strdup("");
-- /* TODO: Coalesce nested tags into one <f> tag!
-- * Currently, the 's' value will be overwritten when b/i/u is nested
-- * within another one, and only the inner-most formatting will be
-- * applied to the text. */
-- } else if (!purple_utf8_strcasecmp(root->name, "b")) {
-- if (root->child->type == XMLNODE_TYPE_DATA) {
-- *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_BOLD);
-- *end = g_strdup("</f>");
-- } else {
-- if (!purple_utf8_strcasecmp(root->child->name,"i")) {
-- ret++;
-- if (root->child->child->type == XMLNODE_TYPE_DATA) {
-- *begin = g_strdup_printf("<f s='%d'>", (MSIM_TEXT_BOLD + MSIM_TEXT_ITALIC));
-- *end = g_strdup("</f>");
-- } else {
-- if (!purple_utf8_strcasecmp(root->child->child->name,"u")) {
-- ret++;
-- *begin = g_strdup_printf("<f s='%d'>", (MSIM_TEXT_BOLD + MSIM_TEXT_ITALIC + MSIM_TEXT_UNDERLINE));
-- *end = g_strdup("</f>");
-- }
-- }
-- } else if (!purple_utf8_strcasecmp(root->child->name,"u")) {
-- ret++;
-- *begin = g_strdup_printf("<f s='%d'>", (MSIM_TEXT_BOLD + MSIM_TEXT_UNDERLINE));
-- *end = g_strdup("</f>");
-- }
-- }
-- } else if (!purple_utf8_strcasecmp(root->name, "i")) {
-- if (root->child->type == XMLNODE_TYPE_DATA) {
-- *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_ITALIC);
-- *end = g_strdup("</f>");
-- } else {
-- if (!purple_utf8_strcasecmp(root->child->name,"u")) {
-- ret++;
-- *begin = g_strdup_printf("<f s='%d'>", (MSIM_TEXT_ITALIC + MSIM_TEXT_UNDERLINE));
-- *end = g_strdup("</f>");
-- }
-- }
-- } else if (!purple_utf8_strcasecmp(root->name, "u")) {
-- *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_UNDERLINE);
-- *end = g_strdup("</f>");
-- } else if (!purple_utf8_strcasecmp(root->name, "a")) {
-- const gchar *href;
-- gchar *link_text;
--
-- href = xmlnode_get_attrib(root, "href");
--
-- if (!href) {
-- href = xmlnode_get_attrib(root, "HREF");
-- }
--
-- link_text = xmlnode_get_data(root);
--
-- if (href) {
-- if (g_str_equal(link_text, href)) {
-- /* Purple gives us: <a href="URL">URL</a>
-- * Translate to <a h='URL' />
-- * Displayed as text of URL with link to URL
-- */
-- *begin = g_strdup_printf("<a h='%s' />", href);
-- } else {
-- /* But if we get: <a href="URL">text</a>
-- * Translate to: text: <a h='URL' />
-- *
-- * Because official client only supports self-closed <a>
-- * tags; you can't change the link text.
-- */
-- *begin = g_strdup_printf("%s: <a h='%s' />", link_text, href);
-- }
-- } else {
-- *begin = g_strdup("<a />");
-- }
--
-- /* Sorry, kid. MySpace doesn't support you within <a> tags. */
-- xmlnode_free(root->child);
-- g_free(link_text);
-- root->child = NULL;
--
-- *end = g_strdup("");
-- } else if (!purple_utf8_strcasecmp(root->name, "font")) {
-- GString *tmpbegin, *tmpend;
-- const gchar *size;
-- const gchar *face;
-- const gchar *color;
--
-- size = xmlnode_get_attrib(root, "size");
-- face = xmlnode_get_attrib(root, "face");
-- color = xmlnode_get_attrib(root, "color");
--
-- tmpbegin = g_string_new("<f");
-- tmpend = g_string_new("</f>");
--
-- if (face != NULL)
-- g_string_append_printf(tmpbegin, " f='%s'", face);
--
-- if (size != NULL)
-- g_string_append_printf(tmpbegin, " h='%d'",
-- msim_point_to_height(session,
-- msim_purple_size_to_point(session, atoi(size))));
--
-- /* Close the <f> tag */
-- g_string_append(tmpbegin, ">");
--
-- if (color != NULL) {
-- g_string_append_printf(tmpbegin, "<c v='%s'>", color);
-- g_string_prepend(tmpend, "</c>");
-- }
--
-- *begin = g_string_free(tmpbegin, FALSE);
-- *end = g_string_free(tmpend, FALSE);
--
-- } else if (!purple_utf8_strcasecmp(root->name, "body")) {
-- const gchar *bgcolor;
--
-- bgcolor = xmlnode_get_attrib(root, "bgcolor");
--
-- if (bgcolor != NULL) {
-- *begin = g_strdup_printf("<b v='%s'>", bgcolor);
-- *end = g_strdup("</b>");
-- }
--
-- } else {
-- gchar *err;
--
--#ifdef MSIM_MARKUP_SHOW_UNKNOWN_TAGS
-- *begin = g_strdup_printf("[%s]", root->name);
-- *end = g_strdup_printf("[/%s]", root->name);
--#else
-- *begin = g_strdup("");
-- *end = g_strdup("");
--#endif
--
-- err = g_strdup_printf("html_tag_to_msim_markup: unrecognized "
-- "HTML tag %s was sent by the IM client; ignoring",
-- root->name ? root->name : "(NULL)");
-- msim_unrecognized(NULL, NULL, err);
-- g_free(err);
-- }
-- return ret;
--}
--
--/**
-- * Convert an xmlnode of msim markup or HTML to an HTML string or msim markup.
-- *
-- * @param f Function to convert tags.
-- *
-- * @return An HTML string. Caller frees.
-- */
--static void
--msim_convert_xmlnode(MsimSession *session, GString *out, xmlnode *root, MSIM_XMLNODE_CONVERT f, int nodes_processed)
--{
-- xmlnode *node;
-- gchar *begin, *end, *tmp;
-- int descended = nodes_processed;
--
-- if (!root || !root->name)
-- return;
--
-- purple_debug_info("msim", "msim_convert_xmlnode: got root=%s\n",
-- root->name);
--
-- begin = end = NULL;
--
-- if (descended == 0) /* We've not formatted this yet.. :) */
-- descended = f(session, root, &begin, &end); /* Get the value that our format function has already descended for us */
--
-- g_string_append(out, begin);
-- g_free(begin);
--
-- /* Loop over all child nodes. */
-- for (node = root->child; node != NULL; node = node->next) {
-- switch (node->type) {
-- case XMLNODE_TYPE_ATTRIB:
-- /* Attributes handled above. */
-- break;
--
-- case XMLNODE_TYPE_TAG:
-- /* A tag or tag with attributes. Recursively descend. */
-- msim_convert_xmlnode(session, out, node, f, descended);
--
-- purple_debug_info("msim", " ** node name=%s\n",
-- node->name ? node->name : "(NULL)");
-- break;
--
-- case XMLNODE_TYPE_DATA:
-- /* Literal text. */
-- /*
-- * TODO: Why is it necessary to escape here? I thought
-- * node->data was already escaped?
-- */
-- tmp = g_markup_escape_text(node->data, node->data_sz);
-- g_string_append(out, tmp);
-- g_free(tmp);
-- break;
--
-- default:
-- purple_debug_warning("msim",
-- "msim_convert_xmlnode: unknown node type\n");
-- }
-- }
--
-- /* TODO: Note that msim counts each piece of text enclosed by <f> as
-- * a paragraph and will display each on its own line. You actually have
-- * to _nest_ <f> tags to intersperse different text in one paragraph!
-- * Comment out this line below to see. */
-- g_string_append(out, end);
-- g_free(end);
--}
--
--/**
-- * Convert XML to something based on MSIM_XMLNODE_CONVERT.
-- */
--static gchar *
--msim_convert_xml(MsimSession *session, const gchar *raw, MSIM_XMLNODE_CONVERT f)
--{
-- xmlnode *root;
-- GString *str;
-- gchar *enclosed_raw;
--
-- g_return_val_if_fail(raw != NULL, NULL);
--
-- /* Enclose text in one root tag, to try to make it valid XML for parsing. */
-- enclosed_raw = g_strconcat("<root>", raw, "</root>", NULL);
--
-- root = xmlnode_from_str(enclosed_raw, -1);
--
-- if (!root) {
-- purple_debug_warning("msim", "msim_markup_to_html: couldn't parse "
-- "%s as XML, returning raw: %s\n", enclosed_raw, raw);
-- /* TODO: msim_unrecognized */
-- g_free(enclosed_raw);
-- return g_strdup(raw);
-- }
--
-- g_free(enclosed_raw);
--
-- str = g_string_new(NULL);
-- msim_convert_xmlnode(session, str, root, f, 0);
-- xmlnode_free(root);
--
-- purple_debug_info("msim", "msim_markup_to_html: returning %s\n", str->str);
--
-- return g_string_free(str, FALSE);
--}
--
--/**
-- * Convert plaintext smileys to <i> markup tags.
-- *
-- * @param before Original text with ASCII smileys. Will be freed.
-- * @return A new string with <i> tags, if applicable. Must be g_free()'d.
-- */
--static gchar *
--msim_convert_smileys_to_markup(gchar *before)
--{
-- gchar *old, *new, *replacement;
-- guint i;
-- struct MSIM_EMOTICON *emote;
--
-- old = before;
-- new = NULL;
--
-- for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) {
-- gchar *name, *symbol;
--
-- name = emote->name;
-- symbol = emote->symbol;
--
-- replacement = g_strdup_printf("<i n=\"%s\"/>", name);
--
-- purple_debug_info("msim", "msim_convert_smileys_to_markup: %s->%s\n",
-- symbol ? symbol : "(NULL)",
-- replacement ? replacement : "(NULL)");
-- new = purple_strreplace(old, symbol, replacement);
--
-- g_free(replacement);
-- g_free(old);
--
-- old = new;
-- }
--
-- return new;
--}
--
--/**
-- * High-level function to convert MySpaceIM markup to Purple (HTML) markup.
-- *
-- * @return Purple markup string, must be g_free()'d. */
--gchar *
--msim_markup_to_html(MsimSession *session, const gchar *raw)
--{
-- return msim_convert_xml(session, raw, msim_markup_tag_to_html);
--}
--
--/**
-- * High-level function to convert Purple (HTML) to MySpaceIM markup.
-- *
-- * TODO: consider using purple_markup_html_to_xhtml() to make valid XML.
-- *
-- * @return HTML markup string, must be g_free()'d. */
--gchar *
--html_to_msim_markup(MsimSession *session, const gchar *raw)
--{
-- gchar *markup;
--
-- markup = msim_convert_xml(session, raw, html_tag_to_msim_markup);
--
-- if (purple_account_get_bool(session->account, "emoticons", TRUE)) {
-- /* Frees markup and allocates a new one. */
-- markup = msim_convert_smileys_to_markup(markup);
-- }
--
-- return markup;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/markup.h pidgin-2.10.7-nonprism/libpurple/protocols/myspace/markup.h
---- pidgin-2.10.7/libpurple/protocols/myspace/markup.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/markup.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,27 +0,0 @@
--/* MySpaceIM Protocol Plugin - markup
-- *
-- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MYSPACE_MARKUP_H
--#define _MYSPACE_MARKUP_H
--
--/* High-level msim markup <=> Purple html conversion functions. */
--gchar *msim_markup_to_html(MsimSession *, const gchar *raw);
--gchar *html_to_msim_markup(MsimSession *, const gchar *raw);
--
--#endif /* !_MYSPACE_MARKUP_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/message.c pidgin-2.10.7-nonprism/libpurple/protocols/myspace/message.c
---- pidgin-2.10.7/libpurple/protocols/myspace/message.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/message.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1413 +0,0 @@
--/** MySpaceIM protocol messages
-- *
-- * \author Jeff Connelly
-- *
-- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "myspace.h"
--#include "message.h"
--
--static void msim_msg_debug_string_element(gpointer data, gpointer user_data);
--
--/**
-- * Escape codes and associated replacement text, used for protocol message
-- * escaping and unescaping.
-- */
--static struct MSIM_ESCAPE_REPLACEMENT {
-- gchar *code;
-- gchar text;
--} msim_escape_replacements[] = {
-- { "/1", '/' },
-- { "/2", '\\' },
-- /* { "/3", "|" }, */ /* Not used here -- only for within arrays */
-- { NULL, 0 }
--};
--
--/**
-- * Escape a protocol message.
-- *
-- * @return The escaped message. Caller must g_free().
-- */
--gchar *
--msim_escape(const gchar *msg)
--{
-- GString *gs;
-- guint i, j;
-- guint msg_len;
--
-- gs = g_string_new("");
-- msg_len = strlen(msg);
--
-- for (i = 0; i < msg_len; ++i) {
-- struct MSIM_ESCAPE_REPLACEMENT *replacement;
-- gchar *replace;
--
-- replace = NULL;
--
-- /* Check for characters that need to be escaped, and escape them. */
-- for (j = 0; (replacement = &msim_escape_replacements[j]) &&
-- replacement->code != NULL; ++j) {
-- if (msg[i] == replacement->text) {
-- replace = replacement->code;
-- break;
-- }
-- }
--
-- if (replace) {
-- g_string_append(gs, replace);
-- } else {
-- g_string_append_c(gs, msg[i]);
-- }
-- }
--
--#ifdef MSIM_DEBUG_ESCAPE
-- purple_debug_info("msim", "msim_escape: msg=%s, ret=%s\n", msg, gs->str);
--#endif
--
-- return g_string_free(gs, FALSE);
--}
--
--/**
-- * Unescape a protocol message.
-- *
-- * @return The unescaped message, caller must g_free().
-- */
--gchar *
--msim_unescape(const gchar *msg)
--{
-- GString *gs;
-- guint i, j;
-- guint msg_len;
--
-- gs = g_string_new("");
-- msg_len = strlen(msg);
--
-- for (i = 0; i < msg_len; ++i) {
-- struct MSIM_ESCAPE_REPLACEMENT *replacement;
-- gchar replace;
--
-- replace = msg[i];
--
-- for (j = 0; (replacement = &msim_escape_replacements[j]) &&
-- replacement->code != NULL; ++j) {
-- if (msg[i] == replacement->code[0] &&
-- i + 1 < msg_len &&
-- msg[i + 1] == replacement->code[1]) {
-- replace = replacement->text;
-- ++i;
-- break;
-- }
-- }
--
-- g_string_append_c(gs, replace);
-- }
--
--#ifdef MSIM_DEBUG_ESCAPE
-- purple_debug_info("msim", "msim_unescape: msg=%s, ret=%s\n", msg, gs->str);
--#endif
--
-- return g_string_free(gs, FALSE);
--}
--
--/**
-- * Create a new message from va_list and its first argument.
-- *
-- * @param first_key The first argument (a key), or NULL to take all arguments
-- * from argp.
-- * @param argp A va_list of variadic arguments, already started with va_start().
-- * @return New MsimMessage *, must be freed with msim_msg_free().
-- *
-- * For internal use - users probably want msim_msg_new() or msim_send().
-- */
--static MsimMessage *
--msim_msg_new_v(gchar *first_key, va_list argp)
--{
-- gchar *key, *value;
-- MsimMessageType type;
-- MsimMessage *msg;
-- gboolean first;
--
-- GString *gs;
-- GList *gl;
-- MsimMessage *dict;
--
-- /* Begin with an empty message. */
-- msg = NULL;
--
-- /* First parameter can be given explicitly. */
-- first = first_key != NULL;
--
-- /* Read key, type, value triplets until NULL. */
-- do {
-- if (first) {
-- key = first_key;
-- first = FALSE;
-- } else {
-- key = va_arg(argp, gchar *);
-- if (!key) {
-- break;
-- }
-- }
--
-- type = va_arg(argp, int);
--
-- /* Interpret variadic arguments. */
-- switch (type) {
-- case MSIM_TYPE_INTEGER:
-- case MSIM_TYPE_BOOLEAN:
-- msg = msim_msg_append(msg, key, type, GUINT_TO_POINTER(va_arg(argp, int)));
-- break;
--
-- case MSIM_TYPE_STRING:
-- value = va_arg(argp, char *);
--
-- g_return_val_if_fail(value != NULL, FALSE);
--
-- msg = msim_msg_append(msg, key, type, value);
-- break;
--
-- case MSIM_TYPE_BINARY:
-- gs = va_arg(argp, GString *);
--
-- g_return_val_if_fail(gs != NULL, FALSE);
--
-- /* msim_msg_free() will free this GString the caller created. */
-- msg = msim_msg_append(msg, key, type, gs);
-- break;
--
-- case MSIM_TYPE_LIST:
-- gl = va_arg(argp, GList *);
--
-- g_return_val_if_fail(gl != NULL, FALSE);
--
-- msg = msim_msg_append(msg, key, type, gl);
-- break;
--
-- case MSIM_TYPE_DICTIONARY:
-- dict = va_arg(argp, MsimMessage *);
--
-- g_return_val_if_fail(dict != NULL, FALSE);
--
-- msg = msim_msg_append(msg, key, type, dict);
-- break;
--
-- default:
-- purple_debug_info("msim", "msim_send: unknown type %d\n", type);
-- break;
-- }
-- } while(key);
--
-- return msg;
--}
--
--/**
-- * Create a new MsimMessage.
-- *
-- * @param first_key The first key in the sequence, or NULL for an empty message.
-- * @param ... A sequence of gchar* key/type/value triplets, terminated with NULL.
-- *
-- * See msim_msg_append() documentation for details on types.
-- */
--MsimMessage *
--msim_msg_new(gchar *first_key, ...)
--{
-- MsimMessage *ret = NULL;
-- va_list argp;
--
-- if (first_key) {
-- va_start(argp, first_key);
-- ret = msim_msg_new_v(first_key, argp);
-- va_end(argp);
-- }
--
-- return ret;
--}
--
--/**
-- * Pack a string using the given GFunc and seperator.
-- * Used by msim_msg_dump() and msim_msg_pack().
-- */
--static gchar *
--msim_msg_pack_using(MsimMessage *msg,
-- GFunc gf,
-- const gchar *sep,
-- const gchar *begin, const gchar *end)
--{
-- int num_items;
-- gchar **strings;
-- gchar **strings_tmp;
-- gchar *joined;
-- gchar *final;
-- int i;
--
-- g_return_val_if_fail(msg != NULL, NULL);
--
-- num_items = g_list_length(msg);
--
-- /* Add one for NULL terminator for g_strjoinv(). */
-- strings = (gchar **)g_new0(gchar *, num_items + 1);
--
-- strings_tmp = strings;
-- g_list_foreach(msg, gf, &strings_tmp);
--
-- joined = g_strjoinv(sep, strings);
-- final = g_strconcat(begin, joined, end, NULL);
-- g_free(joined);
--
-- /* Clean up. */
-- for (i = 0; i < num_items; ++i) {
-- g_free(strings[i]);
-- }
--
-- g_free(strings);
--
-- return final;
--}
--
--/**
-- * Return a human-readable string of the message.
-- *
-- * @return A new gchar *, must be g_free()'d.
-- */
--static gchar *
--msim_msg_dump_to_str(MsimMessage *msg)
--{
-- gchar *debug_str;
--
-- if (!msg) {
-- debug_str = g_strdup("<MsimMessage: empty>");
-- } else {
-- debug_str = msim_msg_pack_using(msg, msim_msg_debug_string_element,
-- "\n", "<MsimMessage: \n", "\n/MsimMessage>");
-- }
--
-- return debug_str;
--}
--
--/**
-- * Store a human-readable string describing the element.
-- *
-- * @param data Pointer to an MsimMessageElement.
-- * @param user_data
-- */
--static void
--msim_msg_debug_string_element(gpointer data, gpointer user_data)
--{
-- MsimMessageElement *elem;
-- gchar *string;
-- GString *gs;
-- gchar *binary;
-- gchar ***items; /* wow, a pointer to a pointer to a pointer */
--
-- gchar *s;
-- GList *gl;
-- guint i;
--
-- elem = (MsimMessageElement *)data;
-- items = user_data;
--
-- switch (elem->type) {
-- case MSIM_TYPE_INTEGER:
-- string = g_strdup_printf("%s(integer): %d", elem->name,
-- GPOINTER_TO_UINT(elem->data));
-- break;
--
-- case MSIM_TYPE_RAW:
-- string = g_strdup_printf("%s(raw): %s", elem->name,
-- elem->data ? (gchar *)elem->data : "(NULL)");
-- break;
--
-- case MSIM_TYPE_STRING:
-- string = g_strdup_printf("%s(string): %s", elem->name,
-- elem->data ? (gchar *)elem->data : "(NULL)");
-- break;
--
-- case MSIM_TYPE_BINARY:
-- gs = (GString *)elem->data;
-- binary = purple_base64_encode((guchar*)gs->str, gs->len);
-- string = g_strdup_printf("%s(binary, %d bytes): %s", elem->name, (int)gs->len, binary);
-- g_free(binary);
-- break;
--
-- case MSIM_TYPE_BOOLEAN:
-- string = g_strdup_printf("%s(boolean): %s", elem->name,
-- elem->data ? "TRUE" : "FALSE");
-- break;
--
-- case MSIM_TYPE_DICTIONARY:
-- if (!elem->data) {
-- s = g_strdup("(NULL)");
-- } else {
-- s = msim_msg_dump_to_str((MsimMessage *)elem->data);
-- }
--
-- if (!s) {
-- s = g_strdup("(NULL, couldn't msim_msg_dump_to_str)");
-- }
--
-- string = g_strdup_printf("%s(dict): %s", elem->name, s);
--
-- g_free(s);
-- break;
--
-- case MSIM_TYPE_LIST:
-- gs = g_string_new("");
-- g_string_append_printf(gs, "%s(list): \n", elem->name);
--
-- i = 0;
-- for (gl = (GList *)elem->data; gl != NULL; gl = g_list_next(gl)) {
-- g_string_append_printf(gs, " %d. %s\n", i, (gchar *)(gl->data));
-- ++i;
-- }
--
-- string = g_string_free(gs, FALSE);
-- break;
--
-- default:
-- string = g_strdup_printf("%s(unknown type %d",
-- elem->name ? elem->name : "(NULL)", elem->type);
-- break;
-- }
--
-- **items = string;
-- ++(*items);
--}
--
--/**
-- * Search for and return the node in msg, matching name, or NULL.
-- *
-- * @param msg Message to search within.
-- * @param name Field name to search for.
-- *
-- * @return The GList * node for the MsimMessageElement with the given name, or NULL if not found or name is NULL.
-- *
-- * For internal use - users probably want to use msim_msg_get() to
-- * access the MsimMessageElement *, instead of the GList * container.
-- *
-- */
--static GList *
--msim_msg_get_node(const MsimMessage *msg, const gchar *name)
--{
-- GList *node;
--
-- if (!name || !msg) {
-- return NULL;
-- }
--
-- /* Linear search for the given name. O(n) but n is small. */
-- for (node = (GList*)msg; node != NULL; node = g_list_next(node)) {
-- MsimMessageElement *elem;
--
-- elem = (MsimMessageElement *)node->data;
--
-- g_return_val_if_fail(elem != NULL, NULL);
-- g_return_val_if_fail(elem->name != NULL, NULL);
--
-- if (strcmp(elem->name, name) == 0) {
-- return node;
-- }
-- }
-- return NULL;
--}
--
--/**
-- * Create a new MsimMessageElement * - must be g_free()'d.
-- *
-- * For internal use; users probably want msim_msg_append() or msim_msg_insert_before().
-- *
-- * @param dynamic_name Whether 'name' should be freed when the message is destroyed.
-- */
--static MsimMessageElement *
--msim_msg_element_new(const gchar *name, MsimMessageType type, gpointer data, gboolean dynamic_name)
--{
-- MsimMessageElement *elem;
--
-- elem = g_new0(MsimMessageElement, 1);
--
-- elem->name = name;
-- elem->dynamic_name = dynamic_name;
-- elem->type = type;
-- elem->data = data;
--
-- return elem;
--}
--
--/**
-- * Append a new element to a message.
-- *
-- * @param name Textual name of element (static string, neither copied nor freed).
-- * @param type An MSIM_TYPE_* code.
-- * @param data Pointer to data, see below.
-- *
-- * @return The new message - must be assigned to as with GList*. For example:
-- *
-- * msg = msim_msg_append(msg, ...)
-- *
-- * The data parameter depends on the type given:
-- *
-- * * MSIM_TYPE_INTEGER: Use GUINT_TO_POINTER(x).
-- *
-- * * MSIM_TYPE_BINARY: Same as integer, non-zero is TRUE and zero is FALSE.
-- *
-- * * MSIM_TYPE_STRING: gchar *. The data WILL BE FREED - use g_strdup() if needed.
-- *
-- * * MSIM_TYPE_RAW: gchar *. The data WILL BE FREED - use g_strdup() if needed.
-- *
-- * * MSIM_TYPE_BINARY: g_string_new_len(data, length). The data AND GString will be freed.
-- *
-- * * MSIM_TYPE_DICTIONARY: An MsimMessage *. Freed when message is destroyed.
-- *
-- * * MSIM_TYPE_LIST: GList * of gchar *. Again, everything will be freed.
-- *
-- * */
--MsimMessage *
--msim_msg_append(MsimMessage *msg, const gchar *name,
-- MsimMessageType type, gpointer data)
--{
-- return g_list_append(msg, msim_msg_element_new(name, type, data, FALSE));
--}
--
--/**
-- * Append a new element, but with a dynamically-allocated name.
-- * Exactly the same as msim_msg_append(), except 'name' will be freed when
-- * the message is destroyed. Normally, it isn't, because a static string is given.
-- */
--static MsimMessage *
--msim_msg_append_dynamic_name(MsimMessage *msg, gchar *name,
-- MsimMessageType type, gpointer data)
--{
-- return g_list_append(msg, msim_msg_element_new(name, type, data, TRUE));
--}
--
--/**
-- * Insert a new element into a message, before the given element name.
-- *
-- * @param name_before Name of the element to insert the new element before. If
-- * could not be found or NULL, new element will be inserted at end.
-- *
-- * See msim_msg_append() for usage of other parameters, and an important note about return value.
-- */
--MsimMessage *
--msim_msg_insert_before(MsimMessage *msg, const gchar *name_before,
-- const gchar *name, MsimMessageType type, gpointer data)
--{
-- MsimMessageElement *new_elem;
-- GList *node_before;
--
-- new_elem = msim_msg_element_new(name, type, data, FALSE);
--
-- node_before = msim_msg_get_node(msg, name_before);
--
-- return g_list_insert_before(msg, node_before, new_elem);
--}
--
--/**
-- * Perform a deep copy on a GList * of gchar * strings. Free with msim_msg_list_free().
-- */
--static GList *
--msim_msg_list_copy(const GList *old)
--{
-- GList *new_list;
--
-- new_list = NULL;
--
-- /* Deep copy (g_list_copy is shallow). Copy each string. */
-- for (; old != NULL; old = g_list_next(old)) {
-- new_list = g_list_append(new_list, g_strdup(old->data));
-- }
--
-- return new_list;
--}
--
--/**
-- * Clone an individual element.
-- *
-- * @param data MsimMessageElement * to clone.
-- * @param user_data Pointer to MsimMessage * to add cloned element to.
-- */
--static void
--msim_msg_clone_element(gpointer data, gpointer user_data)
--{
-- MsimMessageElement *elem;
-- MsimMessage **new;
-- gpointer new_data;
--
-- GString *gs;
-- MsimMessage *dict;
--
-- elem = (MsimMessageElement *)data;
-- new = (MsimMessage **)user_data;
--
-- switch (elem->type) {
-- case MSIM_TYPE_BOOLEAN:
-- case MSIM_TYPE_INTEGER:
-- new_data = elem->data;
-- break;
--
-- case MSIM_TYPE_RAW:
-- case MSIM_TYPE_STRING:
-- new_data = g_strdup((gchar *)elem->data);
-- break;
--
-- case MSIM_TYPE_LIST:
-- new_data = (gpointer)msim_msg_list_copy((GList *)(elem->data));
-- break;
--
-- case MSIM_TYPE_BINARY:
-- gs = (GString *)elem->data;
--
-- new_data = g_string_new_len(gs->str, gs->len);
-- break;
-- case MSIM_TYPE_DICTIONARY:
-- dict = (MsimMessage *)elem->data;
--
-- new_data = msim_msg_clone(dict);
-- break;
--
-- default:
-- purple_debug_info("msim", "msim_msg_clone_element: unknown type %d\n", elem->type);
-- g_return_if_reached();
-- }
--
-- /* Append cloned data. Note that the 'name' field is a static string, so it
-- * never needs to be copied nor freed. */
-- if (elem->dynamic_name)
-- *new = msim_msg_append_dynamic_name(*new, g_strdup(elem->name), elem->type, new_data);
-- else
-- *new = msim_msg_append(*new, elem->name, elem->type, new_data);
--}
--
--/**
-- * Clone an existing MsimMessage.
-- *
-- * @return Cloned message; caller should free with msim_msg_free().
-- */
--MsimMessage *
--msim_msg_clone(MsimMessage *old)
--{
-- MsimMessage *new;
--
-- if (old == NULL) {
-- return NULL;
-- }
--
-- new = msim_msg_new(FALSE);
--
-- g_list_foreach(old, msim_msg_clone_element, &new);
--
-- return new;
--}
--
--/**
-- * Free the data of a message element.
-- *
-- * @param elem The MsimMessageElement *
-- *
-- * Note this only frees the element data; you may also want to free the
-- * element itself with g_free() (see msim_msg_free_element()).
-- */
--void
--msim_msg_free_element_data(MsimMessageElement *elem)
--{
-- switch (elem->type) {
-- case MSIM_TYPE_BOOLEAN:
-- case MSIM_TYPE_INTEGER:
-- /* Integer value stored in gpointer - no need to free(). */
-- break;
--
-- case MSIM_TYPE_RAW:
-- case MSIM_TYPE_STRING:
-- /* Always free strings - caller should have g_strdup()'d if
-- * string was static or temporary and not to be freed. */
-- g_free(elem->data);
-- break;
--
-- case MSIM_TYPE_BINARY:
-- /* Free the GString itself and the binary data. */
-- g_string_free((GString *)elem->data, TRUE);
-- break;
--
-- case MSIM_TYPE_DICTIONARY:
-- msim_msg_free((MsimMessage *)elem->data);
-- break;
--
-- case MSIM_TYPE_LIST:
-- g_list_free((GList *)elem->data);
-- break;
--
-- default:
-- purple_debug_info("msim", "msim_msg_free_element_data: "
-- "not freeing unknown type %d\n", elem->type);
-- break;
-- }
--}
--
--/**
-- * Free a GList * of MsimMessageElement *'s.
-- */
--void
--msim_msg_list_free(GList *l)
--{
--
-- for (; l != NULL; l = g_list_next(l)) {
-- MsimMessageElement *elem;
--
-- elem = (MsimMessageElement *)l->data;
--
-- /* Note that name is almost never dynamically allocated elsewhere;
-- * it is usually a static string, but not in lists. So cast it. */
-- g_free((gchar *)elem->name);
-- g_free(elem->data);
-- g_free(elem);
-- }
-- g_list_free(l);
--}
--
--/**
-- * Free an individual message element.
-- *
-- * @param data MsimMessageElement * to free.
-- * @param user_data Not used; required to match g_list_foreach() callback prototype.
-- *
-- * Frees both the element data and the element itself.
-- * Also frees the name if dynamic_name is TRUE.
-- */
--static void
--msim_msg_free_element(gpointer data, gpointer user_data)
--{
-- MsimMessageElement *elem;
--
-- elem = (MsimMessageElement *)data;
--
-- msim_msg_free_element_data(elem);
--
-- if (elem->dynamic_name)
-- /* Need to cast to remove const-ness, because
-- * elem->name is almost always a constant, static
-- * string, but not in this case. */
-- g_free((gchar *)elem->name);
--
-- g_free(elem);
--}
--
--/**
-- * Free a complete message.
-- */
--void
--msim_msg_free(MsimMessage *msg)
--{
-- if (!msg) {
-- /* already free as can be */
-- return;
-- }
--
-- g_list_foreach(msg, msim_msg_free_element, NULL);
-- g_list_free(msg);
--}
--
--/**
-- * Pack an element into its protocol representation.
-- *
-- * @param data Pointer to an MsimMessageElement.
-- * @param user_data Pointer to a gchar ** array of string items.
-- *
-- * Called by msim_msg_pack(). Will pack the MsimMessageElement into
-- * a part of the protocol string and append it to the array. Caller
-- * is responsible for creating array to correct dimensions, and
-- * freeing each string element of the array added by this function.
-- */
--static void
--msim_msg_pack_element(gpointer data, gpointer user_data)
--{
-- MsimMessageElement *elem;
-- gchar *string, *data_string;
-- gchar ***items;
--
-- elem = (MsimMessageElement *)data;
-- items = (gchar ***)user_data;
--
-- /* Exclude elements beginning with '_' from packed protocol messages. */
-- if (elem->name[0] == '_') {
-- return;
-- }
--
-- data_string = msim_msg_pack_element_data(elem);
--
-- switch (elem->type) {
-- /* These types are represented by key name/value pairs (converted above). */
-- case MSIM_TYPE_INTEGER:
-- case MSIM_TYPE_RAW:
-- case MSIM_TYPE_STRING:
-- case MSIM_TYPE_BINARY:
-- case MSIM_TYPE_DICTIONARY:
-- case MSIM_TYPE_LIST:
-- string = g_strconcat(elem->name, "\\", data_string, NULL);
-- break;
--
-- /* Boolean is represented by absence or presence of name. */
-- case MSIM_TYPE_BOOLEAN:
-- if (GPOINTER_TO_UINT(elem->data)) {
-- /* True - leave in, with blank value. */
-- string = g_strdup_printf("%s\\", elem->name);
-- } else {
-- /* False - leave out. */
-- string = g_strdup("");
-- }
-- break;
--
-- default:
-- g_free(data_string);
-- g_return_if_reached();
-- break;
-- }
--
-- g_free(data_string);
--
-- **items = string;
-- ++(*items);
--}
--
--/**
-- * Pack an element into its protcol representation inside a dictionary.
-- *
-- * See msim_msg_pack_element().
-- */
--static void
--msim_msg_pack_element_dict(gpointer data, gpointer user_data)
--{
-- MsimMessageElement *elem;
-- gchar *string, *data_string, ***items;
--
-- elem = (MsimMessageElement *)data;
-- items = (gchar ***)user_data;
--
-- /* Exclude elements beginning with '_' from packed protocol messages. */
-- if (elem->name[0] == '_') {
-- return;
-- }
--
-- data_string = msim_msg_pack_element_data(elem);
--
-- g_return_if_fail(data_string != NULL);
--
-- switch (elem->type) {
-- /* These types are represented by key name/value pairs (converted above). */
-- case MSIM_TYPE_INTEGER:
-- case MSIM_TYPE_RAW:
-- case MSIM_TYPE_STRING:
-- case MSIM_TYPE_BINARY:
-- case MSIM_TYPE_DICTIONARY:
-- case MSIM_TYPE_LIST:
-- case MSIM_TYPE_BOOLEAN: /* Boolean is On or Off */
-- string = g_strconcat(elem->name, "=", data_string, NULL);
-- break;
--
-- default:
-- g_free(data_string);
-- g_return_if_fail(FALSE);
-- break;
-- }
--
-- g_free(data_string);
--
-- **items = string;
-- ++(*items);
--}
--
--/**
-- * Return a packed string of a message suitable for sending over the wire.
-- *
-- * @return A string. Caller must g_free().
-- */
--gchar *
--msim_msg_pack(MsimMessage *msg)
--{
-- g_return_val_if_fail(msg != NULL, NULL);
--
-- return msim_msg_pack_using(msg, msim_msg_pack_element, "\\", "\\", "\\final\\");
--}
--
--/**
-- * Return a packed string of a dictionary, suitable for embedding in MSIM_TYPE_DICTIONARY.
-- *
-- * @return A string; caller must g_free().
-- */
--static gchar *
--msim_msg_pack_dict(MsimMessage *msg)
--{
-- g_return_val_if_fail(msg != NULL, NULL);
--
-- return msim_msg_pack_using(msg, msim_msg_pack_element_dict, "\034", "", "");
--}
--
--/**
-- * Send an existing MsimMessage.
-- */
--gboolean
--msim_msg_send(MsimSession *session, MsimMessage *msg)
--{
-- gchar *raw;
-- gboolean success;
--
-- raw = msim_msg_pack(msg);
-- g_return_val_if_fail(raw != NULL, FALSE);
-- success = msim_send_raw(session, raw);
-- g_free(raw);
--
-- return success;
--}
--
--/**
-- * Return a message element data as a new string for a raw protocol message,
-- * converting from other types (integer, etc.) if necessary.
-- *
-- * @return const gchar * The data as a string, or NULL. Caller must g_free().
-- *
-- * Returns a string suitable for inclusion in a raw protocol message, not necessarily
-- * optimal for human consumption. For example, strings are escaped. Use
-- * msim_msg_get_string() if you want a string, which in some cases is same as this.
-- */
--gchar *
--msim_msg_pack_element_data(MsimMessageElement *elem)
--{
-- GString *gs;
-- GList *gl;
--
-- g_return_val_if_fail(elem != NULL, NULL);
--
-- switch (elem->type) {
-- case MSIM_TYPE_INTEGER:
-- return g_strdup_printf("%d", GPOINTER_TO_UINT(elem->data));
--
-- case MSIM_TYPE_RAW:
-- /* Not un-escaped - this is a raw element, already escaped if necessary. */
-- return (gchar *)g_strdup((gchar *)elem->data);
--
-- case MSIM_TYPE_STRING:
-- /* Strings get escaped. msim_escape() creates a new string. */
-- g_return_val_if_fail(elem->data != NULL, NULL);
-- return elem->data ? msim_escape((gchar *)elem->data) :
-- g_strdup("(NULL)");
--
-- case MSIM_TYPE_BINARY:
-- gs = (GString *)elem->data;
-- /* Do not escape! */
-- return purple_base64_encode((guchar *)gs->str, gs->len);
--
-- case MSIM_TYPE_BOOLEAN:
-- /* Not used by messages in the wire protocol * -- see msim_msg_pack_element.
-- * Only used by dictionaries, see msim_msg_pack_element_dict. */
-- return elem->data ? g_strdup("On") : g_strdup("Off");
--
-- case MSIM_TYPE_DICTIONARY:
-- return msim_msg_pack_dict((MsimMessage *)elem->data);
--
-- case MSIM_TYPE_LIST:
-- /* Pack using a|b|c|d|... */
-- gs = g_string_new("");
--
-- for (gl = (GList *)elem->data; gl != NULL; gl = g_list_next(gl)) {
-- g_string_append_printf(gs, "%s", (gchar*)(gl->data));
--
-- /* All but last element is separated by a bar. */
-- if (g_list_next(gl))
-- g_string_append(gs, "|");
-- }
--
-- return g_string_free(gs, FALSE);
--
-- default:
-- purple_debug_info("msim", "field %s, unknown type %d\n",
-- elem->name ? elem->name : "(NULL)",
-- elem->type);
-- return NULL;
-- }
--}
--
--/**
-- * Send a message to the server, whose contents is specified using
-- * variable arguments.
-- *
-- * @param session
-- * @param ... A sequence of gchar* key/type/value triplets, terminated with NULL.
-- *
-- * This function exists for coding convenience: it allows a message to be created
-- * and sent in one line of code. Internally it calls msim_msg_send().
-- *
-- * IMPORTANT: See msim_msg_append() documentation for details on element types.
-- *
-- */
--gboolean
--msim_send(MsimSession *session, ...)
--{
-- gboolean success;
-- MsimMessage *msg;
-- va_list argp;
--
-- va_start(argp, session);
-- msg = msim_msg_new_v(NULL, argp);
-- va_end(argp);
--
-- /* Actually send the message. */
-- success = msim_msg_send(session, msg);
--
-- /* Cleanup. */
-- msim_msg_free(msg);
--
-- return success;
--}
--
--/**
-- * Print a human-readable string of the message to Purple's debug log.
-- *
-- * @param fmt_string A static string, in which '%s' will be replaced.
-- */
--void
--msim_msg_dump(const gchar *fmt_string, MsimMessage *msg)
--{
-- gchar *debug_str;
--
-- g_return_if_fail(fmt_string != NULL);
--
-- debug_str = msim_msg_dump_to_str(msg);
--
-- g_return_if_fail(debug_str != NULL);
--
-- purple_debug_info("msim", fmt_string, debug_str);
--
-- g_free(debug_str);
--}
--
--/**
-- * Parse a raw protocol message string into a MsimMessage *.
-- *
-- * @param raw The raw message string to parse, will be g_free()'d.
-- *
-- * @return MsimMessage *. Caller should msim_msg_free() when done.
-- */
--MsimMessage *
--msim_parse(const gchar *raw)
--{
-- MsimMessage *msg;
-- gchar *token;
-- gchar **tokens;
-- gchar *key;
-- gchar *value;
-- int i;
--
-- g_return_val_if_fail(raw != NULL, NULL);
--
-- purple_debug_info("msim", "msim_parse: got <%s>\n", raw);
--
-- key = NULL;
--
-- /* All messages begin with a \. */
-- if (raw[0] != '\\' || raw[1] == 0) {
-- purple_debug_info("msim", "msim_parse: incomplete/bad string, "
-- "missing initial backslash: <%s>\n", raw);
-- /* XXX: Should we try to recover, and read to first backslash? */
--
-- return NULL;
-- }
--
-- msg = msim_msg_new(FALSE);
--
-- for (tokens = g_strsplit(raw + 1, "\\", 0), i = 0;
-- (token = tokens[i]);
-- i++) {
--#ifdef MSIM_DEBUG_PARSE
-- purple_debug_info("msim", "tok=<%s>, i%2=%d\n", token, i % 2);
--#endif
-- if (i % 2) {
-- /* Odd-numbered ordinal is a value. */
--
-- value = token;
--
-- /* Incoming protocol messages get tagged as MSIM_TYPE_RAW, which
-- * represents an untyped piece of data. msim_msg_get_* will
-- * convert to appropriate types for caller, and handle unescaping if needed. */
-- msg = msim_msg_append_dynamic_name(msg, g_strdup(key), MSIM_TYPE_RAW, g_strdup(value));
--#ifdef MSIM_DEBUG_PARSE
-- purple_debug_info("msim", "insert string: |%s|=|%s|\n", key, value);
--#endif
-- } else {
-- /* Even numbered indexes are key names. */
-- key = token;
-- }
-- }
-- g_strfreev(tokens);
--
-- return msg;
--}
--
--/**
-- * Return the first MsimMessageElement * with given name in the MsimMessage *.
-- *
-- * @param name Name to search for.
-- *
-- * @return MsimMessageElement * matching name, or NULL.
-- *
-- * Note: useful fields of MsimMessageElement are 'data' and 'type', which
-- * you can access directly. But it is often more convenient to use
-- * another msim_msg_get_* that converts the data to what type you want.
-- */
--MsimMessageElement *
--msim_msg_get(const MsimMessage *msg, const gchar *name)
--{
-- GList *node;
--
-- node = msim_msg_get_node(msg, name);
-- if (node) {
-- return (MsimMessageElement *)node->data;
-- } else {
-- return NULL;
-- }
--}
--
--gchar *
--msim_msg_get_string_from_element(MsimMessageElement *elem)
--{
-- g_return_val_if_fail(elem != NULL, NULL);
-- switch (elem->type) {
-- case MSIM_TYPE_INTEGER:
-- return g_strdup_printf("%d", GPOINTER_TO_UINT(elem->data));
--
-- case MSIM_TYPE_RAW:
-- /* Raw element from incoming message - if its a string, it'll
-- * be escaped. */
-- return msim_unescape((gchar *)elem->data);
--
-- case MSIM_TYPE_STRING:
-- /* Already unescaped. */
-- return g_strdup((gchar *)elem->data);
--
-- default:
-- purple_debug_info("msim", "msim_msg_get_string_element: type %d unknown, name %s\n",
-- elem->type, elem->name ? elem->name : "(NULL)");
-- return NULL;
-- }
--}
--
--/**
-- * Return the data of an element of a given name, as a string.
-- *
-- * @param name Name of element.
-- *
-- * @return gchar * The data as a string, or NULL if not found.
-- * Caller must g_free().
-- *
-- * Note that msim_msg_pack_element_data() is similar, but returns a string
-- * for inclusion into a raw protocol string (escaped and everything).
-- * This function unescapes the string for you, if needed.
-- */
--gchar *
--msim_msg_get_string(const MsimMessage *msg, const gchar *name)
--{
-- MsimMessageElement *elem;
--
-- elem = msim_msg_get(msg, name);
-- if (!elem) {
-- return NULL;
-- }
--
-- return msim_msg_get_string_from_element(elem);
--}
--
--/**
-- * Parse a |-separated string into a new GList. Free with msim_msg_list_free().
-- */
--static GList *
--msim_msg_list_parse(const gchar *raw)
--{
-- gchar **array;
-- GList *list;
-- guint i;
--
-- array = g_strsplit(raw, "|", 0);
-- list = NULL;
--
-- /* TODO: escape/unescape /3 <-> | within list elements */
--
-- for (i = 0; array[i] != NULL; ++i) {
-- MsimMessageElement *elem;
--
-- /* Freed in msim_msg_list_free() */
-- elem = g_new0(MsimMessageElement, 1);
--
-- /* Give the element a name for debugging purposes.
-- * Not supposed to be looked up by this name; instead,
-- * lookup the elements by indexing the array. */
-- elem->name = g_strdup_printf("(list item #%d)", i);
-- elem->type = MSIM_TYPE_RAW;
-- elem->data = g_strdup(array[i]);
--
-- list = g_list_append(list, elem);
-- }
--
-- g_strfreev(array);
--
-- return list;
--}
--
--static GList *
--msim_msg_get_list_from_element(MsimMessageElement *elem)
--{
-- g_return_val_if_fail(elem != NULL, NULL);
-- switch (elem->type) {
-- case MSIM_TYPE_LIST:
-- return msim_msg_list_copy((GList *)elem->data);
--
-- case MSIM_TYPE_RAW:
-- return msim_msg_list_parse((gchar *)elem->data);
--
-- default:
-- purple_debug_info("msim_msg_get_list", "type %d unknown, name %s\n",
-- elem->type, elem->name ? elem->name : "(NULL)");
-- return NULL;
-- }
--}
--
--/**
-- * Return an element as a new list. Caller frees with msim_msg_list_free().
-- */
--GList *
--msim_msg_get_list(const MsimMessage *msg, const gchar *name)
--{
-- MsimMessageElement *elem;
--
-- elem = msim_msg_get(msg, name);
-- if (!elem) {
-- return NULL;
-- }
--
-- return msim_msg_get_list_from_element(elem);
--}
--
--/**
-- * Parse a \x1c-separated "dictionary" of key=value pairs into a hash table.
-- *
-- * @param raw The text of the dictionary to parse. Often the
-- * value for the 'body' field.
-- *
-- * @return A new MsimMessage *. Must msim_msg_free() when done.
-- */
--static MsimMessage *
--msim_msg_dictionary_parse(const gchar *raw)
--{
-- MsimMessage *dict;
-- gchar *item;
-- gchar **items;
-- gchar **elements;
-- guint i;
--
-- g_return_val_if_fail(raw != NULL, NULL);
--
-- dict = msim_msg_new(NULL);
--
-- for (items = g_strsplit(raw, "\x1c", 0), i = 0;
-- (item = items[i]);
-- i++) {
-- gchar *key, *value;
--
-- elements = g_strsplit(item, "=", 2);
--
-- key = elements[0];
-- if (!key) {
-- purple_debug_info("msim", "msim_msg_dictionary_parse(%s): null key\n",
-- raw);
-- g_strfreev(elements);
-- break;
-- }
--
-- value = elements[1];
-- if (!value) {
-- purple_debug_info("msim", "msim_msg_dictionary_prase(%s): null value\n",
-- raw);
-- g_strfreev(elements);
-- break;
-- }
--
--#ifdef MSIM_DEBUG_PARSE
-- purple_debug_info("msim_msg_dictionary_parse","-- %s: %s\n", key ? key : "(NULL)",
-- value ? value : "(NULL)");
--#endif
-- /* Append with _dynamic_name since g_strdup(key) is dynamic, and
-- * needs to be freed when the message is destroyed. It isn't static as usual. */
-- dict = msim_msg_append_dynamic_name(dict, g_strdup(key), MSIM_TYPE_RAW, g_strdup(value));
--
-- g_strfreev(elements);
-- }
--
-- g_strfreev(items);
--
-- return dict;
--}
--
--static MsimMessage *
--msim_msg_get_dictionary_from_element(MsimMessageElement *elem)
--{
-- g_return_val_if_fail(elem != NULL, NULL);
-- switch (elem->type) {
-- case MSIM_TYPE_DICTIONARY:
-- return msim_msg_clone((MsimMessage *)elem->data);
--
-- case MSIM_TYPE_RAW:
-- return msim_msg_dictionary_parse(elem->data);
--
-- default:
-- purple_debug_info("msim_msg_get_dictionary", "type %d unknown, name %s\n",
-- elem->type, elem->name ? elem->name : "(NULL)");
-- return NULL;
-- }
--}
--
--/**
-- * Return an element as a new dictionary. Caller frees with msim_msg_free().
-- */
--MsimMessage *
--msim_msg_get_dictionary(const MsimMessage *msg, const gchar *name)
--{
-- MsimMessageElement *elem;
--
-- elem = msim_msg_get(msg, name);
-- if (!elem) {
-- return NULL;
-- }
--
-- return msim_msg_get_dictionary_from_element(elem);
--}
--
--guint
--msim_msg_get_integer_from_element(MsimMessageElement *elem)
--{
-- g_return_val_if_fail(elem != NULL, 0);
-- switch (elem->type) {
-- case MSIM_TYPE_INTEGER:
-- return GPOINTER_TO_UINT(elem->data);
--
-- case MSIM_TYPE_RAW:
-- case MSIM_TYPE_STRING:
-- /* TODO: find out if we need larger integers */
-- return (guint)atoi((gchar *)elem->data);
--
-- default:
-- return 0;
-- }
--}
--
--/**
-- * Return the data of an element of a given name, as an unsigned integer.
-- *
-- * @param name Name of element.
-- *
-- * @return guint Numeric representation of data, or 0 if could not be converted / not found.
-- *
-- * Useful to obtain an element's data if you know it should be an integer,
-- * even if it is not stored as an MSIM_TYPE_INTEGER. MSIM_TYPE_STRING will
-- * be converted handled correctly, for example.
-- */
--guint
--msim_msg_get_integer(const MsimMessage *msg, const gchar *name)
--{
-- MsimMessageElement *elem;
--
-- elem = msim_msg_get(msg, name);
--
-- if (!elem) {
-- return 0;
-- }
--
-- return msim_msg_get_integer_from_element(elem);
--}
--
--static gboolean
--msim_msg_get_binary_from_element(MsimMessageElement *elem, gchar **binary_data, gsize *binary_length)
--{
-- GString *gs;
--
-- g_return_val_if_fail(elem != NULL, FALSE);
--
-- switch (elem->type) {
-- case MSIM_TYPE_RAW:
-- /* Incoming messages are tagged with MSIM_TYPE_RAW, and
-- * converted appropriately. They can still be "strings", just they won't
-- * be tagged as MSIM_TYPE_STRING (as MSIM_TYPE_STRING is intended to be used
-- * by msimprpl code for things like instant messages - stuff that should be
-- * escaped if needed). DWIM.
-- */
--
-- /* Previously, incoming messages were stored as MSIM_TYPE_STRING.
-- * This was fine for integers and strings, since they can easily be
-- * converted in msim_get_*, as desirable. However, it does not work
-- * well for binary strings. Consider:
-- *
-- * If incoming base64'd elements were tagged as MSIM_TYPE_STRING.
-- * msim_msg_get_binary() sees MSIM_TYPE_STRING, base64 decodes, returns.
-- * everything is fine.
-- * But then, msim_send() is called on the incoming message, which has
-- * a base64'd MSIM_TYPE_STRING that really is encoded binary. The values
-- * will be escaped since strings are escaped, and / becomes /2; no good.
-- *
-- */
-- *binary_data = (gchar *)purple_base64_decode((const gchar *)elem->data, binary_length);
-- return ((*binary_data) != NULL);
--
-- case MSIM_TYPE_BINARY:
-- gs = (GString *)elem->data;
--
-- /* Duplicate data, so caller can g_free() it. */
-- *binary_data = g_memdup(gs->str, gs->len);
-- *binary_length = gs->len;
--
-- return TRUE;
--
--
-- /* Rejected because if it isn't already a GString, have to g_new0 it and
-- * then caller has to ALSO free the GString!
-- *
-- * return (GString *)elem->data; */
--
-- default:
-- purple_debug_info("msim", "msim_msg_get_binary: unhandled type %d for key %s\n",
-- elem->type, elem->name ? elem->name : "(NULL)");
-- return FALSE;
-- }
--}
--
--/**
-- * Return the data of an element of a given name, as a binary GString.
-- *
-- * @param binary_data A pointer to a new pointer, which will be filled in with the binary data. CALLER MUST g_free().
-- *
-- * @param binary_length A pointer to an integer, which will be set to the binary data length.
-- *
-- * @return TRUE if successful, FALSE if not.
-- */
--gboolean
--msim_msg_get_binary(const MsimMessage *msg, const gchar *name,
-- gchar **binary_data, gsize *binary_length)
--{
-- MsimMessageElement *elem;
--
-- elem = msim_msg_get(msg, name);
-- if (!elem) {
-- return FALSE;
-- }
--
-- return msim_msg_get_binary_from_element(elem, binary_data, binary_length);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/message.h pidgin-2.10.7-nonprism/libpurple/protocols/myspace/message.h
---- pidgin-2.10.7/libpurple/protocols/myspace/message.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/message.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,109 +0,0 @@
--/** MySpaceIM protocol messages
-- *
-- * \author Jeff Connelly
-- *
-- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MYSPACE_MESSAGE_H
--#define _MYSPACE_MESSAGE_H
--
--#include <glib.h>
--
--#define MsimMessage GList /* #define instead of typedef to avoid casting */
--typedef gchar MsimMessageType;
--typedef struct _MsimMessageElement MsimMessageElement;
--
--#include "session.h"
--
--/* Types */
--struct _MsimMessageElement
--{
-- const gchar *name; /**< Textual name of element. */
-- gboolean dynamic_name; /**< TRUE if 'name' is a dynamic string to be freed, not static. */
-- guint type; /**< MSIM_TYPE_* code. */
-- gpointer data; /**< Pointer to data, or GUINT_TO_POINTER for int/bool. */
--};
--
--#define msim_msg_get_next_element_node(msg) ((MsimMessage *)(msg->next))
--
--/* Protocol field types */
--#define MSIM_TYPE_RAW '-'
--#define MSIM_TYPE_INTEGER 'i'
--#define MSIM_TYPE_STRING 's'
--#define MSIM_TYPE_BINARY 'b'
--#define MSIM_TYPE_BOOLEAN 'f'
--#define MSIM_TYPE_DICTIONARY 'd'
--#define MSIM_TYPE_LIST 'l'
--
--gchar *msim_escape(const gchar *msg);
--gchar *msim_unescape(const gchar *msg);
--
--MsimMessage *msim_msg_new(gchar *first_key, ...);
--/* No sentinel attribute, because can leave off varargs if not_empty is FALSE. */
--
--MsimMessage *msim_msg_clone(MsimMessage *old);
--void msim_msg_free_element_data(MsimMessageElement *elem);
--void msim_msg_free(MsimMessage *msg);
--MsimMessage *msim_msg_append(MsimMessage *msg, const gchar *name, MsimMessageType type, gpointer data);
--MsimMessage *msim_msg_insert_before(MsimMessage *msg, const gchar *name_before, const gchar *name, MsimMessageType type, gpointer data);
--gchar *msim_msg_pack_element_data(MsimMessageElement *elem);
--void msim_msg_dump(const char *fmt_string, MsimMessage *msg);
--gchar *msim_msg_pack(MsimMessage *msg);
--
--void msim_msg_list_free(GList *l);
--
--/* Based on http://permalink.gmane.org/gmane.comp.parsers.sparse/695
-- * Define macros for useful gcc attributes. */
--#ifdef __GNUC__
--#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
--#define FORMAT_ATTR(pos) __attribute__ ((__format__ (__printf__, pos, pos+1)))
--#define NORETURN_ATTR __attribute__ ((__noreturn__))
--/* __sentinel__ attribute was introduced in gcc 3.5 */
--#if (GCC_VERSION >= 3005)
-- #define SENTINEL_ATTR __attribute__ ((__sentinel__(0)))
--#else
-- #define SENTINEL_ATTR
--#endif /* gcc >= 3.5 */
--#else
-- #define FORMAT_ATTR(pos)
-- #define NORETURN_ATTR
-- #define SENTINEL_ATTR
--#endif
--
--/* Cause gcc to emit "a missing sentinel in function call" if forgot
-- * to write NULL as last, terminating parameter. */
--gboolean msim_send(struct _MsimSession *session, ...) SENTINEL_ATTR;
--
--gboolean msim_msg_send(struct _MsimSession *session, MsimMessage *msg);
--
--MsimMessage *msim_parse(const gchar *raw);
--
--MsimMessageElement *msim_msg_get(const MsimMessage *msg, const gchar *name);
--
--/* Retrieve data by name */
--gchar *msim_msg_get_string(const MsimMessage *msg, const gchar *name);
--GList *msim_msg_get_list(const MsimMessage *msg, const gchar *name);
--MsimMessage *msim_msg_get_dictionary(const MsimMessage *msg, const gchar *name);
--guint msim_msg_get_integer(const MsimMessage *msg, const gchar *name);
--gboolean msim_msg_get_binary(const MsimMessage *msg, const gchar *name, gchar **binary_data, gsize *binary_length);
--
--/* Retrieve data by element (MsimMessageElement *), returned from msim_msg_get() */
--gchar *msim_msg_get_string_from_element(MsimMessageElement *elem);
--guint msim_msg_get_integer_from_element(MsimMessageElement *elem);
--
--#endif /* _MYSPACE_MESSAGE_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/myspace.c pidgin-2.10.7-nonprism/libpurple/protocols/myspace/myspace.c
---- pidgin-2.10.7/libpurple/protocols/myspace/myspace.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/myspace.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,3667 +0,0 @@
--/**
-- * MySpaceIM Protocol Plugin
-- *
-- * \author Jeff Connelly
-- *
-- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
-- *
-- * Based on Purple's "C Plugin HOWTO" hello world example.
-- *
-- * Code also drawn from mockprpl:
-- * http://snarfed.org/space/purple+mock+protocol+plugin
-- * Copyright (C) 2004-2007, Ryan Barrett <mockprpl@ryanb.org>
-- *
-- * and some constructs also based on existing Purple plugins, which are:
-- * Copyright (C) 2003, Robbert Haarman <purple@inglorion.net>
-- * Copyright (C) 2003, Ethan Blanton <eblanton@cs.purdue.edu>
-- * Copyright (C) 2000-2003, Rob Flynn <rob@tgflinux.com>
-- * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#define PURPLE_PLUGIN
--
--#include "myspace.h"
--
--#include "privacy.h"
--
--static void msim_set_status(PurpleAccount *account, PurpleStatus *status);
--static void msim_set_idle(PurpleConnection *gc, int time);
--
--/**
-- * Perform actual postprocessing on a message, adding userid as specified.
-- *
-- * @param msg The message to postprocess.
-- * @param uid_before Name of field where to insert new field before, or NULL for end.
-- * @param uid_field_name Name of field to add uid to.
-- * @param uid The userid to insert.
-- *
-- * If the field named by uid_field_name already exists, then its string contents will
-- * be used for the field, except "<uid>" will be replaced by the userid.
-- *
-- * If the field named by uid_field_name does not exist, it will be added before the
-- * field named by uid_before, as an integer, with the userid.
-- *
-- * Does not handle sending, or scheduling userid lookup. For that, see msim_postprocess_outgoing().
-- */
--static MsimMessage *
--msim_do_postprocessing(MsimMessage *msg, const gchar *uid_before,
-- const gchar *uid_field_name, guint uid)
--{
-- MsimMessageElement *elem;
--
-- /* First, check - if the field already exists, replace <uid> within it */
-- if ((elem = msim_msg_get(msg, uid_field_name)) != NULL) {
-- gchar *fmt_string;
-- gchar *uid_str, *new_str;
--
-- /* Get the packed element, flattening it. This allows <uid> to be
-- * replaced within nested data structures, since the replacement is done
-- * on the linear, packed data, not on a complicated data structure.
-- *
-- * For example, if the field was originally a dictionary or a list, you
-- * would have to iterate over all the items in it to see what needs to
-- * be replaced. But by packing it first, the <uid> marker is easily replaced
-- * just by a string replacement.
-- */
-- fmt_string = msim_msg_pack_element_data(elem);
--
-- uid_str = g_strdup_printf("%d", uid);
-- new_str = purple_strreplace(fmt_string, "<uid>", uid_str);
-- g_free(uid_str);
-- g_free(fmt_string);
--
-- /* Free the old element data */
-- msim_msg_free_element_data(elem->data);
--
-- /* Replace it with our new data */
-- elem->data = new_str;
-- elem->type = MSIM_TYPE_RAW;
--
-- } else {
-- /* Otherwise, insert new field into outgoing message. */
-- msg = msim_msg_insert_before(msg, uid_before, uid_field_name, MSIM_TYPE_INTEGER, GUINT_TO_POINTER(uid));
-- }
--
-- return msg;
--}
--
--/**
-- * Callback for msim_postprocess_outgoing() to add a userid to a message, and send it (once receiving userid).
-- *
-- * @param session
-- * @param userinfo The user information reply message, containing the user ID
-- * @param data The message to postprocess and send.
-- *
-- * The data message should contain these fields:
-- *
-- * _uid_field_name: string, name of field to add with userid from userinfo message
-- * _uid_before: string, name of field before field to insert, or NULL for end
-- */
--static void
--msim_postprocess_outgoing_cb(MsimSession *session, const MsimMessage *userinfo,
-- gpointer data)
--{
-- gchar *uid_field_name, *uid_before, *username;
-- guint uid;
-- MsimMessage *msg, *body;
--
-- msg = (MsimMessage *)data;
--
-- /* Obtain userid from userinfo message. */
-- body = msim_msg_get_dictionary(userinfo, "body");
-- g_return_if_fail(body != NULL);
--
-- uid = msim_msg_get_integer(body, "UserID");
-- msim_msg_free(body);
--
-- username = msim_msg_get_string(msg, "_username");
--
-- if (!uid) {
-- gchar *msg;
--
-- msg = g_strdup_printf(_("No such user: %s"), username);
-- if (!purple_conv_present_error(username, session->account, msg)) {
-- purple_notify_error(NULL, NULL, _("User lookup"), msg);
-- }
--
-- g_free(msg);
-- g_free(username);
-- /* TODO: free
-- * msim_msg_free(msg);
-- */
-- return;
-- }
--
-- uid_field_name = msim_msg_get_string(msg, "_uid_field_name");
-- uid_before = msim_msg_get_string(msg, "_uid_before");
--
-- msg = msim_do_postprocessing(msg, uid_before, uid_field_name, uid);
--
-- /* Send */
-- if (!msim_msg_send(session, msg)) {
-- msim_msg_dump("msim_postprocess_outgoing_cb: sending failed for message: %s\n", msg);
-- }
--
--
-- /* Free field names AFTER sending message, because MsimMessage does NOT copy
-- * field names - instead, treats them as static strings (which they usually are).
-- */
-- g_free(uid_field_name);
-- g_free(uid_before);
-- g_free(username);
-- /* TODO: free
-- * msim_msg_free(msg);
-- */
--}
--
--/**
-- * Postprocess and send a message.
-- *
-- * @param session
-- * @param msg Message to postprocess. Will NOT be freed.
-- * @param username Username to resolve. Assumed to be a static string (will not be freed or copied).
-- * @param uid_field_name Name of new field to add, containing uid of username. Static string.
-- * @param uid_before Name of existing field to insert username field before. Static string.
-- *
-- * @return TRUE if successful.
-- */
--static gboolean
--msim_postprocess_outgoing(MsimSession *session, MsimMessage *msg,
-- const gchar *username, const gchar *uid_field_name,
-- const gchar *uid_before)
--{
-- PurpleBuddy *buddy;
-- guint uid;
-- gboolean rc;
--
-- g_return_val_if_fail(msg != NULL, FALSE);
--
-- /* Store information for msim_postprocess_outgoing_cb(). */
-- msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, g_strdup(username));
-- msg = msim_msg_append(msg, "_uid_field_name", MSIM_TYPE_STRING, g_strdup(uid_field_name));
-- msg = msim_msg_append(msg, "_uid_before", MSIM_TYPE_STRING, g_strdup(uid_before));
--
-- /* First, try the most obvious. If numeric userid is given, use that directly. */
-- if (msim_is_userid(username)) {
-- uid = atol(username);
-- } else {
-- /* Next, see if on buddy list and know uid. */
-- buddy = purple_find_buddy(session->account, username);
-- if (buddy) {
-- uid = purple_blist_node_get_int(PURPLE_BLIST_NODE(buddy), "UserID");
-- } else {
-- uid = 0;
-- }
--
-- if (!buddy || !uid) {
-- /* Don't have uid offhand - need to ask for it, and wait until hear back before sending. */
-- purple_debug_info("msim", ">>> msim_postprocess_outgoing: couldn't find username %s in blist\n",
-- username ? username : "(NULL)");
-- msim_lookup_user(session, username, msim_postprocess_outgoing_cb, msim_msg_clone(msg));
-- return TRUE; /* not sure of status yet - haven't sent! */
-- }
-- }
--
-- /* Already have uid, postprocess and send msg immediately. */
-- purple_debug_info("msim", "msim_postprocess_outgoing: found username %s has uid %d\n",
-- username ? username : "(NULL)", uid);
--
-- msg = msim_do_postprocessing(msg, uid_before, uid_field_name, uid);
--
-- rc = msim_msg_send(session, msg);
--
-- /* TODO: free
-- * msim_msg_free(msg);
-- */
--
-- return rc;
--}
--
--/**
-- * Send a buddy message of a given type.
-- *
-- * @param session
-- * @param who Username to send message to.
-- * @param text Message text to send. Not freed; will be copied.
-- * @param type A MSIM_BM_* constant.
-- *
-- * @return TRUE if success, FALSE if fail.
-- *
-- * Buddy messages ('bm') include instant messages, action messages, status messages, etc.
-- */
--gboolean
--msim_send_bm(MsimSession *session, const gchar *who, const gchar *text,
-- int type)
--{
-- gboolean rc;
-- MsimMessage *msg;
-- const gchar *from_username;
--
-- g_return_val_if_fail(who != NULL, FALSE);
-- g_return_val_if_fail(text != NULL, FALSE);
--
-- from_username = session->account->username;
--
-- g_return_val_if_fail(from_username != NULL, FALSE);
--
-- purple_debug_info("msim", "sending %d message from %s to %s: %s\n",
-- type, from_username, who, text);
--
-- msg = msim_msg_new(
-- "bm", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(type),
-- "sesskey", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(session->sesskey),
-- /* 't' will be inserted here */
-- "cv", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(MSIM_CLIENT_VERSION),
-- "msg", MSIM_TYPE_STRING, g_strdup(text),
-- NULL);
--
-- rc = msim_postprocess_outgoing(session, msg, who, "t", "cv");
--
-- msim_msg_free(msg);
--
-- return rc;
--}
--
--/**
-- * Lookup a username by userid, from buddy list.
-- *
-- * @param wanted_uid
-- *
-- * @return Username of wanted_uid, if on blist, or NULL.
-- * This is a static string, so don't free it. Copy it if needed.
-- *
-- */
--static const gchar *
--msim_uid2username_from_blist(PurpleAccount *account, guint wanted_uid)
--{
-- GSList *buddies, *cur;
-- const gchar *ret;
--
-- buddies = purple_find_buddies(account, NULL);
--
-- if (!buddies)
-- {
-- purple_debug_info("msim", "msim_uid2username_from_blist: no buddies?\n");
-- return NULL;
-- }
--
-- ret = NULL;
--
-- for (cur = buddies; cur != NULL; cur = g_slist_next(cur))
-- {
-- PurpleBuddy *buddy;
-- guint uid;
-- const gchar *name;
--
-- /* See finch/gnthistory.c */
-- buddy = cur->data;
--
-- uid = purple_blist_node_get_int(PURPLE_BLIST_NODE(buddy), "UserID");
-- name = purple_buddy_get_name(buddy);
--
-- if (uid == wanted_uid)
-- {
-- ret = name;
-- break;
-- }
-- }
--
-- g_slist_free(buddies);
-- return ret;
--}
--
--/**
-- * Setup a callback, to be called when a reply is received with the returned rid.
-- *
-- * @param cb The callback, an MSIM_USER_LOOKUP_CB.
-- * @param data Arbitrary user data to be passed to callback (probably an MsimMessage *).
-- *
-- * @return The request/reply ID, used to link replies with requests, or -1.
-- * Put the rid in your request, 'rid' field.
-- *
-- * TODO: Make more generic and more specific:
-- * 1) MSIM_USER_LOOKUP_CB - make it for PERSIST_REPLY, not just user lookup
-- * 2) data - make it an MsimMessage?
-- */
--guint
--msim_new_reply_callback(MsimSession *session, MSIM_USER_LOOKUP_CB cb,
-- gpointer data)
--{
-- guint rid;
--
-- rid = session->next_rid++;
--
-- g_hash_table_insert(session->user_lookup_cb, GUINT_TO_POINTER(rid), cb);
-- g_hash_table_insert(session->user_lookup_cb_data, GUINT_TO_POINTER(rid), data);
--
-- return rid;
--}
--
--/**
-- * Return the icon name for a buddy and account.
-- *
-- * @param acct The account to find the icon for, or NULL for protocol icon.
-- * @param buddy The buddy to find the icon for, or NULL for the account icon.
-- *
-- * @return The base icon name string.
-- */
--static const gchar *
--msim_list_icon(PurpleAccount *acct, PurpleBuddy *buddy)
--{
-- /* Use a MySpace icon submitted by hbons at
-- * http://developer.pidgin.im/wiki/MySpaceIM. */
-- return "myspace";
--}
--
--/**
-- * Obtain the status text for a buddy.
-- *
-- * @param buddy The buddy to obtain status text for.
-- *
-- * @return Status text, or NULL if error. Caller g_free()'s.
-- */
--static char *
--msim_status_text(PurpleBuddy *buddy)
--{
-- MsimUser *user;
-- const gchar *display_name = NULL, *headline = NULL;
-- PurpleAccount *account;
--
-- g_return_val_if_fail(buddy != NULL, NULL);
--
-- account = purple_buddy_get_account(buddy);
--
-- user = msim_get_user_from_buddy(buddy, FALSE);
-- if (user != NULL) {
-- /* Retrieve display name and/or headline, depending on user preference. */
-- if (purple_account_get_bool(account, "show_headline", TRUE)) {
-- headline = user->headline;
-- }
--
-- if (purple_account_get_bool(account, "show_display_name", FALSE)) {
-- display_name = user->display_name;
-- }
-- }
--
-- /* Return appropriate combination of display name and/or headline, or neither. */
--
-- if (display_name && headline) {
-- return g_strconcat(display_name, " ", headline, NULL);
-- } else if (display_name) {
-- return g_strdup(display_name);
-- } else if (headline) {
-- return g_strdup(headline);
-- }
--
-- return NULL;
--}
--
--/**
-- * Obtain the tooltip text for a buddy.
-- *
-- * @param buddy Buddy to obtain tooltip text on.
-- * @param user_info Variable modified to have the tooltip text.
-- * @param full TRUE if should obtain full tooltip text.
-- */
--static void
--msim_tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info,
-- gboolean full)
--{
-- MsimUser *user;
--
-- g_return_if_fail(buddy != NULL);
-- g_return_if_fail(user_info != NULL);
--
-- user = msim_get_user_from_buddy(buddy, TRUE);
--
-- if (PURPLE_BUDDY_IS_ONLINE(buddy)) {
-- MsimSession *session;
-- PurpleAccount *account = purple_buddy_get_account(buddy);
-- PurpleConnection *gc = purple_account_get_connection(account);
--
-- session = (MsimSession *)gc->proto_data;
--
-- /* TODO: if (full), do something different? */
--
-- /* TODO: request information? have to figure out how to do
-- * the asynchronous lookup like oscar does (tooltip shows
-- * 'retrieving...' if not yet available, then changes when it is).
-- *
-- * Right now, only show what we have on hand.
-- */
--
-- /* Show abbreviated user info. */
-- msim_append_user_info(session, user_info, user, FALSE);
-- }
--}
--
--/**
-- * Get possible user status types. Based on mockprpl.
-- *
-- * @return GList of status types.
-- */
--static GList *
--msim_status_types(PurpleAccount *acct)
--{
-- GList *types;
-- PurpleStatusType *status;
--
-- purple_debug_info("myspace", "returning status types\n");
--
-- types = NULL;
--
-- /* Statuses are almost all the same. Define a macro to reduce code repetition. */
--#define _MSIM_ADD_NEW_STATUS(prim) status = \
-- purple_status_type_new_with_attrs( \
-- prim, /* PurpleStatusPrimitive */ \
-- NULL, /* id - use default */ \
-- NULL, /* name - use default */ \
-- TRUE, /* saveable */ \
-- TRUE, /* user_settable */ \
-- FALSE, /* not independent */ \
-- \
-- /* Attributes - each status can have a message. */ \
-- "message", \
-- _("Message"), \
-- purple_value_new(PURPLE_TYPE_STRING), \
-- NULL); \
-- \
-- \
-- types = g_list_append(types, status)
--
--
-- _MSIM_ADD_NEW_STATUS(PURPLE_STATUS_AVAILABLE);
-- _MSIM_ADD_NEW_STATUS(PURPLE_STATUS_AWAY);
-- _MSIM_ADD_NEW_STATUS(PURPLE_STATUS_OFFLINE);
-- _MSIM_ADD_NEW_STATUS(PURPLE_STATUS_INVISIBLE);
--
-- /* Except tune status is different... */
-- status = purple_status_type_new_with_attrs(
-- PURPLE_STATUS_TUNE, /* primitive */
-- "tune", /* ID */
-- NULL, /* name - use default */
-- FALSE, /* saveable */
-- TRUE, /* should be user_settable some day */
-- TRUE, /* independent */
--
-- PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
-- PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
--
-- types = g_list_append(types, status);
--
-- return types;
--}
--
--/*
-- * TODO: This define is stolen from oscar.h.
-- * It's also in yahoo.h.
-- * It should be in libpurple/util.c
-- */
--#define msim_put32(buf, data) ( \
-- (*((buf)) = (unsigned char)((data)>>24)&0xff), \
-- (*((buf)+1) = (unsigned char)((data)>>16)&0xff), \
-- (*((buf)+2) = (unsigned char)((data)>>8)&0xff), \
-- (*((buf)+3) = (unsigned char)(data)&0xff), \
-- 4)
--
--/**
-- * Compute the base64'd login challenge response based on username, password, nonce, and IPs.
-- *
-- * @param nonce The base64 encoded nonce ('nc') field from the server.
-- * @param email User's email address (used as login name).
-- * @param password User's cleartext password.
-- * @param response_len Will be written with response length.
-- *
-- * @return Binary login challenge response, ready to send to the server.
-- * Must be g_free()'d when finished. NULL if error.
-- */
--static gchar *
--msim_compute_login_response(const gchar nonce[2 * NONCE_SIZE],
-- const gchar *email, const gchar *password, guint *response_len)
--{
-- PurpleCipherContext *key_context;
-- PurpleCipher *sha1;
-- PurpleCipherContext *rc4;
--
-- guchar hash_pw[HASH_SIZE];
-- guchar key[HASH_SIZE];
-- gchar *password_truncated, *password_utf16le, *password_utf8_lc;
-- GString *data;
-- guchar *data_out;
-- size_t data_out_len;
-- gsize conv_bytes_read, conv_bytes_written;
-- GError *conv_error;
--#ifdef MSIM_DEBUG_LOGIN_CHALLENGE
-- int i;
--#endif
--
-- g_return_val_if_fail(nonce != NULL, NULL);
-- g_return_val_if_fail(email != NULL, NULL);
-- g_return_val_if_fail(password != NULL, NULL);
-- g_return_val_if_fail(response_len != NULL, NULL);
--
-- /*
-- * Truncate password to 10 characters. Their "change password"
-- * web page doesn't let you enter more than 10 characters, but you
-- * can enter more than 10 when logging in on myspace.com and they
-- * truncate it.
-- */
-- password_truncated = g_strndup(password, 10);
--
-- /* Convert password to lowercase (required for passwords containing
-- * uppercase characters). MySpace passwords are lowercase,
-- * see ticket #2066. */
-- password_utf8_lc = g_utf8_strdown(password_truncated, -1);
-- g_free(password_truncated);
--
-- /* Convert ASCII password to UTF16 little endian */
-- purple_debug_info("msim", "converting password to UTF-16LE\n");
-- conv_error = NULL;
-- password_utf16le = g_convert(password_utf8_lc, -1, "UTF-16LE", "UTF-8",
-- &conv_bytes_read, &conv_bytes_written, &conv_error);
-- g_free(password_utf8_lc);
--
-- if (conv_error != NULL) {
-- purple_debug_error("msim",
-- "g_convert password UTF8->UTF16LE failed: %s",
-- conv_error->message);
-- g_error_free(conv_error);
-- return NULL;
-- }
--
-- /* Compute password hash */
-- purple_cipher_digest_region("sha1", (guchar *)password_utf16le,
-- conv_bytes_written, sizeof(hash_pw), hash_pw, NULL);
-- g_free(password_utf16le);
--
--#ifdef MSIM_DEBUG_LOGIN_CHALLENGE
-- purple_debug_info("msim", "pwhash = ");
-- for (i = 0; i < sizeof(hash_pw); i++)
-- purple_debug_info("msim", "%.2x ", hash_pw[i]);
-- purple_debug_info("msim", "\n");
--#endif
--
-- /* key = sha1(sha1(pw) + nonce2) */
-- sha1 = purple_ciphers_find_cipher("sha1");
-- key_context = purple_cipher_context_new(sha1, NULL);
-- purple_cipher_context_append(key_context, hash_pw, HASH_SIZE);
-- purple_cipher_context_append(key_context, (guchar *)(nonce + NONCE_SIZE), NONCE_SIZE);
-- purple_cipher_context_digest(key_context, sizeof(key), key, NULL);
-- purple_cipher_context_destroy(key_context);
--
--#ifdef MSIM_DEBUG_LOGIN_CHALLENGE
-- purple_debug_info("msim", "key = ");
-- for (i = 0; i < sizeof(key); i++) {
-- purple_debug_info("msim", "%.2x ", key[i]);
-- }
-- purple_debug_info("msim", "\n");
--#endif
--
-- rc4 = purple_cipher_context_new_by_name("rc4", NULL);
--
-- /* Note: 'key' variable is 0x14 bytes (from SHA-1 hash),
-- * but only first 0x10 used for the RC4 key. */
-- purple_cipher_context_set_option(rc4, "key_len", (gpointer)0x10);
-- purple_cipher_context_set_key(rc4, key);
--
-- /* rc4 encrypt:
-- * nonce1+email+IP list */
--
-- data = g_string_new(NULL);
-- g_string_append_len(data, nonce, NONCE_SIZE);
--
-- /* Include the null terminator */
-- g_string_append_len(data, email, strlen(email) + 1);
--
-- while (data->len % 4 != 0)
-- g_string_append_c(data, 0xfb);
--
--#ifdef SEND_OUR_IP_ADDRESSES
-- /* TODO: Obtain IPs of network interfaces instead of using this hardcoded value */
-- g_string_set_size(data, data->len + 4);
-- msim_put32(data->str + data->len - 4, MSIM_LOGIN_IP_LIST_LEN);
-- g_string_append_len(data, MSIM_LOGIN_IP_LIST, MSIM_LOGIN_IP_LIST_LEN);
--#else
-- g_string_set_size(data, data->len + 4);
-- msim_put32(data->str + data->len - 4, 0);
--#endif /* !SEND_OUR_IP_ADDRESSES */
--
-- data_out = g_new0(guchar, data->len);
--
-- purple_cipher_context_encrypt(rc4, (const guchar *)data->str,
-- data->len, data_out, &data_out_len);
-- purple_cipher_context_destroy(rc4);
--
-- if (data_out_len != data->len) {
-- purple_debug_info("msim", "msim_compute_login_response: "
-- "data length mismatch: %" G_GSIZE_FORMAT " != %"
-- G_GSIZE_FORMAT "\n", data_out_len, data->len);
-- }
--
-- g_string_free(data, TRUE);
--
--#ifdef MSIM_DEBUG_LOGIN_CHALLENGE
-- purple_debug_info("msim", "response=<%s>\n", data_out);
--#endif
--
-- *response_len = data_out_len;
--
-- return (gchar *)data_out;
--}
--
--/**
-- * Process a login challenge, sending a response.
-- *
-- * @param session
-- * @param msg Login challenge message.
-- *
-- * @return TRUE if successful, FALSE if not
-- */
--static gboolean
--msim_login_challenge(MsimSession *session, MsimMessage *msg)
--{
-- PurpleAccount *account;
-- gchar *response;
-- guint response_len;
-- gchar *nc;
-- gsize nc_len;
-- gboolean ret;
--
-- g_return_val_if_fail(msg != NULL, FALSE);
--
-- g_return_val_if_fail(msim_msg_get_binary(msg, "nc", &nc, &nc_len), FALSE);
--
-- account = session->account;
--
-- g_return_val_if_fail(account != NULL, FALSE);
--
-- purple_connection_update_progress(session->gc, _("Reading challenge"), 1, 4);
--
-- purple_debug_info("msim", "nc is %" G_GSIZE_FORMAT
-- " bytes, decoded\n", nc_len);
--
-- if (nc_len != MSIM_AUTH_CHALLENGE_LENGTH) {
-- purple_debug_info("msim", "bad nc length: %" G_GSIZE_MODIFIER
-- "x != 0x%x\n", nc_len, MSIM_AUTH_CHALLENGE_LENGTH);
-- purple_connection_error_reason (session->gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Unexpected challenge length from server"));
-- return FALSE;
-- }
--
-- purple_connection_update_progress(session->gc, _("Logging in"), 2, 4);
--
-- response_len = 0;
-- response = msim_compute_login_response(nc, account->username, account->password, &response_len);
--
-- g_free(nc);
--
-- ret = msim_send(session,
-- "login2", MSIM_TYPE_INTEGER, MSIM_AUTH_ALGORITHM,
-- /* This is actually user's email address. */
-- "username", MSIM_TYPE_STRING, g_strdup(account->username),
-- /* GString will be freed in msim_msg_free() in msim_send(). */
-- "response", MSIM_TYPE_BINARY, g_string_new_len(response, response_len),
-- "clientver", MSIM_TYPE_INTEGER, MSIM_CLIENT_VERSION,
-- "langid", MSIM_TYPE_INTEGER, MSIM_LANGUAGE_ID_ENGLISH,
-- "imlang", MSIM_TYPE_STRING, g_strdup(MSIM_LANGUAGE_NAME_ENGLISH),
-- "reconn", MSIM_TYPE_INTEGER, 0,
-- "status", MSIM_TYPE_INTEGER, 100,
-- "id", MSIM_TYPE_INTEGER, 1,
-- NULL);
--
-- g_free(response);
--
-- return ret;
--}
--
--/**
-- * Process unrecognized information.
-- *
-- * @param session
-- * @param msg An MsimMessage that was unrecognized, or NULL.
-- * @param note Information on what was unrecognized, or NULL.
-- */
--void
--msim_unrecognized(MsimSession *session, MsimMessage *msg, gchar *note)
--{
-- /* TODO: Some more context, outwardly equivalent to a backtrace,
-- * for helping figure out what this msg is for. What was going on?
-- * But not too much information so that a user
-- * posting this dump reveals confidential information.
-- */
--
-- /* TODO: dump unknown msgs to file, so user can send them to me
-- * if they wish, to help add support for new messages (inspired
-- * by Alexandr Shutko, who maintains OSCAR protocol documentation).
-- *
-- * Filed enhancement ticket for libpurple as #4688.
-- */
--
-- purple_debug_info("msim", "Unrecognized data on account for %s\n",
-- (session && session->account && session->account->username) ?
-- session->account->username : "(NULL)");
-- if (note) {
-- purple_debug_info("msim", "(Note: %s)\n", note);
-- }
--
-- if (msg) {
-- msim_msg_dump("Unrecognized message dump: %s\n", msg);
-- }
--}
--
--/** Called when the session key arrives to check whether the user
-- * has a username, and set one if desired. */
--static gboolean
--msim_is_username_set(MsimSession *session, MsimMessage *msg)
--{
-- g_return_val_if_fail(msg != NULL, FALSE);
-- g_return_val_if_fail(session->gc != NULL, FALSE);
--
-- session->sesskey = msim_msg_get_integer(msg, "sesskey");
-- purple_debug_info("msim", "SESSKEY=<%d>\n", session->sesskey);
--
-- /* What is proof? Used to be uid, but now is 52 base64'd bytes... */
--
-- /* Comes with: proof,profileid,userid,uniquenick -- all same values
-- * some of the time, but can vary. This is our own user ID. */
-- session->userid = msim_msg_get_integer(msg, "userid");
--
-- /* Save uid to account so this account can be looked up by uid. */
-- purple_account_set_int(session->account, "uid", session->userid);
--
-- /* Not sure what profileid is used for. */
-- if (msim_msg_get_integer(msg, "profileid") != session->userid) {
-- msim_unrecognized(session, msg,
-- "Profile ID didn't match user ID, don't know why");
-- }
--
-- /* We now know are our own username, only after we're logged in..
-- * which is weird, but happens because you login with your email
-- * address and not username. Will be freed in msim_session_destroy(). */
-- session->username = msim_msg_get_string(msg, "uniquenick");
--
-- /* If user lacks a username, help them get one. */
-- if (msim_msg_get_integer(msg, "uniquenick") == session->userid) {
-- purple_debug_info("msim_is_username_set", "no username is set\n");
-- purple_request_yes_no(session->gc,
-- _("MySpaceIM - No Username Set"),
-- _("You appear to have no MySpace username."),
-- _("Would you like to set one now? (Note: THIS CANNOT BE CHANGED!)"),
-- 0,
-- session->account,
-- NULL,
-- NULL,
-- session->gc,
-- G_CALLBACK(msim_set_username_cb),
-- G_CALLBACK(msim_do_not_set_username_cb));
-- purple_debug_info("msim_is_username_set","'username not set' alert prompted\n");
-- return FALSE;
-- }
-- return TRUE;
--}
--
--#ifdef MSIM_USE_KEEPALIVE
--/**
-- * Check if the connection is still alive, based on last communication.
-- */
--static gboolean
--msim_check_alive(gpointer data)
--{
-- MsimSession *session;
-- time_t delta;
--
-- session = (MsimSession *)data;
--
-- delta = time(NULL) - session->last_comm;
--
-- /* purple_debug_info("msim", "msim_check_alive: delta=%d\n", delta); */
-- if (delta >= MSIM_KEEPALIVE_INTERVAL) {
-- purple_debug_info("msim",
-- "msim_check_alive: %zu > interval of %d, presumed dead\n",
-- delta, MSIM_KEEPALIVE_INTERVAL);
-- purple_connection_error_reason(session->gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Lost connection with server"));
--
-- return FALSE;
-- }
--
-- return TRUE;
--}
--#endif
--
--/**
-- * Handle mail reply checks.
-- */
--static void
--msim_check_inbox_cb(MsimSession *session, const MsimMessage *reply, gpointer data)
--{
-- MsimMessage *body;
-- guint i, n;
-- /* Information for each new inbox message type. */
-- static struct
-- {
-- const gchar *key;
-- guint bit;
-- const gchar *url;
-- const gchar *text;
-- } message_types[] = {
-- { "Mail", MSIM_INBOX_MAIL, "http://messaging.myspace.com/index.cfm?fuseaction=mail.inbox", NULL },
-- { "BlogComment", MSIM_INBOX_BLOG_COMMENT, "http://blog.myspace.com/index.cfm?fuseaction=blog", NULL },
-- { "ProfileComment", MSIM_INBOX_PROFILE_COMMENT, "http://home.myspace.com/index.cfm?fuseaction=user", NULL },
-- { "FriendRequest", MSIM_INBOX_FRIEND_REQUEST, "http://messaging.myspace.com/index.cfm?fuseaction=mail.friendRequests", NULL },
-- { "PictureComment", MSIM_INBOX_PICTURE_COMMENT, "http://home.myspace.com/index.cfm?fuseaction=user", NULL }
-- };
-- const gchar *froms[G_N_ELEMENTS(message_types) + 1] = { "" },
-- *tos[G_N_ELEMENTS(message_types) + 1] = { "" },
-- *urls[G_N_ELEMENTS(message_types) + 1] = { "" },
-- *subjects[G_N_ELEMENTS(message_types) + 1] = { "" };
--
-- g_return_if_fail(reply != NULL);
--
-- /* Can't write _()'d strings in array initializers. Workaround. */
-- /* khc: then use N_() in the array initializer and use _() when they are
-- used */
-- message_types[0].text = _("New mail messages");
-- message_types[1].text = _("New blog comments");
-- message_types[2].text = _("New profile comments");
-- message_types[3].text = _("New friend requests!");
-- message_types[4].text = _("New picture comments");
--
-- body = msim_msg_get_dictionary(reply, "body");
--
-- if (body == NULL)
-- return;
--
-- n = 0;
--
-- for (i = 0; i < G_N_ELEMENTS(message_types); ++i) {
-- const gchar *key;
-- guint bit;
--
-- key = message_types[i].key;
-- bit = message_types[i].bit;
--
-- if (msim_msg_get(body, key)) {
-- /* Notify only on when _changes_ from no mail -> has mail
-- * (edge triggered) */
-- if (!(session->inbox_status & bit)) {
-- purple_debug_info("msim", "msim_check_inbox_cb: got %s, at %d\n",
-- key ? key : "(NULL)", n);
--
-- subjects[n] = message_types[i].text;
-- froms[n] = _("MySpace");
-- tos[n] = session->username;
-- /* TODO: append token, web challenge, so automatically logs in.
-- * Would also need to free strings because they won't be static
-- */
-- urls[n] = message_types[i].url;
--
-- ++n;
-- } else {
-- purple_debug_info("msim",
-- "msim_check_inbox_cb: already notified of %s\n",
-- key ? key : "(NULL)");
-- }
--
-- session->inbox_status |= bit;
-- }
-- }
--
-- if (n) {
-- purple_debug_info("msim",
-- "msim_check_inbox_cb: notifying of %d\n", n);
--
-- /* TODO: free strings with callback _if_ change to dynamic (w/ token) */
-- purple_notify_emails(session->gc, /* handle */
-- n, /* count */
-- TRUE, /* detailed */
-- subjects, froms, tos, urls,
-- NULL, /* PurpleNotifyCloseCallback cb */
-- NULL); /* gpointer user_data */
--
-- }
--
-- msim_msg_free(body);
--}
--
--/**
-- * Send request to check if there is new mail.
-- */
--static gboolean
--msim_check_inbox(gpointer data)
--{
-- MsimSession *session;
--
-- session = (MsimSession *)data;
--
-- purple_debug_info("msim", "msim_check_inbox: checking mail\n");
-- g_return_val_if_fail(msim_send(session,
-- "persist", MSIM_TYPE_INTEGER, 1,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
-- "dsn", MSIM_TYPE_INTEGER, MG_CHECK_MAIL_DSN,
-- "lid", MSIM_TYPE_INTEGER, MG_CHECK_MAIL_LID,
-- "uid", MSIM_TYPE_INTEGER, session->userid,
-- "rid", MSIM_TYPE_INTEGER,
-- msim_new_reply_callback(session, msim_check_inbox_cb, NULL),
-- "body", MSIM_TYPE_STRING, g_strdup(""),
-- NULL), TRUE);
--
-- /* Always return true, so that we keep checking for mail. */
-- return TRUE;
--}
--
--/**
-- * Add contact from server to buddy list, after looking up username.
-- * Callback from msim_add_contact_from_server().
-- *
-- * @param data An MsimMessage * of the contact information. Will be freed.
-- */
--static void
--msim_add_contact_from_server_cb(MsimSession *session, const MsimMessage *user_lookup_info, gpointer data)
--{
-- MsimMessage *contact_info, *user_lookup_info_body;
-- PurpleGroup *group;
-- PurpleBuddy *buddy;
-- MsimUser *user;
-- gchar *username, *group_name, *display_name;
-- guint uid, visibility;
--
-- contact_info = (MsimMessage *)data;
-- purple_debug_info("msim_add_contact_from_server_cb", "contact_info addr=%p\n", contact_info);
-- uid = msim_msg_get_integer(contact_info, "ContactID");
--
-- if (!user_lookup_info) {
-- username = g_strdup(msim_uid2username_from_blist(session->account, uid));
-- display_name = NULL;
-- g_return_if_fail(username != NULL);
-- } else {
-- user_lookup_info_body = msim_msg_get_dictionary(user_lookup_info, "body");
-- username = msim_msg_get_string(user_lookup_info_body, "UserName");
-- display_name = msim_msg_get_string(user_lookup_info_body, "DisplayName");
-- msim_msg_free(user_lookup_info_body);
-- g_return_if_fail(username != NULL);
-- }
--
-- purple_debug_info("msim_add_contact_from_server_cb",
-- "*** about to add/update username=%s\n", username);
--
-- /* 1. Creates a new group, or gets existing group if it exists (or so
-- * the documentation claims). */
-- group_name = msim_msg_get_string(contact_info, "GroupName");
-- if (!group_name || (*group_name == '\0')) {
-- g_free(group_name);
-- group_name = g_strdup(_("IM Friends"));
-- purple_debug_info("myspace", "No GroupName specified, defaulting to '%s'.\n", group_name);
-- }
-- group = purple_find_group(group_name);
-- if (!group) {
-- group = purple_group_new(group_name);
-- /* Add group to beginning. See #2752. */
-- purple_blist_add_group(group, NULL);
-- }
-- g_free(group_name);
--
-- visibility = msim_msg_get_integer(contact_info, "Visibility");
-- if (visibility == 2) {
-- /* This buddy is blocked (and therefore not on our buddy list */
-- purple_privacy_deny_add(session->account, username, TRUE);
-- msim_msg_free(contact_info);
-- g_free(username);
-- g_free(display_name);
-- return;
-- }
--
-- /* 2. Get or create buddy */
-- buddy = purple_find_buddy(session->account, username);
-- if (!buddy) {
-- purple_debug_info("msim_add_contact_from_server_cb",
-- "creating new buddy: %s\n", username);
-- buddy = purple_buddy_new(session->account, username, NULL);
-- }
--
-- /* TODO: use 'Position' in contact_info to take into account where buddy is */
-- purple_blist_add_buddy(buddy, NULL, group, NULL /* insertion point */);
--
-- if (strtol(username, NULL, 10) == uid) {
-- /*
-- * This user has not set their username! Set their server
-- * alias to their display name so that we don't see a bunch
-- * of numbers in the buddy list.
-- */
-- if (display_name != NULL) {
-- purple_blist_node_set_string(PURPLE_BLIST_NODE(buddy), "DisplayName", display_name);
-- serv_got_alias(session->gc, username, display_name);
-- } else {
-- serv_got_alias(session->gc, username,
-- purple_blist_node_get_string(PURPLE_BLIST_NODE(buddy), "DisplayName"));
-- }
-- }
-- g_free(display_name);
--
-- /* 3. Update buddy information */
-- user = msim_get_user_from_buddy(buddy, TRUE);
--
-- user->id = uid;
-- /* Keep track of the user ID across sessions */
-- purple_blist_node_set_int(PURPLE_BLIST_NODE(buddy), "UserID", uid);
--
-- /* Stores a few fields in the MsimUser, relevant to the buddy itself.
-- * AvatarURL, Headline, ContactID. */
-- msim_store_user_info(session, contact_info, NULL);
--
-- /* TODO: other fields, store in 'user' */
-- msim_msg_free(contact_info);
--
-- g_free(username);
--}
--
--/**
-- * Add first ContactID in contact_info to buddy's list. Used to add
-- * server-side buddies to client-side list.
-- *
-- * @return TRUE if added.
-- */
--static gboolean
--msim_add_contact_from_server(MsimSession *session, MsimMessage *contact_info)
--{
-- guint uid;
-- const gchar *username;
--
-- uid = msim_msg_get_integer(contact_info, "ContactID");
-- g_return_val_if_fail(uid != 0, FALSE);
--
-- /* Lookup the username, since NickName and IMName is unreliable */
-- username = msim_uid2username_from_blist(session->account, uid);
-- if (!username) {
-- gchar *uid_str;
--
-- uid_str = g_strdup_printf("%d", uid);
-- purple_debug_info("msim_add_contact_from_server",
-- "contact_info addr=%p\n", contact_info);
-- msim_lookup_user(session, uid_str, msim_add_contact_from_server_cb, (gpointer)msim_msg_clone(contact_info));
-- g_free(uid_str);
-- } else {
-- msim_add_contact_from_server_cb(session, NULL, (gpointer)msim_msg_clone(contact_info));
-- }
--
-- /* Say that the contact was added, even if we're still looking up
-- * their username. */
-- return TRUE;
--}
--
--/**
-- * Called when contact list is received from server.
-- */
--static void
--msim_got_contact_list(MsimSession *session, const MsimMessage *reply, gpointer user_data)
--{
-- MsimMessage *body, *body_node;
-- gchar *msg;
-- guint buddy_count;
--
-- body = msim_msg_get_dictionary(reply, "body");
--
-- buddy_count = 0;
--
-- for (body_node = body;
-- body_node != NULL;
-- body_node = msim_msg_get_next_element_node(body_node))
-- {
-- MsimMessageElement *elem;
--
-- elem = (MsimMessageElement *)body_node->data;
--
-- if (g_str_equal(elem->name, "ContactID"))
-- {
-- /* Will look for first contact in body_node */
-- if (msim_add_contact_from_server(session, body_node)) {
-- ++buddy_count;
-- }
-- }
-- }
--
-- switch (GPOINTER_TO_UINT(user_data)) {
-- case MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS:
-- msg = g_strdup_printf(ngettext("%d buddy was added or updated from the server (including buddies already on the server-side list)",
-- "%d buddies were added or updated from the server (including buddies already on the server-side list)",
-- buddy_count),
-- buddy_count);
-- purple_notify_info(session->account, _("Add contacts from server"), msg, NULL);
-- g_free(msg);
-- break;
--
-- case MSIM_CONTACT_LIST_IMPORT_TOP_FRIENDS:
-- /* TODO */
-- break;
--
-- case MSIM_CONTACT_LIST_INITIAL_FRIENDS:
-- /* The session is now set up, ready to be connected. This emits the
-- * signedOn signal, so clients can now do anything with msimprpl, and
-- * we're ready for it (session key, userid, username all setup). */
-- purple_connection_update_progress(session->gc, _("Connected"), 3, 4);
-- purple_connection_set_state(session->gc, PURPLE_CONNECTED);
-- break;
-- }
--
-- msim_msg_free(body);
--}
--
--/**
-- * Get contact list, calling msim_got_contact_list() with
-- * what_to_do_after as user_data gpointer.
-- *
-- * @param what_to_do_after should be one of the MSIM_CONTACT_LIST_* #defines.
-- */
--static gboolean
--msim_get_contact_list(MsimSession *session, int what_to_do_after)
--{
-- return msim_send(session,
-- "persist", MSIM_TYPE_INTEGER, 1,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
-- "dsn", MSIM_TYPE_INTEGER, MG_LIST_ALL_CONTACTS_DSN,
-- "lid", MSIM_TYPE_INTEGER, MG_LIST_ALL_CONTACTS_LID,
-- "uid", MSIM_TYPE_INTEGER, session->userid,
-- "rid", MSIM_TYPE_INTEGER,
-- msim_new_reply_callback(session, msim_got_contact_list, GUINT_TO_POINTER(what_to_do_after)),
-- "body", MSIM_TYPE_STRING, g_strdup(""),
-- NULL);
--}
--
--/** Called after username is set, if necessary and we're open for business. */
--gboolean msim_we_are_logged_on(MsimSession *session)
--{
-- MsimMessage *body;
--
-- /* Set display name to username (otherwise will show email address) */
-- purple_connection_set_display_name(session->gc, session->username);
--
-- body = msim_msg_new(
-- "UserID", MSIM_TYPE_INTEGER, session->userid,
-- NULL);
--
-- /* Request IM info about ourself. */
-- msim_send(session,
-- "persist", MSIM_TYPE_INTEGER, 1,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
-- "dsn", MSIM_TYPE_INTEGER, MG_OWN_MYSPACE_INFO_DSN,
-- "lid", MSIM_TYPE_INTEGER, MG_OWN_MYSPACE_INFO_LID,
-- "rid", MSIM_TYPE_INTEGER, session->next_rid++,
-- "UserID", MSIM_TYPE_INTEGER, session->userid,
-- "body", MSIM_TYPE_DICTIONARY, body,
-- NULL);
--
-- /* Request MySpace info about ourself. */
-- msim_send(session,
-- "persist", MSIM_TYPE_INTEGER, 1,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
-- "dsn", MSIM_TYPE_INTEGER, MG_OWN_IM_INFO_DSN,
-- "lid", MSIM_TYPE_INTEGER, MG_OWN_IM_INFO_LID,
-- "rid", MSIM_TYPE_INTEGER, session->next_rid++,
-- "body", MSIM_TYPE_STRING, g_strdup(""),
-- NULL);
--
-- /* TODO: set options (persist cmd=514,dsn=1,lid=10) */
-- /* TODO: set blocklist */
--
-- /* Notify servers of our current status. */
-- purple_debug_info("msim", "msim_we_are_logged_on: notifying servers of status\n");
-- msim_set_status(session->account,
-- purple_account_get_active_status(session->account));
--
-- /* TODO: setinfo */
-- /*
-- body = msim_msg_new(
-- "TotalFriends", MSIM_TYPE_INTEGER, 666,
-- NULL);
-- msim_send(session,
-- "setinfo", MSIM_TYPE_BOOLEAN, TRUE,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- "info", MSIM_TYPE_DICTIONARY, body,
-- NULL);
-- */
--
-- /* Disable due to problems with timeouts. TODO: fix. */
--#ifdef MSIM_USE_KEEPALIVE
-- purple_timeout_add_seconds(MSIM_KEEPALIVE_INTERVAL_CHECK,
-- (GSourceFunc)msim_check_alive, session);
--#endif
--
-- /* Check mail if they want to. */
-- if (purple_account_get_check_mail(session->account)) {
-- session->inbox_handle = purple_timeout_add(MSIM_MAIL_INTERVAL_CHECK,
-- (GSourceFunc)msim_check_inbox, session);
-- msim_check_inbox(session);
-- }
--
-- msim_get_contact_list(session, MSIM_CONTACT_LIST_INITIAL_FRIENDS);
--
-- return TRUE;
--}
--
--/**
-- * Record the client version in the buddy list, from an incoming message.
-- */
--static gboolean
--msim_incoming_bm_record_cv(MsimSession *session, MsimMessage *msg)
--{
-- gchar *username, *cv;
-- gboolean ret;
-- MsimUser *user;
--
-- username = msim_msg_get_string(msg, "_username");
-- cv = msim_msg_get_string(msg, "cv");
--
-- g_return_val_if_fail(username != NULL, FALSE);
-- if (!cv) {
-- /* No client version to record, don't worry about it. */
-- g_free(username);
-- return FALSE;
-- }
--
-- user = msim_find_user(session, username);
--
-- if (user) {
-- user->client_cv = atol(cv);
-- ret = TRUE;
-- } else {
-- ret = FALSE;
-- }
--
-- g_free(username);
-- g_free(cv);
--
-- return ret;
--}
--
--#ifdef MSIM_SEND_CLIENT_VERSION
--/**
-- * Send our client version to another unofficial client that understands it.
-- */
--static gboolean
--msim_send_unofficial_client(MsimSession *session, gchar *username)
--{
-- gchar *our_info;
-- gboolean ret;
--
-- our_info = g_strdup_printf("Libpurple %d.%d.%d - msimprpl %s",
-- PURPLE_MAJOR_VERSION,
-- PURPLE_MINOR_VERSION,
-- PURPLE_MICRO_VERSION,
-- MSIM_PRPL_VERSION_STRING);
--
-- ret = msim_send_bm(session, username, our_info, MSIM_BM_UNOFFICIAL_CLIENT);
--
-- return ret;
--}
--#endif
--/**
-- * Process incoming status mood messages.
-- *
-- * @param session
-- * @param msg Status mood update message. Caller frees.
-- *
-- * @return TRUE if successful.
-- */
--static gboolean
--msim_incoming_status_mood(MsimSession *session, MsimMessage *msg) {
-- /* TODO: I dont know too much about this yet,
-- * so until I see how the official client handles
-- * this and decide if libpurple should as well,
-- * well just say we used it
-- */
-- gchar *ss;
-- ss = msim_msg_get_string(msg, "msg");
-- purple_debug_info("msim", "Incoming Status Message: %s", ss ? ss : "(NULL)");
-- g_free(ss);
-- return TRUE;
--}
--
--/**
-- * Process incoming status messages.
-- *
-- * @param session
-- * @param msg Status update message. Caller frees.
-- *
-- * @return TRUE if successful.
-- */
--static gboolean
--msim_incoming_status(MsimSession *session, MsimMessage *msg)
--{
-- MsimUser *user;
-- GList *list;
-- gchar *status_headline, *status_headline_escaped;
-- gint status_code, purple_status_code;
-- gchar *username;
-- gchar *unrecognized_msg;
--
-- g_return_val_if_fail(msg != NULL, FALSE);
--
-- /* Helpfully looked up by msim_incoming_resolve() for us. */
-- username = msim_msg_get_string(msg, "_username");
-- g_return_val_if_fail(username != NULL, FALSE);
--
-- {
-- gchar *ss;
--
-- ss = msim_msg_get_string(msg, "msg");
-- purple_debug_info("msim",
-- "msim_status: updating status for <%s> to <%s>\n",
-- username, ss ? ss : "(NULL)");
-- g_free(ss);
-- }
--
-- /* Example fields:
-- * |s|0|ss|Offline
-- * |s|1|ss|:-)|ls||ip|0|p|0
-- */
-- list = msim_msg_get_list(msg, "msg");
--
-- status_code = msim_msg_get_integer_from_element(g_list_nth_data(list, MSIM_STATUS_ORDINAL_ONLINE));
-- purple_debug_info("msim", "msim_status: %s's status code = %d\n", username, status_code);
-- status_headline = msim_msg_get_string_from_element(g_list_nth_data(list, MSIM_STATUS_ORDINAL_HEADLINE));
--
-- /* Add buddy if not found.
-- * TODO: Could this be responsible for #3444? */
-- user = msim_find_user(session, username);
-- if (!user) {
-- PurpleBuddy *buddy;
--
-- purple_debug_info("msim",
-- "msim_status: making new buddy for %s\n", username);
-- buddy = purple_buddy_new(session->account, username, NULL);
-- purple_blist_add_buddy(buddy, NULL, NULL, NULL);
--
-- user = msim_get_user_from_buddy(buddy, TRUE);
-- user->id = msim_msg_get_integer(msg, "f");
--
-- /* Keep track of the user ID across sessions */
-- purple_blist_node_set_int(PURPLE_BLIST_NODE(buddy), "UserID", user->id);
--
-- msim_store_user_info(session, msg, NULL);
-- } else {
-- purple_debug_info("msim", "msim_status: found buddy %s\n", username);
-- }
--
-- if (status_headline && strcmp(status_headline, "") != 0) {
-- /* The status headline is plaintext, but libpurple treats it as HTML,
-- * so escape any HTML characters to their entity equivalents. */
-- status_headline_escaped = g_markup_escape_text(status_headline, -1);
-- } else {
-- status_headline_escaped = NULL;
-- }
--
-- g_free(status_headline);
--
-- /* don't copy; let the MsimUser own the headline, memory-wise */
-- g_free(user->headline);
-- user->headline = status_headline_escaped;
--
-- /* Set user status */
-- switch (status_code) {
-- case MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN:
-- purple_status_code = PURPLE_STATUS_OFFLINE;
-- break;
--
-- case MSIM_STATUS_CODE_ONLINE:
-- purple_status_code = PURPLE_STATUS_AVAILABLE;
-- break;
--
-- case MSIM_STATUS_CODE_AWAY:
-- purple_status_code = PURPLE_STATUS_AWAY;
-- break;
--
-- case MSIM_STATUS_CODE_IDLE:
-- /* Treat idle as an available status. */
-- purple_status_code = PURPLE_STATUS_AVAILABLE;
-- break;
--
-- default:
-- purple_debug_info("msim", "msim_incoming_status for %s, unknown status code %d, treating as available\n",
-- username, status_code);
-- purple_status_code = PURPLE_STATUS_AVAILABLE;
--
-- unrecognized_msg = g_strdup_printf("msim_incoming_status, unrecognized status code: %d\n",
-- status_code);
-- msim_unrecognized(session, NULL, unrecognized_msg);
-- g_free(unrecognized_msg);
-- }
--
-- purple_prpl_got_user_status(session->account, username, purple_primitive_get_id_from_type(purple_status_code), NULL);
--
-- if (status_code == MSIM_STATUS_CODE_IDLE) {
-- purple_debug_info("msim", "msim_status: got idle: %s\n", username);
-- purple_prpl_got_user_idle(session->account, username, TRUE, 0);
-- } else {
-- /* All other statuses indicate going back to non-idle. */
-- purple_prpl_got_user_idle(session->account, username, FALSE, 0);
-- }
--
--#ifdef MSIM_SEND_CLIENT_VERSION
-- if (status_code == MSIM_STATUS_CODE_ONLINE) {
-- /* Secretly whisper to unofficial clients our own version as they come online */
-- msim_send_unofficial_client(session, username);
-- }
--#endif
--
-- if (status_code != MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN) {
-- /* Get information when they come online.
-- * TODO: periodically refresh?
-- */
-- purple_debug_info("msim_incoming_status", "%s came online, looking up\n", username);
-- msim_lookup_user(session, username, NULL, NULL);
-- }
--
-- g_free(username);
-- msim_msg_list_free(list);
--
-- return TRUE;
--}
--
--/**
-- * Handle an incoming instant message.
-- *
-- * @param session The session
-- * @param msg Message from the server, containing 'f' (userid from) and 'msg'.
-- * Should also contain username in _username from preprocessing.
-- *
-- * @return TRUE if successful.
-- */
--static gboolean
--msim_incoming_im(MsimSession *session, MsimMessage *msg, const gchar *username)
--{
-- gchar *msg_msim_markup, *msg_purple_markup;
-- gchar *userid;
-- time_t time_received;
-- PurpleConversation *conv;
--
-- /* I know this isn't really a string... but we need it to be one for
-- * purple_find_conversation_with_account(). */
-- userid = msim_msg_get_string(msg, "f");
--
-- purple_debug_info("msim_incoming_im", "UserID is %s", userid);
--
-- if (msim_is_userid(username)) {
-- purple_debug_info("msim", "Ignoring message from spambot (%s) on account %s\n",
-- username, purple_account_get_username(session->account));
-- return FALSE;
-- }
--
-- /* See if a conversation with their UID already exists...*/
-- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, userid, session->account);
-- if (conv) {
-- /* Since the conversation exists... We need to normalize it */
-- purple_conversation_set_name(conv, username);
-- }
--
-- msg_msim_markup = msim_msg_get_string(msg, "msg");
-- g_return_val_if_fail(msg_msim_markup != NULL, FALSE);
--
-- msg_purple_markup = msim_markup_to_html(session, msg_msim_markup);
-- g_free(msg_msim_markup);
--
-- time_received = msim_msg_get_integer(msg, "date");
-- if (!time_received) {
-- purple_debug_info("msim_incoming_im", "date in message not set.\n");
-- time_received = time(NULL);
-- }
--
-- serv_got_im(session->gc, username, msg_purple_markup, PURPLE_MESSAGE_RECV, time_received);
--
-- g_free(msg_purple_markup);
--
-- return TRUE;
--}
--
--/**
-- * Handle an incoming action message or an IM.
-- *
-- * @param session
-- * @param msg
-- *
-- * @return TRUE if successful.
-- */
--static gboolean
--msim_incoming_action_or_im(MsimSession *session, MsimMessage *msg)
--{
-- gchar *msg_text, *username;
-- gboolean rc;
--
-- g_return_val_if_fail(msg != NULL, FALSE);
--
-- msg_text = msim_msg_get_string(msg, "msg");
-- g_return_val_if_fail(msg_text != NULL, FALSE);
--
-- username = msim_msg_get_string(msg, "_username");
-- g_return_val_if_fail(username != NULL, FALSE);
--
-- purple_debug_info("msim",
-- "msim_incoming_action_or_im: action <%s> from <%s>\n",
-- msg_text, username);
--
-- if (g_str_equal(msg_text, "%typing%")) {
-- serv_got_typing(session->gc, username, 0, PURPLE_TYPING);
-- rc = TRUE;
-- } else if (g_str_equal(msg_text, "%stoptyping%")) {
-- serv_got_typing_stopped(session->gc, username);
-- rc = TRUE;
-- } else if (strstr(msg_text, "!!!ZAP_SEND!!!=RTE_BTN_ZAPS_")) {
-- rc = msim_incoming_zap(session, msg);
-- } else if (strstr(msg_text, "!!!GroupCount=")) {
-- /* TODO: support group chats. I think the number in msg_text has
-- * something to do with the 'gid' field. */
-- purple_debug_info("msim",
-- "msim_incoming_action_or_im: "
-- "TODO: implement #4691, group chats: %s\n", msg_text);
--
-- rc = TRUE;
-- } else if (strstr(msg_text, "!!!Offline=")) {
-- /* TODO: support group chats. This one might mean a user
-- * went offline or exited the chat. */
-- purple_debug_info("msim", "msim_incoming_action_or_im: "
-- "TODO: implement #4691, group chats: %s\n", msg_text);
--
-- rc = TRUE;
-- } else if (msim_msg_get_integer(msg, "aid") != 0) {
-- purple_debug_info("msim", "TODO: implement #4691, group chat from %d on %d: %s\n",
-- msim_msg_get_integer(msg, "aid"),
-- msim_msg_get_integer(msg, "f"),
-- msg_text);
--
-- rc = TRUE;
-- } else {
-- rc = msim_incoming_im(session, msg, username);
-- }
--
-- g_free(msg_text);
-- g_free(username);
--
-- return rc;
--}
--
--/**
-- * Process an incoming media (message background?) message.
-- */
--static gboolean
--msim_incoming_media(MsimSession *session, MsimMessage *msg)
--{
-- gchar *username, *text;
--
-- username = msim_msg_get_string(msg, "_username");
-- text = msim_msg_get_string(msg, "msg");
--
-- g_return_val_if_fail(username != NULL, FALSE);
-- g_return_val_if_fail(text != NULL, FALSE);
--
-- purple_debug_info("msim", "msim_incoming_media: from %s, got msg=%s\n", username, text);
--
-- /* Media messages are sent when the user opens a window to someone.
-- * Tell libpurple they started typing and stopped typing, to inform the Psychic
-- * Mode plugin so it too can open a window to the user. */
-- serv_got_typing(session->gc, username, 0, PURPLE_TYPING);
-- serv_got_typing_stopped(session->gc, username);
--
-- g_free(username);
--
-- return TRUE;
--}
--
--/**
-- * Process an incoming "unofficial client" message. The plugin for
-- * Miranda IM sends this message with the plugin information.
-- */
--static gboolean
--msim_incoming_unofficial_client(MsimSession *session, MsimMessage *msg)
--{
-- MsimUser *user;
-- gchar *username, *client_info;
--
-- username = msim_msg_get_string(msg, "_username");
-- client_info = msim_msg_get_string(msg, "msg");
--
-- g_return_val_if_fail(username != NULL, FALSE);
-- g_return_val_if_fail(client_info != NULL, FALSE);
--
-- purple_debug_info("msim", "msim_incoming_unofficial_client: %s is using client %s\n",
-- username, client_info);
--
-- user = msim_find_user(session, username);
--
-- g_return_val_if_fail(user != NULL, FALSE);
--
-- if (user->client_info) {
-- g_free(user->client_info);
-- }
-- user->client_info = client_info;
--
-- g_free(username);
-- /* Do not free client_info - the MsimUser now owns it. */
--
-- return TRUE;
--}
--
--/**
-- * Handle an incoming buddy message.
-- */
--static gboolean
--msim_incoming_bm(MsimSession *session, MsimMessage *msg)
--{
-- guint bm;
--
-- bm = msim_msg_get_integer(msg, "bm");
--
-- msim_incoming_bm_record_cv(session, msg);
--
-- switch (bm) {
-- case MSIM_BM_STATUS:
-- return msim_incoming_status(session, msg);
-- case MSIM_BM_ACTION_OR_IM_DELAYABLE:
-- case MSIM_BM_ACTION_OR_IM_INSTANT:
-- return msim_incoming_action_or_im(session, msg);
-- case MSIM_BM_MEDIA:
-- return msim_incoming_media(session, msg);
-- case MSIM_BM_UNOFFICIAL_CLIENT:
-- return msim_incoming_unofficial_client(session, msg);
-- case MSIM_BM_STATUS_MOOD:
-- return msim_incoming_status_mood(session, msg);
-- default:
-- /*
-- * Unknown message type! We used to call
-- * msim_incoming_action_or_im(session, msg);
-- * for these, but that doesn't help anything, and it means
-- * we'll show broken gibberish if MySpace starts sending us
-- * other message types.
-- */
-- purple_debug_warning("myspace", "Received unknown imcoming "
-- "message, bm=%u\n", bm);
-- return TRUE;
-- }
--}
--
--/**
-- * Process the initial server information from the server.
-- */
--static gboolean
--msim_process_server_info(MsimSession *session, MsimMessage *msg)
--{
-- MsimMessage *body;
--
-- body = msim_msg_get_dictionary(msg, "body");
-- g_return_val_if_fail(body != NULL, FALSE);
--
-- /* Example body:
--AdUnitRefreshInterval=10.
--AlertPollInterval=360.
--AllowChatRoomEmoticonSharing=False.
--ChatRoomUserIDs=78744676;163733130;1300326231;123521495;142663391.
--CurClientVersion=673.
--EnableIMBrowse=True.
--EnableIMStuffAvatars=False.
--EnableIMStuffZaps=False.
--MaxAddAllFriends=100.
--MaxContacts=1000.
--MinClientVersion=594.
--MySpaceIM_ENGLISH=78744676.
--MySpaceNowTimer=720.
--PersistenceDataTimeout=900.
--UseWebChallenge=1.
--WebTicketGoHome=False
--
-- Anything useful? TODO: use what is useful, and use it.
--*/
-- purple_debug_info("msim_process_server_info",
-- "maximum contacts: %d\n",
-- msim_msg_get_integer(body, "MaxContacts"));
--
-- session->server_info = body;
-- /* session->server_info freed in msim_session_destroy */
--
-- return TRUE;
--}
--
--/**
-- * Process a web challenge, used to login to the web site.
-- */
--static gboolean
--msim_web_challenge(MsimSession *session, MsimMessage *msg)
--{
-- /* TODO: web challenge, store token. #2659. */
-- return FALSE;
--}
--
--/**
-- * Process a persistance message reply from the server.
-- *
-- * @param session
-- * @param msg Message reply from server.
-- *
-- * @return TRUE if successful.
-- *
-- * msim_lookup_user sets callback for here
-- */
--static gboolean
--msim_process_reply(MsimSession *session, MsimMessage *msg)
--{
-- MSIM_USER_LOOKUP_CB cb;
-- gpointer data;
-- guint rid, cmd, dsn, lid;
--
-- g_return_val_if_fail(msg != NULL, FALSE);
--
-- msim_store_user_info(session, msg, NULL);
--
-- rid = msim_msg_get_integer(msg, "rid");
-- cmd = msim_msg_get_integer(msg, "cmd");
-- dsn = msim_msg_get_integer(msg, "dsn");
-- lid = msim_msg_get_integer(msg, "lid");
--
-- /* Unsolicited messages */
-- if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_GET)) {
-- if (dsn == MG_SERVER_INFO_DSN && lid == MG_SERVER_INFO_LID) {
-- return msim_process_server_info(session, msg);
-- } else if (dsn == MG_WEB_CHALLENGE_DSN && lid == MG_WEB_CHALLENGE_LID) {
-- return msim_web_challenge(session, msg);
-- }
-- }
--
-- /* If a callback is registered for this userid lookup, call it. */
-- cb = g_hash_table_lookup(session->user_lookup_cb, GUINT_TO_POINTER(rid));
-- data = g_hash_table_lookup(session->user_lookup_cb_data, GUINT_TO_POINTER(rid));
--
-- if (cb) {
-- purple_debug_info("msim", "msim_process_reply: calling callback now\n");
-- /* Clone message, so that the callback 'cb' can use it (needs to free it also). */
-- cb(session, msg, data);
-- g_hash_table_remove(session->user_lookup_cb, GUINT_TO_POINTER(rid));
-- g_hash_table_remove(session->user_lookup_cb_data, GUINT_TO_POINTER(rid));
-- } else {
-- purple_debug_info("msim",
-- "msim_process_reply: no callback for rid %d\n", rid);
-- }
--
-- return TRUE;
--}
--
--/**
-- * Handle an error from the server.
-- *
-- * @param session
-- * @param msg The message.
-- *
-- * @return TRUE if successfully reported error.
-- */
--static gboolean
--msim_error(MsimSession *session, MsimMessage *msg)
--{
-- gchar *errmsg, *full_errmsg;
-- guint err;
--
-- g_return_val_if_fail(msg != NULL, FALSE);
--
-- err = msim_msg_get_integer(msg, "err");
-- errmsg = msim_msg_get_string(msg, "errmsg");
--
-- full_errmsg = g_strdup_printf(_("Protocol error, code %d: %s"), err,
-- errmsg ? errmsg : "no 'errmsg' given");
--
-- g_free(errmsg);
--
-- purple_debug_info("msim", "msim_error (sesskey=%d): %s\n",
-- session->sesskey, full_errmsg);
--
-- /* Destroy session if fatal. */
-- if (msim_msg_get(msg, "fatal")) {
-- PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-- purple_debug_info("msim", "fatal error, closing\n");
--
-- switch (err) {
-- case MSIM_ERROR_INCORRECT_PASSWORD: /* Incorrect password */
-- reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
-- if (!purple_account_get_remember_password(session->account))
-- purple_account_set_password(session->account, NULL);
--#ifdef MSIM_MAX_PASSWORD_LENGTH
-- if (session->account->password && (strlen(session->account->password) > MSIM_MAX_PASSWORD_LENGTH)) {
-- gchar *suggestion;
--
-- suggestion = g_strdup_printf(_("%s Your password is "
-- "%zu characters, which is longer than the "
-- "maximum length of %d. Please shorten your "
-- "password at http://profileedit.myspace.com/index.cfm?fuseaction=accountSettings.changePassword and try again."),
-- full_errmsg,
-- strlen(session->account->password),
-- MSIM_MAX_PASSWORD_LENGTH);
--
-- /* Replace full_errmsg. */
-- g_free(full_errmsg);
-- full_errmsg = suggestion;
-- } else {
-- g_free(full_errmsg);
-- full_errmsg = g_strdup(_("Incorrect username or password"));
-- }
--#endif
-- break;
-- case MSIM_ERROR_LOGGED_IN_ELSEWHERE: /* Logged in elsewhere */
-- reason = PURPLE_CONNECTION_ERROR_NAME_IN_USE;
-- if (!purple_account_get_remember_password(session->account))
-- purple_account_set_password(session->account, NULL);
-- break;
-- }
-- purple_connection_error_reason(session->gc, reason, full_errmsg);
-- } else {
-- purple_notify_error(session->account, _("MySpaceIM Error"), full_errmsg, NULL);
-- }
--
-- g_free(full_errmsg);
--
-- return TRUE;
--}
--
--/**
-- * Process a message.
-- *
-- * @param session
-- * @param msg A message from the server, ready for processing (possibly with resolved username information attached). Caller frees.
-- *
-- * @return TRUE if successful. FALSE if processing failed.
-- */
--static gboolean
--msim_process(MsimSession *session, MsimMessage *msg)
--{
-- g_return_val_if_fail(session != NULL, FALSE);
-- g_return_val_if_fail(msg != NULL, FALSE);
--
-- if (msim_msg_get_integer(msg, "lc") == 1) {
-- return msim_login_challenge(session, msg);
-- } else if (msim_msg_get_integer(msg, "lc") == 2) {
-- /* return msim_we_are_logged_on(session, msg); */
-- if (msim_is_username_set(session, msg)) {
-- return msim_we_are_logged_on(session);
-- } else {
-- /* No username is set... We'll wait for the callbacks to do their work */
-- /* When they're all done, the last one will call msim_we_are_logged_on() and pick up where we left off */
-- return FALSE;
-- }
-- } else if (msim_msg_get(msg, "bm")) {
-- return msim_incoming_bm(session, msg);
-- } else if (msim_msg_get(msg, "rid")) {
-- return msim_process_reply(session, msg);
-- } else if (msim_msg_get(msg, "error")) {
-- return msim_error(session, msg);
-- } else if (msim_msg_get(msg, "ka")) {
-- return TRUE;
-- } else {
-- msim_unrecognized(session, msg, "in msim_process");
-- return FALSE;
-- }
--}
--
--/**
-- * After a uid is resolved to username, tag it with the username and submit for processing.
-- *
-- * @param session
-- * @param userinfo Response messsage to resolving request.
-- * @param data MsimMessage *, the message to attach information to.
-- */
--static void
--msim_incoming_resolved(MsimSession *session, const MsimMessage *userinfo,
-- gpointer data)
--{
-- gchar *username;
-- MsimMessage *msg, *body;
--
-- g_return_if_fail(userinfo != NULL);
--
-- body = msim_msg_get_dictionary(userinfo, "body");
-- g_return_if_fail(body != NULL);
--
-- username = msim_msg_get_string(body, "UserName");
-- g_return_if_fail(username != NULL);
-- /* Note: username will be owned by 'msg' below. */
--
-- msg = (MsimMessage *)data;
-- g_return_if_fail(msg != NULL);
--
-- /* TODO: more elegant solution than below. attach whole message? */
-- /* Special elements name beginning with '_', we'll use internally within the
-- * program (did not come directly from the wire). */
-- msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, username); /* This makes 'msg' the owner of 'username' */
--
-- /* TODO: attach more useful information, like ImageURL */
--
-- msim_process(session, msg);
--
-- msim_msg_free(msg);
-- msim_msg_free(body);
--}
--
--/**
-- * Preprocess incoming messages, resolving as needed, calling
-- * msim_process() when ready to process.
-- *
-- * @param session
-- * @param msg MsimMessage *, freed by caller.
-- */
--static gboolean
--msim_preprocess_incoming(MsimSession *session, MsimMessage *msg)
--{
-- g_return_val_if_fail(msg != NULL, FALSE);
--
-- if (msim_msg_get(msg, "bm") && msim_msg_get(msg, "f")) {
-- guint uid;
-- const gchar *username;
--
-- /* 'f' = userid message is from, in buddy messages */
-- uid = msim_msg_get_integer(msg, "f");
--
-- username = msim_uid2username_from_blist(session->account, uid);
--
-- if (username) {
-- /* Know username already, use it. */
-- purple_debug_info("msim", "msim_preprocess_incoming: tagging with _username=%s\n",
-- username);
-- msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, g_strdup(username));
-- return msim_process(session, msg);
--
-- } else {
-- gchar *from;
--
-- /* Send lookup request. */
-- /* XXX: where is msim_msg_get_string() freed? make _strdup and _nonstrdup. */
-- purple_debug_info("msim", "msim_incoming: sending lookup, setting up callback\n");
-- from = msim_msg_get_string(msg, "f");
-- msim_lookup_user(session, from, msim_incoming_resolved, msim_msg_clone(msg));
-- g_free(from);
--
-- /* indeterminate */
-- return TRUE;
-- }
-- } else {
-- /* Nothing to resolve - send directly to processing. */
-- return msim_process(session, msg);
-- }
--}
--
--/**
-- * Callback when input available.
-- *
-- * @param gc_uncasted A PurpleConnection pointer.
-- * @param source File descriptor.
-- * @param cond PURPLE_INPUT_READ
-- *
-- * Reads the input, and calls msim_preprocess_incoming() to handle it.
-- */
--static void
--msim_input_cb(gpointer gc_uncasted, gint source, PurpleInputCondition cond)
--{
-- PurpleConnection *gc;
-- MsimSession *session;
-- gchar *end;
-- int n;
--
-- g_return_if_fail(gc_uncasted != NULL);
-- g_return_if_fail(source >= 0); /* Note: 0 is a valid fd */
--
-- gc = (PurpleConnection *)(gc_uncasted);
-- session = gc->proto_data;
--
-- /* libpurple/eventloop.h only defines these two */
-- if (cond != PURPLE_INPUT_READ && cond != PURPLE_INPUT_WRITE) {
-- purple_debug_info("msim_input_cb", "unknown condition=%d\n", cond);
-- purple_connection_error_reason (gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Invalid input condition"));
-- return;
-- }
--
-- g_return_if_fail(cond == PURPLE_INPUT_READ);
--
-- /* Mark down that we got data, so we don't timeout. */
-- session->last_comm = time(NULL);
--
-- /* If approaching end of buffer, reallocate some more memory. */
-- if (session->rxsize < session->rxoff + MSIM_READ_BUF_SIZE) {
-- purple_debug_info("msim",
-- "msim_input_cb: %d-byte read buffer full, rxoff=%d, " "growing by %d bytes\n",
-- session->rxsize, session->rxoff, MSIM_READ_BUF_SIZE);
-- session->rxsize += MSIM_READ_BUF_SIZE;
-- session->rxbuf = g_realloc(session->rxbuf, session->rxsize);
--
-- return;
-- }
--
-- purple_debug_info("msim", "dynamic buffer at %d (max %d), reading up to %d\n",
-- session->rxoff, session->rxsize,
-- MSIM_READ_BUF_SIZE - session->rxoff - 1);
--
-- /* Read into buffer. On Win32, need recv() not read(). session->fd also holds
-- * the file descriptor, but it sometimes differs from the 'source' parameter.
-- */
-- n = recv(session->fd,
-- session->rxbuf + session->rxoff,
-- session->rxsize - session->rxoff - 1, 0);
--
-- if (n < 0) {
-- gchar *tmp;
--
-- if (errno == EAGAIN)
-- /* No worries */
-- return;
--
-- tmp = g_strdup_printf(_("Lost connection with server: %s"),
-- g_strerror(errno));
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-- g_free(tmp);
-- return;
-- } else if (n == 0) {
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Server closed the connection"));
-- return;
-- }
--
-- /* Null terminate */
-- purple_debug_info("msim", "msim_input_cb: going to null terminate "
-- "at n=%d\n", n);
-- session->rxbuf[session->rxoff + n] = 0;
--
--#ifdef MSIM_CHECK_EMBEDDED_NULLS
-- /* Check for embedded NULs. I don't handle them, and they shouldn't occur. */
-- if (strlen(session->rxbuf + session->rxoff) != n) {
-- /* Occurs after login, but it is not a null byte. */
-- purple_debug_info("msim", "msim_input_cb: strlen=%d, but read %d bytes"
-- "--null byte encountered?\n",
-- strlen(session->rxbuf + session->rxoff), n);
-- /*purple_connection_error_reason (gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- "Invalid message - null byte on input"); */
-- return;
-- }
--#endif
--
-- session->rxoff += n;
-- purple_debug_info("msim", "msim_input_cb: read=%d\n", n);
--
--#ifdef MSIM_DEBUG_RXBUF
-- purple_debug_info("msim", "buf=<%s>\n", session->rxbuf);
--#endif
--
-- /* Look for \\final\\ end markers. If found, process message. */
-- while((end = strstr(session->rxbuf, MSIM_FINAL_STRING))) {
-- MsimMessage *msg;
--
--#ifdef MSIM_DEBUG_RXBUF
-- purple_debug_info("msim", "in loop: buf=<%s>\n", session->rxbuf);
--#endif
-- *end = 0;
-- msg = msim_parse(session->rxbuf);
-- if (!msg) {
-- purple_debug_info("msim", "msim_input_cb: couldn't parse rxbuf\n");
-- purple_connection_error_reason (gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Unable to parse message"));
-- break;
-- } else {
-- /* Process message and then free it (processing function should
-- * clone message if it wants to keep it afterwards.) */
-- if (!msim_preprocess_incoming(session, msg)) {
-- msim_msg_dump("msim_input_cb: preprocessing message failed on msg: %s\n", msg);
-- }
-- msim_msg_free(msg);
-- }
--
-- /* Move remaining part of buffer to beginning. */
-- session->rxoff -= strlen(session->rxbuf) + strlen(MSIM_FINAL_STRING);
-- memmove(session->rxbuf, end + strlen(MSIM_FINAL_STRING),
-- session->rxsize - (end + strlen(MSIM_FINAL_STRING) - session->rxbuf));
--
-- /* Clear end of buffer
-- * memset(end, 0, MSIM_READ_BUF_SIZE - (end - session->rxbuf));
-- */
-- }
--}
--
--/**
-- * Callback when connected. Sets up input handlers.
-- *
-- * @param data A PurpleConnection pointer.
-- * @param source File descriptor.
-- * @param error_message
-- */
--static void
--msim_connect_cb(gpointer data, gint source, const gchar *error_message)
--{
-- PurpleConnection *gc;
-- MsimSession *session;
--
-- g_return_if_fail(data != NULL);
--
-- gc = (PurpleConnection *)data;
-- session = (MsimSession *)gc->proto_data;
--
-- if (source < 0) {
-- gchar *tmp = g_strdup_printf(_("Unable to connect: %s"),
-- error_message);
-- purple_connection_error_reason (gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-- g_free(tmp);
-- return;
-- }
--
-- session->fd = source;
--
-- gc->inpa = purple_input_add(source, PURPLE_INPUT_READ, msim_input_cb, gc);
--}
--
--/**
-- * Start logging in to the MSIM servers.
-- *
-- * @param acct Account information to use to login.
-- */
--static void
--msim_login(PurpleAccount *acct)
--{
-- PurpleConnection *gc;
-- const gchar *host;
-- int port;
--
-- g_return_if_fail(acct != NULL);
-- g_return_if_fail(acct->username != NULL);
--
-- purple_debug_info("msim", "logging in %s\n", acct->username);
--
-- gc = purple_account_get_connection(acct);
-- gc->proto_data = msim_session_new(acct);
-- gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_URLDESC;
--
-- /*
-- * Lets wipe out our local list of blocked buddies. We'll get a
-- * list of all blocked buddies from the server, and we shouldn't
-- * have stuff in the local list that isn't on the server list.
-- */
-- while (acct->deny != NULL)
-- purple_privacy_deny_remove(acct, acct->deny->data, TRUE);
--
-- /* 1. connect to server */
-- purple_connection_update_progress(gc, _("Connecting"),
-- 0, /* which connection step this is */
-- 4); /* total number of steps */
--
-- host = purple_account_get_string(acct, "server", MSIM_SERVER);
-- port = purple_account_get_int(acct, "port", MSIM_PORT);
--
-- /* From purple.sf.net/api:
-- * """Note that this function name can be misleading--although it is called
-- * "proxy connect," it is used for establishing any outgoing TCP connection,
-- * whether through a proxy or not.""" */
--
-- /* Calls msim_connect_cb when connected. */
-- if (!purple_proxy_connect(gc, acct, host, port, msim_connect_cb, gc)) {
-- /* TODO: try other ports if in auto mode, then save
-- * working port and try that first next time. */
-- purple_connection_error_reason (gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Unable to connect"));
-- return;
-- }
--}
--
--static void
--msim_buddy_free(PurpleBuddy *buddy)
--{
-- msim_user_free(purple_buddy_get_protocol_data(buddy));
-- purple_buddy_set_protocol_data(buddy, NULL);
--}
--
--/**
-- * Close the connection.
-- *
-- * @param gc The connection.
-- */
--static void
--msim_close(PurpleConnection *gc)
--{
-- GSList *buddies;
-- MsimSession *session;
--
-- if (gc == NULL) {
-- return;
-- }
--
-- /*
-- * Free our protocol-specific buddy data. It almost seems like libpurple
-- * should call our buddy_free prpl callback so that we don't need to do
-- * this... but it doesn't, so we do.
-- */
-- buddies = purple_find_buddies(purple_connection_get_account(gc), NULL);
-- while (buddies != NULL) {
-- msim_buddy_free(buddies->data);
-- buddies = g_slist_delete_link(buddies, buddies);
-- }
--
-- session = (MsimSession *)gc->proto_data;
-- if (session == NULL)
-- return;
--
-- gc->proto_data = NULL;
--
-- if (session->gc->inpa) {
-- purple_input_remove(session->gc->inpa);
-- }
-- if (session->fd >= 0) {
-- close(session->fd);
-- session->fd = -1;
-- }
--
-- msim_session_destroy(session);
--}
--
--/**
-- * Schedule an IM to be sent once the user ID is looked up.
-- *
-- * @param gc Connection.
-- * @param who A user id, email, or username to send the message to.
-- * @param message Instant message text to send.
-- * @param flags Flags.
-- *
-- * @return 1 if successful or postponed, -1 if failed
-- *
-- * Allows sending to a user by username, email address, or userid. If
-- * a username or email address is given, the userid must be looked up.
-- * This function does that by calling msim_postprocess_outgoing().
-- */
--static int
--msim_send_im(PurpleConnection *gc, const gchar *who, const gchar *message,
-- PurpleMessageFlags flags)
--{
-- MsimSession *session;
-- gchar *message_msim;
-- int rc;
--
-- g_return_val_if_fail(gc != NULL, -1);
-- g_return_val_if_fail(who != NULL, -1);
-- g_return_val_if_fail(message != NULL, -1);
--
-- /* 'flags' has many options, not used here. */
--
-- session = (MsimSession *)gc->proto_data;
--
-- message_msim = html_to_msim_markup(session, message);
--
-- if (msim_send_bm(session, who, message_msim, MSIM_BM_ACTION_OR_IM_DELAYABLE)) {
-- /* Return 1 to have Purple show this IM as being sent, 0 to not. I always
-- * return 1 even if the message could not be sent, since I don't know if
-- * it has failed yet--because the IM is only sent after the userid is
-- * retrieved from the server (which happens after this function returns).
-- * If an error does occur, it should be logged to the IM window.
-- */
-- rc = 1;
-- } else {
-- rc = -1;
-- }
--
-- g_free(message_msim);
--
-- return rc;
--}
--
--/**
-- * Handle when our user starts or stops typing to another user.
-- *
-- * @param gc
-- * @param name The buddy name to which our user is typing to
-- * @param state PURPLE_TYPING, PURPLE_TYPED, PURPLE_NOT_TYPING
-- *
-- * @return 0
-- */
--static unsigned int
--msim_send_typing(PurpleConnection *gc, const gchar *name,
-- PurpleTypingState state)
--{
-- const gchar *typing_str;
-- MsimSession *session;
--
-- g_return_val_if_fail(gc != NULL, 0);
-- g_return_val_if_fail(name != NULL, 0);
--
-- session = (MsimSession *)gc->proto_data;
--
-- switch (state) {
-- case PURPLE_TYPING:
-- typing_str = "%typing%";
-- break;
--
-- case PURPLE_TYPED:
-- case PURPLE_NOT_TYPING:
-- default:
-- typing_str = "%stoptyping%";
-- break;
-- }
--
-- purple_debug_info("msim", "msim_send_typing(%s): %d (%s)\n", name, state, typing_str);
-- msim_send_bm(session, name, typing_str, MSIM_BM_ACTION_OR_IM_INSTANT);
-- return 0;
--}
--
--/**
-- * Callback for msim_get_info(), for when user info is received.
-- */
--static void
--msim_get_info_cb(MsimSession *session, const MsimMessage *user_info_msg,
-- gpointer data)
--{
-- MsimMessage *msg;
-- gchar *username;
-- PurpleNotifyUserInfo *user_info;
-- MsimUser *user;
--
-- /* Get user{name,id} from msim_get_info, passed as an MsimMessage for
-- orthogonality. */
-- msg = (MsimMessage *)data;
-- g_return_if_fail(msg != NULL);
--
-- username = msim_msg_get_string(msg, "user");
-- if (!username) {
-- purple_debug_info("msim", "msim_get_info_cb: no 'user' in msg\n");
-- return;
-- }
--
-- msim_msg_free(msg);
-- purple_debug_info("msim", "msim_get_info_cb: got for user: %s\n", username);
--
-- user = msim_find_user(session, username);
--
-- if (!user) {
-- /* User isn't on blist, create a temporary user to store info. */
-- user = g_new0(MsimUser, 1);
-- user->temporary_user = TRUE;
-- }
--
-- /* Update user structure with new information */
-- msim_store_user_info(session, user_info_msg, user);
--
-- user_info = purple_notify_user_info_new();
--
-- /* Append data from MsimUser to PurpleNotifyUserInfo for display, full */
-- msim_append_user_info(session, user_info, user, TRUE);
--
-- purple_notify_userinfo(session->gc, username, user_info, NULL, NULL);
-- purple_debug_info("msim", "msim_get_info_cb: username=%s\n", username);
--
-- purple_notify_user_info_destroy(user_info);
--
-- if (user->temporary_user)
-- msim_user_free(user);
-- g_free(username);
--}
--
--/**
-- * Retrieve a user's profile.
-- * @param username Username, user ID, or email address to lookup.
-- */
--static void
--msim_get_info(PurpleConnection *gc, const gchar *username)
--{
-- MsimSession *session;
-- MsimUser *user;
-- gchar *user_to_lookup;
-- MsimMessage *user_msg;
--
-- g_return_if_fail(gc != NULL);
-- g_return_if_fail(username != NULL);
--
-- session = (MsimSession *)gc->proto_data;
--
-- /* Obtain uid of buddy. */
-- user = msim_find_user(session, username);
--
-- /* If is on buddy list, lookup by uid since it is faster. */
-- if (user && user->id) {
-- user_to_lookup = g_strdup_printf("%d", user->id);
-- } else {
-- /* Looking up buddy not on blist. Lookup by whatever user entered. */
-- user_to_lookup = g_strdup(username);
-- }
--
-- /* Pass the username to msim_get_info_cb(), because since we lookup
-- * by userid, the userinfo message will only contain the uid (not
-- * the username) but it would be useful to display the username too.
-- */
-- user_msg = msim_msg_new(
-- "user", MSIM_TYPE_STRING, g_strdup(username),
-- NULL);
-- purple_debug_info("msim", "msim_get_info, setting up lookup, user=%s\n", username);
--
-- msim_lookup_user(session, user_to_lookup, msim_get_info_cb, user_msg);
--
-- g_free(user_to_lookup);
--}
--
--/**
-- * Set status using an MSIM_STATUS_CODE_* value.
-- * @param status_code An MSIM_STATUS_CODE_* value.
-- * @param statstring Status string, must be a dynamic string (will be freed by msim_send).
-- */
--static void
--msim_set_status_code(MsimSession *session, guint status_code, gchar *statstring)
--{
-- g_return_if_fail(statstring != NULL);
--
-- purple_debug_info("msim", "msim_set_status_code: going to set status to code=%d,str=%s\n",
-- status_code, statstring);
--
-- if (!msim_send(session,
-- "status", MSIM_TYPE_INTEGER, status_code,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- "statstring", MSIM_TYPE_STRING, statstring,
-- "locstring", MSIM_TYPE_STRING, g_strdup(""),
-- NULL))
-- {
-- purple_debug_info("msim", "msim_set_status: failed to set status\n");
-- }
--}
--
--/**
-- * Set your status - callback for when user manually sets it.
-- */
--static void
--msim_set_status(PurpleAccount *account, PurpleStatus *status)
--{
-- PurpleStatusType *type;
-- PurplePresence *pres;
-- MsimSession *session;
-- guint status_code;
-- const gchar *message;
-- gchar *stripped;
-- gchar *unrecognized_msg;
--
-- session = (MsimSession *)account->gc->proto_data;
--
-- type = purple_status_get_type(status);
-- pres = purple_status_get_presence(status);
--
-- switch (purple_status_type_get_primitive(type)) {
-- case PURPLE_STATUS_AVAILABLE:
-- purple_debug_info("msim", "msim_set_status: available (%d->%d)\n", PURPLE_STATUS_AVAILABLE,
-- MSIM_STATUS_CODE_ONLINE);
-- status_code = MSIM_STATUS_CODE_ONLINE;
-- break;
--
-- case PURPLE_STATUS_INVISIBLE:
-- purple_debug_info("msim", "msim_set_status: invisible (%d->%d)\n", PURPLE_STATUS_INVISIBLE,
-- MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN);
-- status_code = MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN;
-- break;
--
-- case PURPLE_STATUS_AWAY:
-- purple_debug_info("msim", "msim_set_status: away (%d->%d)\n", PURPLE_STATUS_AWAY,
-- MSIM_STATUS_CODE_AWAY);
-- status_code = MSIM_STATUS_CODE_AWAY;
-- break;
--
-- default:
-- purple_debug_info("msim", "msim_set_status: unknown "
-- "status interpreting as online");
-- status_code = MSIM_STATUS_CODE_ONLINE;
--
-- unrecognized_msg = g_strdup_printf("msim_set_status, unrecognized status type: %d\n",
-- purple_status_type_get_primitive(type));
-- msim_unrecognized(session, NULL, unrecognized_msg);
-- g_free(unrecognized_msg);
--
-- break;
-- }
--
-- message = purple_status_get_attr_string(status, "message");
--
-- /* Status strings are plain text. */
-- if (message != NULL)
-- stripped = purple_markup_strip_html(message);
-- else
-- stripped = g_strdup("");
--
-- msim_set_status_code(session, status_code, stripped);
--
-- /* If we should be idle, set that status. Time is irrelevant here. */
-- if (purple_presence_is_idle(pres) && status_code != MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN)
-- msim_set_idle(account->gc, 1);
--}
--
--/**
-- * Go idle.
-- */
--static void
--msim_set_idle(PurpleConnection *gc, int time)
--{
-- MsimSession *session;
-- PurpleStatus *status;
--
-- g_return_if_fail(gc != NULL);
--
-- session = (MsimSession *)gc->proto_data;
--
-- status = purple_account_get_active_status(session->account);
--
-- if (time == 0) {
-- /* Going back from idle. In msim, idle is mutually exclusive
-- * from the other states (you can only be away or idle, but not
-- * both, for example), so by going non-idle I go back to what
-- * libpurple says I should be.
-- */
-- msim_set_status(session->account, status);
-- } else {
-- const gchar *message;
-- gchar *stripped;
--
-- /* Set the idle message to the status message from the real
-- * current status.
-- */
-- message = purple_status_get_attr_string(status, "message");
-- if (message != NULL)
-- stripped = purple_markup_strip_html(message);
-- else
-- stripped = g_strdup("");
--
-- /* msim doesn't support idle time, so just go idle */
-- msim_set_status_code(session, MSIM_STATUS_CODE_IDLE, stripped);
-- }
--}
--
--/**
-- * @return TRUE if everything was ok, FALSE if something went awry.
-- */
--static gboolean
--msim_update_blocklist_for_buddy(MsimSession *session, const char *name, gboolean allow, gboolean block)
--{
-- MsimMessage *msg;
-- GList *list;
--
-- list = NULL;
-- list = g_list_prepend(list, allow ? "a+" : "a-");
-- list = g_list_prepend(list, "<uid>");
-- list = g_list_prepend(list, block ? "b+" : "b-");
-- list = g_list_prepend(list, "<uid>");
-- list = g_list_reverse(list);
--
-- msg = msim_msg_new(
-- "blocklist", MSIM_TYPE_BOOLEAN, TRUE,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- /* TODO: MsimMessage lists. Currently <uid> isn't replaced in lists. */
-- /* "idlist", MSIM_TYPE_STRING, g_strdup("a-|<uid>|b-|<uid>"), */
-- "idlist", MSIM_TYPE_LIST, list,
-- NULL);
--
-- if (!msim_postprocess_outgoing(session, msg, name, "idlist", NULL)) {
-- purple_debug_error("myspace",
-- "blocklist command failed for %s, allow=%d, block=%d\n",
-- name, allow, block);
-- msim_msg_free(msg);
-- return FALSE;
-- }
--
-- msim_msg_free(msg);
--
-- return TRUE;
--}
--
--/**
-- * Add a buddy to user's buddy list.
-- */
--static void
--msim_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
--{
-- MsimSession *session;
-- MsimMessage *msg;
-- MsimMessage *msg_persist;
-- MsimMessage *body;
-- const char *name, *gname;
--
-- session = (MsimSession *)gc->proto_data;
-- name = purple_buddy_get_name(buddy);
-- gname = group ? purple_group_get_name(group) : NULL;
--
-- if (msim_get_user_from_buddy(buddy, FALSE) != NULL)
-- return;
--
-- purple_debug_info("msim", "msim_add_buddy: want to add %s to %s\n",
-- name, gname ? gname : "(no group)");
--
-- msg = msim_msg_new(
-- "addbuddy", MSIM_TYPE_BOOLEAN, TRUE,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- /* "newprofileid" will be inserted here with uid. */
-- "reason", MSIM_TYPE_STRING, g_strdup(""),
-- NULL);
--
-- if (!msim_postprocess_outgoing(session, msg, name, "newprofileid", "reason")) {
-- purple_notify_error(NULL, NULL, _("Failed to add buddy"), _("'addbuddy' command failed."));
-- msim_msg_free(msg);
-- return;
-- }
-- msim_msg_free(msg);
--
-- /* TODO: if addbuddy fails ('error' message is returned), delete added buddy from
-- * buddy list since Purple adds it locally. */
--
-- body = msim_msg_new(
-- "ContactID", MSIM_TYPE_STRING, g_strdup("<uid>"),
-- "GroupName", MSIM_TYPE_STRING, g_strdup(gname),
-- "Position", MSIM_TYPE_INTEGER, 1000,
-- "Visibility", MSIM_TYPE_INTEGER, 1,
-- "NickName", MSIM_TYPE_STRING, g_strdup(""),
-- "NameSelect", MSIM_TYPE_INTEGER, 0,
-- NULL);
--
-- /* TODO: Update blocklist. */
--
-- msg_persist = msim_msg_new(
-- "persist", MSIM_TYPE_INTEGER, 1,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_BIT_ACTION | MSIM_CMD_PUT,
-- "dsn", MSIM_TYPE_INTEGER, MC_CONTACT_INFO_DSN,
-- "uid", MSIM_TYPE_INTEGER, session->userid,
-- "lid", MSIM_TYPE_INTEGER, MC_CONTACT_INFO_LID,
-- /* TODO: Use msim_new_reply_callback to get rid. */
-- "rid", MSIM_TYPE_INTEGER, session->next_rid++,
-- "body", MSIM_TYPE_DICTIONARY, body,
-- NULL);
--
-- if (!msim_postprocess_outgoing(session, msg_persist, name, "body", NULL))
-- {
-- purple_notify_error(NULL, NULL, _("Failed to add buddy"), _("persist command failed"));
-- msim_msg_free(msg_persist);
-- return;
-- }
-- msim_msg_free(msg_persist);
--
-- /* Add to allow list, remove from block list */
-- msim_update_blocklist_for_buddy(session, name, TRUE, FALSE);
--}
--
--/**
-- * Remove a buddy from the user's buddy list.
-- */
--static void
--msim_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
--{
-- MsimSession *session;
-- MsimMessage *delbuddy_msg;
-- MsimMessage *persist_msg;
-- const char *name;
--
-- session = (MsimSession *)gc->proto_data;
-- name = purple_buddy_get_name(buddy);
--
-- delbuddy_msg = msim_msg_new(
-- "delbuddy", MSIM_TYPE_BOOLEAN, TRUE,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- /* 'delprofileid' with uid will be inserted here. */
-- NULL);
--
-- if (!msim_postprocess_outgoing(session, delbuddy_msg, name, "delprofileid", NULL)) {
-- purple_notify_error(NULL, NULL, _("Failed to remove buddy"), _("'delbuddy' command failed"));
-- msim_msg_free(delbuddy_msg);
-- return;
-- }
-- msim_msg_free(delbuddy_msg);
--
-- persist_msg = msim_msg_new(
-- "persist", MSIM_TYPE_INTEGER, 1,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_BIT_ACTION | MSIM_CMD_DELETE,
-- "dsn", MSIM_TYPE_INTEGER, MD_DELETE_BUDDY_DSN,
-- "lid", MSIM_TYPE_INTEGER, MD_DELETE_BUDDY_LID,
-- "uid", MSIM_TYPE_INTEGER, session->userid,
-- "rid", MSIM_TYPE_INTEGER, session->next_rid++,
-- /* <uid> will be replaced by postprocessing */
-- "body", MSIM_TYPE_STRING, g_strdup("ContactID=<uid>"),
-- NULL);
--
-- if (!msim_postprocess_outgoing(session, persist_msg, name, "body", NULL)) {
-- purple_notify_error(NULL, NULL, _("Failed to remove buddy"), _("persist command failed"));
-- msim_msg_free(persist_msg);
-- return;
-- }
-- msim_msg_free(persist_msg);
--
-- /*
-- * Remove from our approve list and from our block list (this
-- * doesn't seem like it would be necessary, but the official client
-- * does it)
-- */
-- if (!msim_update_blocklist_for_buddy(session, name, FALSE, FALSE)) {
-- purple_notify_error(NULL, NULL,
-- _("Failed to remove buddy"), _("blocklist command failed"));
-- return;
-- }
-- msim_buddy_free(buddy);
--}
--
--/**
-- * Remove a buddy from the user's buddy list and add them to the block list.
-- */
--static void
--msim_add_deny(PurpleConnection *gc, const char *name)
--{
-- MsimSession *session;
-- MsimMessage *msg, *body;
--
-- session = (MsimSession *)gc->proto_data;
--
-- /* Remove from buddy list */
-- msg = msim_msg_new(
-- "delbuddy", MSIM_TYPE_BOOLEAN, TRUE,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- /* 'delprofileid' with uid will be inserted here. */
-- NULL);
-- if (!msim_postprocess_outgoing(session, msg, name, "delprofileid", NULL))
-- purple_debug_error("myspace", "delbuddy command failed\n");
-- msim_msg_free(msg);
--
-- /* Remove from our approve list and add to our block list */
-- msim_update_blocklist_for_buddy(session, name, FALSE, TRUE);
--
-- /*
-- * Add the buddy to our list of blocked contacts, so we know they
-- * are blocked if we log in with another client
-- */
-- body = msim_msg_new(
-- "ContactID", MSIM_TYPE_STRING, g_strdup("<uid>"),
-- "Visibility", MSIM_TYPE_INTEGER, 2,
-- NULL);
-- msg = msim_msg_new(
-- "persist", MSIM_TYPE_INTEGER, 1,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_BIT_ACTION | MSIM_CMD_PUT,
-- "dsn", MSIM_TYPE_INTEGER, MC_CONTACT_INFO_DSN,
-- "lid", MSIM_TYPE_INTEGER, MC_CONTACT_INFO_LID,
-- "rid", MSIM_TYPE_INTEGER, session->next_rid++,
-- "body", MSIM_TYPE_DICTIONARY, body,
-- NULL);
-- if (!msim_postprocess_outgoing(session, msg, name, "body", NULL))
-- purple_debug_error("myspace", "add to block list command failed\n");
-- msim_msg_free(msg);
--
-- /*
-- * TODO: MySpace doesn't allow blocked buddies on our buddy list,
-- * do they? If not then we need to remove the buddy from
-- * libpurple's buddy list.
-- */
--}
--
--/**
-- * Remove a buddy from the user's block list.
-- */
--static void
--msim_rem_deny(PurpleConnection *gc, const char *name)
--{
-- MsimSession *session;
-- MsimMessage *msg, *body;
--
-- session = (MsimSession *)gc->proto_data;
--
-- /*
-- * Remove from our list of blocked contacts, so we know they
-- * are no longer blocked if we log in with another client
-- */
-- body = msim_msg_new(
-- "ContactID", MSIM_TYPE_STRING, g_strdup("<uid>"),
-- NULL);
-- msg = msim_msg_new(
-- "persist", MSIM_TYPE_INTEGER, 1,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_BIT_ACTION | MSIM_CMD_DELETE,
-- "dsn", MSIM_TYPE_INTEGER, MC_DELETE_CONTACT_INFO_DSN,
-- "lid", MSIM_TYPE_INTEGER, MC_DELETE_CONTACT_INFO_LID,
-- "rid", MSIM_TYPE_INTEGER, session->next_rid++,
-- "body", MSIM_TYPE_DICTIONARY, body,
-- NULL);
-- if (!msim_postprocess_outgoing(session, msg, name, "body", NULL))
-- purple_debug_error("myspace", "remove from block list command failed\n");
-- msim_msg_free(msg);
--
-- /* Remove from our approve list and our block list */
-- msim_update_blocklist_for_buddy(session, name, FALSE, FALSE);
--}
--
--/**
-- * Returns a string of a username in canonical form. Basically removes all the
-- * spaces, lowercases the string, and looks up user IDs to usernames.
-- * Normalizing tom, TOM, Tom, and 6221 wil all return 'tom'.
-- *
-- * Borrowed this code from oscar_normalize. Added checking for
-- * "if userid, get name before normalizing"
-- */
--static const char *msim_normalize(const PurpleAccount *account, const char *str) {
-- static char normalized[BUF_LEN];
-- char *tmp1, *tmp2;
-- int i, j;
-- guint id;
--
-- g_return_val_if_fail(str != NULL, NULL);
--
-- if (msim_is_userid(str)) {
-- /* Have user ID, we need to get their username first :) */
-- const char *username;
--
-- /* If the account does not exist, we can't look up the user. */
-- if (!account || !account->gc)
-- return str;
--
-- id = atol(str);
-- username = msim_uid2username_from_blist((PurpleAccount *)account, id);
-- if (!username) {
-- /* Not in buddy list... scheisse... TODO: Manual Lookup! Bug #4631 */
-- /* Note: manual lookup using msim_lookup_user() is a problem inside
-- * msim_normalize(), because msim_lookup_user() calls a callback function
-- * when the user information has been looked up, but msim_normalize() expects
-- * the result immediately. */
-- strncpy(normalized, str, BUF_LEN);
-- } else {
-- strncpy(normalized, username, BUF_LEN);
-- }
-- } else {
-- /* Have username. */
-- strncpy(normalized, str, BUF_LEN);
-- }
--
-- /* Strip spaces. */
-- for (i=0, j=0; normalized[j]; j++) {
-- if (normalized[j] != ' ')
-- normalized[i++] = normalized[j];
-- }
-- normalized[i] = '\0';
--
-- /* Lowercase and perform UTF-8 normalization. */
-- tmp1 = g_utf8_strdown(normalized, -1);
-- tmp2 = g_utf8_normalize(tmp1, -1, G_NORMALIZE_DEFAULT);
-- g_snprintf(normalized, sizeof(normalized), "%s", tmp2);
-- g_free(tmp2);
-- g_free(tmp1);
--
-- /* TODO: re-add caps and spacing back to what the user wanted.
-- * User can format their own names, for example 'msimprpl' is shown
-- * as 'MsIm PrPl' in the official client.
-- *
-- * TODO: file a ticket to add this enhancement.
-- */
--
-- return normalized;
--}
--
--/**
-- * Return whether the buddy can be messaged while offline.
-- *
-- * The protocol supports offline messages in just the same way as online
-- * messages.
-- */
--static gboolean
--msim_offline_message(const PurpleBuddy *buddy)
--{
-- return TRUE;
--}
--
--/**
-- * Send raw data to the server, possibly with embedded NULs.
-- *
-- * Used in prpl_info struct, so that plugins can have the most possible
-- * control of what is sent over the connection. Inside this prpl,
-- * msim_send_raw() is used, since it sends NUL-terminated strings (easier).
-- *
-- * @param gc PurpleConnection
-- * @param buf Buffer to send
-- * @param total_bytes Size of buffer to send
-- *
-- * @return Bytes successfully sent, or -1 on error.
-- */
--/*
-- * TODO: This needs to do non-blocking writes and use a watcher to check
-- * when the fd is available to be written to.
-- */
--static int
--msim_send_really_raw(PurpleConnection *gc, const char *buf, int total_bytes)
--{
-- int total_bytes_sent;
-- MsimSession *session;
--
-- g_return_val_if_fail(gc != NULL, -1);
-- g_return_val_if_fail(buf != NULL, -1);
-- g_return_val_if_fail(total_bytes >= 0, -1);
--
-- session = (MsimSession *)gc->proto_data;
--
-- /* Loop until all data is sent, or a failure occurs. */
-- total_bytes_sent = 0;
-- do {
-- int bytes_sent;
--
-- bytes_sent = send(session->fd, buf + total_bytes_sent,
-- total_bytes - total_bytes_sent, 0);
--
-- if (bytes_sent < 0) {
-- purple_debug_info("msim", "msim_send_raw(%s): send() failed: %s\n",
-- buf, g_strerror(errno));
-- return total_bytes_sent;
-- }
-- total_bytes_sent += bytes_sent;
--
-- } while(total_bytes_sent < total_bytes);
--
-- return total_bytes_sent;
--}
--
--/**
-- * Send raw data (given as a NUL-terminated string) to the server.
-- *
-- * @param session
-- * @param msg The raw data to send, in a NUL-terminated string.
-- *
-- * @return TRUE if succeeded, FALSE if not.
-- *
-- */
--gboolean
--msim_send_raw(MsimSession *session, const gchar *msg)
--{
-- size_t len;
--
-- g_return_val_if_fail(msg != NULL, FALSE);
--
-- purple_debug_info("msim", "msim_send_raw: writing <%s>\n", msg);
-- len = strlen(msg);
--
-- return msim_send_really_raw(session->gc, msg, len) == len;
--}
--
--static GHashTable *
--msim_get_account_text_table(PurpleAccount *unused)
--{
-- GHashTable *table;
--
-- table = g_hash_table_new(g_str_hash, g_str_equal);
--
-- g_hash_table_insert(table, "login_label", (gpointer)_("Email Address..."));
--
-- return table;
--}
--
--/**
-- * Callbacks called by Purple, to access this plugin.
-- */
--static PurplePluginProtocolInfo prpl_info = {
-- /* options */
-- OPT_PROTO_USE_POINTSIZE /* specify font size in sane point size */
-- | OPT_PROTO_MAIL_CHECK,
--
-- /* | OPT_PROTO_IM_IMAGE - TODO: direct images. */
-- NULL, /* user_splits */
-- NULL, /* protocol_options */
-- NO_BUDDY_ICONS, /* icon_spec - TODO: eventually should add this */
-- msim_list_icon, /* list_icon */
-- NULL, /* list_emblems */
-- msim_status_text, /* status_text */
-- msim_tooltip_text, /* tooltip_text */
-- msim_status_types, /* status_types */
-- msim_blist_node_menu, /* blist_node_menu */
-- NULL, /* chat_info */
-- NULL, /* chat_info_defaults */
-- msim_login, /* login */
-- msim_close, /* close */
-- msim_send_im, /* send_im */
-- NULL, /* set_info */
-- msim_send_typing, /* send_typing */
-- msim_get_info, /* get_info */
-- msim_set_status, /* set_status */
-- msim_set_idle, /* set_idle */
-- NULL, /* change_passwd */
-- msim_add_buddy, /* add_buddy */
-- NULL, /* add_buddies */
-- msim_remove_buddy, /* remove_buddy */
-- NULL, /* remove_buddies */
-- NULL, /* add_permit */
-- msim_add_deny, /* add_deny */
-- NULL, /* rem_permit */
-- msim_rem_deny, /* rem_deny */
-- NULL, /* set_permit_deny */
-- NULL, /* join_chat */
-- NULL, /* reject chat invite */
-- NULL, /* get_chat_name */
-- NULL, /* chat_invite */
-- NULL, /* chat_leave */
-- NULL, /* chat_whisper */
-- NULL, /* chat_send */
-- NULL, /* keepalive */
-- NULL, /* register_user */
-- NULL, /* get_cb_info */
-- NULL, /* get_cb_away */
-- NULL, /* alias_buddy */
-- NULL, /* group_buddy */
-- NULL, /* rename_group */
-- msim_buddy_free, /* buddy_free */
-- NULL, /* convo_closed */
-- msim_normalize, /* normalize */
-- NULL, /* set_buddy_icon */
-- NULL, /* remove_group */
-- NULL, /* get_cb_real_name */
-- NULL, /* set_chat_topic */
-- NULL, /* find_blist_chat */
-- NULL, /* roomlist_get_list */
-- NULL, /* roomlist_cancel */
-- NULL, /* roomlist_expand_category */
-- NULL, /* can_receive_file */
-- NULL, /* send_file */
-- NULL, /* new_xfer */
-- msim_offline_message, /* offline_message */
-- NULL, /* whiteboard_prpl_ops */
-- msim_send_really_raw, /* send_raw */
-- NULL, /* roomlist_room_serialize */
-- NULL, /* unregister_user */
-- msim_send_attention, /* send_attention */
-- msim_attention_types, /* attention_types */
-- sizeof(PurplePluginProtocolInfo), /* struct_size */
-- msim_get_account_text_table, /* 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 */
--};
--
--/**
-- * Load the plugin.
-- */
--static gboolean
--msim_load(PurplePlugin *plugin)
--{
-- /* If compiled to use RC4 from libpurple, check if it is really there. */
-- if (!purple_ciphers_find_cipher("rc4")) {
-- purple_debug_error("msim", "rc4 not in libpurple, but it is required - not loading MySpaceIM plugin!\n");
-- purple_notify_error(plugin, _("Missing Cipher"),
-- _("The RC4 cipher could not be found"),
-- _("Upgrade "
-- "to a libpurple with RC4 support (>= 2.0.1). MySpaceIM "
-- "plugin will not be loaded."));
-- return FALSE;
-- }
-- return TRUE;
--}
--
--/**
-- * Called when friends have been imported to buddy list on server.
-- */
--static void
--msim_import_friends_cb(MsimSession *session, const MsimMessage *reply, gpointer user_data)
--{
-- MsimMessage *body;
-- gchar *completed;
--
-- /* Check if the friends were imported successfully. */
-- body = msim_msg_get_dictionary(reply, "body");
-- g_return_if_fail(body != NULL);
-- completed = msim_msg_get_string(body, "Completed");
-- msim_msg_free(body);
-- g_return_if_fail(completed != NULL);
-- if (!g_str_equal(completed, "True"))
-- {
-- purple_debug_info("msim_import_friends_cb",
-- "failed to import friends: %s", completed);
-- purple_notify_error(session->account, _("Add friends from MySpace.com"),
-- _("Importing friends failed"), NULL);
-- g_free(completed);
-- return;
-- }
-- g_free(completed);
--
-- purple_debug_info("msim_import_friends_cb",
-- "added friends to server-side buddy list, requesting new contacts from server");
--
-- msim_get_contact_list(session, MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS);
--
-- /* TODO: show, X friends have been added */
--}
--
--/**
-- * Import friends from myspace.com.
-- */
--static void msim_import_friends(PurplePluginAction *action)
--{
-- PurpleConnection *gc;
-- MsimSession *session;
-- gchar *group_name;
--
-- gc = (PurpleConnection *)action->context;
-- session = (MsimSession *)gc->proto_data;
--
-- group_name = "MySpace Friends";
--
-- g_return_if_fail(msim_send(session,
-- "persist", MSIM_TYPE_INTEGER, 1,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_PUT,
-- "dsn", MSIM_TYPE_INTEGER, MC_IMPORT_ALL_FRIENDS_DSN,
-- "lid", MSIM_TYPE_INTEGER, MC_IMPORT_ALL_FRIENDS_LID,
-- "uid", MSIM_TYPE_INTEGER, session->userid,
-- "rid", MSIM_TYPE_INTEGER,
-- msim_new_reply_callback(session, msim_import_friends_cb, NULL),
-- "body", MSIM_TYPE_STRING,
-- g_strdup_printf("GroupName=%s", group_name),
-- NULL));
--}
--
--/**
-- * Actions menu for account.
-- */
--static GList *
--msim_actions(PurplePlugin *plugin, gpointer context /* PurpleConnection* */)
--{
-- GList *menu;
-- PurplePluginAction *act;
--
-- menu = NULL;
--
--#if 0
-- /* TODO: find out how */
-- act = purple_plugin_action_new(_("Find people..."), msim_);
-- menu = g_list_append(menu, act);
--
-- act = purple_plugin_action_new(_("Change IM name..."), NULL);
-- menu = g_list_append(menu, act);
--#endif
--
-- act = purple_plugin_action_new(_("Add friends from MySpace.com"), msim_import_friends);
-- menu = g_list_append(menu, act);
--
-- return menu;
--}
--
--/**
-- * Based on MSN's plugin info comments.
-- */
--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-myspace", /**< id */
-- "MySpaceIM", /**< name */
-- MSIM_PRPL_VERSION_STRING, /**< version */
-- /** summary */
-- "MySpaceIM Protocol Plugin",
-- /** description */
-- "MySpaceIM Protocol Plugin",
-- "Jeff Connelly <jeff2@soc.pidgin.im>", /**< author */
-- "http://developer.pidgin.im/wiki/MySpaceIM/", /**< homepage */
--
-- msim_load, /**< load */
-- NULL, /**< unload */
-- NULL, /**< destroy */
-- NULL, /**< ui_info */
-- &prpl_info, /**< extra_info */
-- NULL, /**< prefs_info */
-- msim_actions, /**< msim_actions */
-- NULL, /**< reserved1 */
-- NULL, /**< reserved2 */
-- NULL, /**< reserved3 */
-- NULL /**< reserved4 */
--};
--
--#ifdef MSIM_SELF_TEST
--/*
-- * Test functions.
-- * Used to test or try out the internal workings of msimprpl. If you're reading
-- * this code for the first time, these functions can be instructive in learning
-- * how msimprpl is architected.
-- */
--
--/**
-- * Test MsimMessage for basic functionality.
-- */
--static int
--msim_test_msg(void)
--{
-- MsimMessage *msg, *msg_cloned, *msg2;
-- GList *list;
-- gchar *packed, *packed_expected, *packed_cloned;
-- guint failures;
--
-- failures = 0;
--
-- purple_debug_info("msim", "\n\nTesting MsimMessage\n");
-- msg = msim_msg_new(NULL); /* Create a new, empty message. */
--
-- /* Append some new elements. */
-- msg = msim_msg_append(msg, "bx", MSIM_TYPE_BINARY, g_string_new_len("XXX", 3));
-- msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v1"));
-- msg = msim_msg_append(msg, "k1", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(42));
-- msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v43"));
-- msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v52/xxx\\yyy"));
-- msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v7"));
-- msim_msg_dump("msg debug str=%s\n", msg);
-- packed = msim_msg_pack(msg);
--
-- purple_debug_info("msim", "msg packed=%s\n", packed);
--
-- packed_expected = "\\bx\\WFhY\\k1\\v1\\k1\\42\\k1"
-- "\\v43\\k1\\v52/1xxx/2yyy\\k1\\v7\\final\\";
--
-- if (!g_str_equal(packed, packed_expected)) {
-- purple_debug_info("msim", "!!!(%d), msim_msg_pack not what expected: %s != %s\n",
-- ++failures, packed, packed_expected);
-- }
--
--
-- msg_cloned = msim_msg_clone(msg);
-- packed_cloned = msim_msg_pack(msg_cloned);
--
-- purple_debug_info("msim", "msg cloned=%s\n", packed_cloned);
-- if (!g_str_equal(packed, packed_cloned)) {
-- purple_debug_info("msim", "!!!(%d), msim_msg_pack on cloned message not equal to original: %s != %s\n",
-- ++failures, packed_cloned, packed);
-- }
--
-- g_free(packed);
-- g_free(packed_cloned);
-- msim_msg_free(msg_cloned);
-- msim_msg_free(msg);
--
-- /* Try some of the more advanced functionality */
-- list = NULL;
--
-- list = g_list_prepend(list, "item3");
-- list = g_list_prepend(list, "item2");
-- list = g_list_prepend(list, "item1");
-- list = g_list_prepend(list, "item0");
--
-- msg = msim_msg_new(NULL);
-- msg = msim_msg_append(msg, "string", MSIM_TYPE_STRING, g_strdup("string value"));
-- msg = msim_msg_append(msg, "raw", MSIM_TYPE_RAW, g_strdup("raw value"));
-- msg = msim_msg_append(msg, "integer", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(3140));
-- msg = msim_msg_append(msg, "boolean", MSIM_TYPE_BOOLEAN, GUINT_TO_POINTER(FALSE));
-- msg = msim_msg_append(msg, "list", MSIM_TYPE_LIST, list);
--
-- msim_msg_dump("msg with list=%s\n", msg);
-- purple_debug_info("msim", "msg with list packed=%s\n", msim_msg_pack(msg));
--
-- msg2 = msim_msg_new(NULL);
-- msg2 = msim_msg_append(msg2, "outer", MSIM_TYPE_STRING, g_strdup("outer value"));
-- msg2 = msim_msg_append(msg2, "body", MSIM_TYPE_DICTIONARY, msg);
-- msim_msg_dump("msg with dict=%s\n", msg2); /* msg2 now 'owns' msg */
-- purple_debug_info("msim", "msg with dict packed=%s\n", msim_msg_pack(msg2));
--
-- msim_msg_free(msg2);
--
-- return failures;
--}
--
--/**
-- * Test protocol-level escaping/unescaping.
-- */
--static int
--msim_test_escaping(void)
--{
-- guint failures;
-- gchar *raw, *escaped, *unescaped, *expected;
--
-- failures = 0;
--
-- purple_debug_info("msim", "\n\nTesting escaping\n");
--
-- raw = "hello/world\\hello/world";
--
-- escaped = msim_escape(raw);
-- purple_debug_info("msim", "msim_test_escaping: raw=%s, escaped=%s\n", raw, escaped);
-- expected = "hello/1world/2hello/1world";
-- if (!g_str_equal(escaped, expected)) {
-- purple_debug_info("msim", "!!!(%d), msim_escape failed: %s != %s\n",
-- ++failures, escaped, expected);
-- }
--
--
-- unescaped = msim_unescape(escaped);
-- g_free(escaped);
-- purple_debug_info("msim", "msim_test_escaping: unescaped=%s\n", unescaped);
-- if (!g_str_equal(raw, unescaped)) {
-- purple_debug_info("msim", "!!!(%d), msim_unescape failed: %s != %s\n",
-- ++failures, raw, unescaped);
-- }
--
-- return failures;
--}
--
--static void
--msim_test_all(void)
--{
-- guint failures;
--
-- failures = 0;
-- failures += msim_test_msg();
-- failures += msim_test_escaping();
--
-- if (failures) {
-- purple_debug_info("msim", "msim_test_all HAD FAILURES: %d\n", failures);
-- } else {
-- purple_debug_info("msim", "msim_test_all - all tests passed!\n");
-- }
-- exit(0);
--}
--#endif
--
--#ifdef MSIM_CHECK_NEWER_VERSION
--/**
-- * Callback for when a currentversion.txt has been downloaded.
-- */
--static void
--msim_check_newer_version_cb(PurpleUtilFetchUrlData *url_data,
-- gpointer user_data,
-- const gchar *url_text,
-- gsize len,
-- const gchar *error_message)
--{
-- GKeyFile *keyfile;
-- GError *error;
-- GString *data;
-- gchar *newest_filever;
--
-- if (!url_text) {
-- purple_debug_info("msim_check_newer_version_cb",
-- "got error: %s\n", error_message);
-- return;
-- }
--
-- purple_debug_info("msim_check_newer_version_cb",
-- "url_text=%s\n", url_text ? url_text : "(NULL)");
--
-- /* Prepend [group] so that GKeyFile can parse it (requires a group). */
-- data = g_string_new(url_text);
-- purple_debug_info("msim", "data=%s\n", data->str
-- ? data->str : "(NULL)");
-- data = g_string_prepend(data, "[group]\n");
--
-- purple_debug_info("msim", "data=%s\n", data->str
-- ? data->str : "(NULL)");
--
-- /* url_text is variable=data\n...†*/
--
-- /* Check FILEVER, 1.0.716.0. 716 is build, MSIM_CLIENT_VERSION */
-- /* New (english) version can be downloaded from SETUPURL+SETUPFILE */
--
-- error = NULL;
-- keyfile = g_key_file_new();
--
-- /* Default list seperator is ;, but currentversion.txt doesn't have
-- * these, so set to an unused character to avoid parsing problems. */
-- g_key_file_set_list_separator(keyfile, '\0');
--
-- g_key_file_load_from_data(keyfile, data->str, data->len,
-- G_KEY_FILE_NONE, &error);
-- g_string_free(data, TRUE);
--
-- if (error != NULL) {
-- purple_debug_info("msim_check_newer_version_cb",
-- "couldn't parse, error: %d %d %s\n",
-- error->domain, error->code, error->message);
-- g_error_free(error);
-- return;
-- }
--
-- gchar **ks;
-- guint n;
-- ks = g_key_file_get_keys(keyfile, "group", &n, NULL);
-- purple_debug_info("msim", "n=%d\n", n);
-- guint i;
-- for (i = 0; ks[i] != NULL; ++i)
-- {
-- purple_debug_info("msim", "%d=%s\n", i, ks[i]);
-- }
--
-- newest_filever = g_key_file_get_string(keyfile, "group",
-- "FILEVER", &error);
--
-- purple_debug_info("msim_check_newer_version_cb",
-- "newest filever: %s\n", newest_filever ?
-- newest_filever : "(NULL)");
-- if (error != NULL) {
-- purple_debug_info("msim_check_newer_version_cb",
-- "error: %d %d %s\n",
-- error->domain, error->code, error->message);
-- g_error_free(error);
-- }
--
-- g_key_file_free(keyfile);
--
-- exit(0);
--}
--#endif
--
--/**
-- Handle a myim:addContact command, after username has been looked up.
-- */
--static void
--msim_uri_handler_addContact_cb(MsimSession *session, MsimMessage *userinfo, gpointer data)
--{
-- MsimMessage *body;
-- gchar *username;
--
-- body = msim_msg_get_dictionary(userinfo, "body");
-- username = msim_msg_get_string(body, "UserName");
-- msim_msg_free(body);
--
-- if (!username) {
-- guint uid;
--
-- uid = msim_msg_get_integer(userinfo, "UserID");
-- g_return_if_fail(uid != 0);
--
-- username = g_strdup_printf("%d", uid);
-- }
--
-- purple_blist_request_add_buddy(session->account, username, _("Buddies"), NULL);
--
-- g_free(username);
--}
--
--/* TODO: move uid->username resolving to IM sending and buddy adding functions,
-- * so that user can manually add or IM by userid and username automatically
-- * looked up if possible? */
--
--/**
-- * Handle a myim:sendIM URI command, after username has been looked up.
-- */
--static void
--msim_uri_handler_sendIM_cb(MsimSession *session, MsimMessage *userinfo, gpointer data)
--{
-- PurpleConversation *conv;
-- MsimMessage *body;
-- gchar *username;
--
-- body = msim_msg_get_dictionary(userinfo, "body");
-- username = msim_msg_get_string(body, "UserName");
-- msim_msg_free(body);
--
-- if (!username) {
-- guint uid;
--
-- uid = msim_msg_get_integer(userinfo, "UserID");
-- g_return_if_fail(uid != 0);
--
-- username = g_strdup_printf("%d", uid);
-- }
--
--
-- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, username, session->account);
-- if (!conv) {
-- purple_debug_info("msim_uri_handler", "creating new conversation for %s\n", username);
-- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, session->account, username);
-- }
--
-- /* Just open the window so the user can send an IM. */
-- purple_conversation_present(conv);
--
-- g_free(username);
--}
--
--static gboolean
--msim_uri_handler(const gchar *proto, const gchar *cmd, GHashTable *params)
--{
-- PurpleAccount *account;
-- MsimSession *session;
-- GList *l;
-- gchar *uid_str, *cid_str;
-- guint uid, cid;
--
-- if (g_ascii_strcasecmp(proto, "myim"))
-- return FALSE;
--
-- /* Parameters are case-insensitive. */
-- uid_str = g_hash_table_lookup(params, "uid");
-- cid_str = g_hash_table_lookup(params, "cid");
--
-- uid = uid_str ? atol(uid_str) : 0;
-- cid = cid_str ? atol(cid_str) : 0;
--
-- /* Need a contact. */
-- g_return_val_if_fail(cid != 0, FALSE);
--
-- /* TODO: if auto=true, "Add all the people on this page to my IM List!", on
-- * http://collect.myspace.com/index.cfm?fuseaction=im.friendslist. Don't need a cid. */
--
-- /* Convert numeric contact ID back to a string. Needed for looking up. Don't just
-- * directly use cid directly from parameters, because it might not be numeric.
-- * It is trivial to change this to allow cID to be a username, but that's not how
-- * the official MySpaceIM client works, so don't provide that functionality. */
-- cid_str = g_strdup_printf("%d", cid);
--
--
-- /* Find our account with specified user id, or use first connected account if uid=0. */
-- account = NULL;
-- l = purple_accounts_get_all();
-- while (l) {
-- if (purple_account_is_connected(l->data) &&
-- (uid == 0 || purple_account_get_int(l->data, "uid", 0) == uid)) {
-- account = l->data;
-- break;
-- }
-- l = l->next;
-- }
--
-- if (!account) {
-- purple_notify_error(NULL, _("myim URL handler"),
-- _("No suitable MySpaceIM account could be found to open this myim URL."),
-- _("Enable the proper MySpaceIM account and try again."));
-- g_free(cid_str);
-- return FALSE;
-- }
--
-- session = (MsimSession *)account->gc->proto_data;
-- g_return_val_if_fail(session != NULL, FALSE);
--
-- /* Lookup userid to username. TODO: push this down, to IM sending/contact
-- * adding functions. */
--
-- /* myim:sendIM?uID=USERID&cID=CONTACTID */
-- if (!g_ascii_strcasecmp(cmd, "sendIM")) {
-- msim_lookup_user(session, cid_str, (MSIM_USER_LOOKUP_CB)msim_uri_handler_sendIM_cb, NULL);
-- g_free(cid_str);
-- return TRUE;
--
-- /* myim:addContact?uID=USERID&cID=CONTACTID */
-- } else if (!g_ascii_strcasecmp(cmd, "addContact")) {
-- msim_lookup_user(session, cid_str, (MSIM_USER_LOOKUP_CB)msim_uri_handler_addContact_cb, NULL);
-- g_free(cid_str);
-- return TRUE;
-- }
--
-- return FALSE;
--}
--
--/**
-- * Initialize plugin.
-- */
--static void
--init_plugin(PurplePlugin *plugin)
--{
--#ifdef MSIM_SELF_TEST
-- msim_test_all();
-- exit(0);
--#endif /* MSIM_SELF_TEST */
--
-- PurpleAccountOption *option;
-- static gboolean initialized = FALSE;
--
--#ifdef MSIM_CHECK_NEWER_VERSION
-- /* PROBLEM: MySpace's servers always return Content-Location, and
-- * libpurple redirects to it, infinitely, even though it is the same
-- * location we requested! */
-- purple_util_fetch_url("http://im.myspace.com/nsis/currentversion.txt",
-- FALSE, /* not full URL */
-- "MSIMAutoUpdateAgent", /* user agent */
-- TRUE, /* use HTTP/1.1 */
-- msim_check_newer_version_cb, NULL);
--#endif
--
-- /* TODO: default to automatically try different ports. Make the user be
-- * able to set the first port to try (like LastConnectedPort in Windows client). */
-- option = purple_account_option_string_new(_("Connect server"), "server", MSIM_SERVER);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
-- option = purple_account_option_int_new(_("Connect port"), "port", MSIM_PORT);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
--#ifdef MSIM_USER_WANTS_TO_CONFIGURE_STATUS_TEXT
-- option = purple_account_option_bool_new(_("Show display name in status text"), "show_display_name", TRUE);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
-- option = purple_account_option_bool_new(_("Show headline in status text"), "show_headline", TRUE);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--#endif
--
--#ifdef MSIM_USER_WANTS_TO_DISABLE_EMOTICONS
-- option = purple_account_option_bool_new(_("Send emoticons"), "emoticons", TRUE);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--#endif
--
--#ifdef MSIM_USER_REALLY_CARES_ABOUT_PRECISE_FONT_SIZES
-- option = purple_account_option_int_new(_("Screen resolution (dots per inch)"), "dpi", MSIM_DEFAULT_DPI);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
-- option = purple_account_option_int_new(_("Base font size (points)"), "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--#endif
--
-- /* Code below only runs once. Based on oscar.c's oscar_init(). */
-- if (initialized)
-- return;
--
-- initialized = TRUE;
--
-- purple_signal_connect(purple_get_core(), "uri-handler", &initialized,
-- PURPLE_CALLBACK(msim_uri_handler), NULL);
--}
--
--PURPLE_INIT_PLUGIN(myspace, init_plugin, info);
-diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/myspace.h pidgin-2.10.7-nonprism/libpurple/protocols/myspace/myspace.h
---- pidgin-2.10.7/libpurple/protocols/myspace/myspace.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/myspace.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,203 +0,0 @@
--/* MySpaceIM Protocol Plugin, header file
-- *
-- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MYSPACE_MYSPACE_H
--#define _MYSPACE_MYSPACE_H
--
--#include "internal.h"
--
--/* Other includes */
--#include <string.h>
--#include <errno.h>/* for EAGAIN */
--#include <stdarg.h>
--#include <math.h>
--
--#include <glib.h>
--
--#ifdef _WIN32
--#include "win32dep.h"
--#else
--/* For recv() and send(); needed to match Win32 */
--#include <sys/types.h>
--#include <sys/socket.h>
--#endif
--
--#include "notify.h"
--#include "plugin.h"
--#include "accountopt.h"
--#include "version.h"
--#include "cipher.h" /* for SHA-1 */
--#include "util.h" /* for base64 */
--#include "debug.h" /* for purple_debug_info */
--#include "request.h" /* For dialogs used in setting the username */
--#include "xmlnode.h"
--#include "core.h"
--#include "conversation.h" /* For late normalization */
--
--/* MySpaceIM includes */
--#include "persist.h"
--#include "message.h"
--#include "session.h"
--#include "zap.h"
--#include "markup.h"
--#include "user.h"
--
--/* Conditional compilation options */
--/* Send third-party client version? (Recognized by us and Miranda's plugin) */
--/*#define MSIM_SEND_CLIENT_VERSION */
--
--/* Debugging options */
--/* Low-level and rarely needed */
--/*#define MSIM_DEBUG_PARSE */
--/*#define MSIM_DEBUG_LOGIN_CHALLENGE*/
--/*#define MSIM_DEBUG_RXBUF */
--
--/* Encode unknown HTML tags from IM clients in messages as [tag], instead of
-- * ignoring. Useful for debugging */
--/*#define MSIM_MARKUP_SHOW_UNKNOWN_TAGS */
--
--/* Define to cause init_plugin() to run some tests and print
-- * the results to the Purple debug log, then exit. Useful to
-- * run with 'pidgin -d' to see the output. Don't define if
-- * you want to actually use the plugin! */
--/*#define MSIM_SELF_TEST */
--
--/* Constants */
--
--/* Maximum length of a password that is acceptable. This is the limit
-- * on the official client (build 679) and on the 'new password' field at
-- * http://settings.myspace.com/index.cfm?fuseaction=user.changepassword
-- * (though curiously, not on the 'current password' field). */
--
--/* After login fails, if password is greater than this many characters,
-- * warn user that it may be too long. */
--#define MSIM_MAX_PASSWORD_LENGTH 10
--
--/* Maximum length of usernames, when setting. */
--#define MSIM_MAX_USERNAME_LENGTH 25
--
--/* Build version of MySpaceIM to report to servers (1.0.xxx.0) */
--#define MSIM_CLIENT_VERSION 697
--
--/* Check for a newer official MySpaceIM client on startup?
-- * (Mostly useful for developers) */
--/*#define MSIM_CHECK_NEWER_VERSION*/
--
--/* Language codes from http://www.microsoft.com/globaldev/reference/oslocversion.mspx */
--#define MSIM_LANGUAGE_ID_ENGLISH 1033
--#define MSIM_LANGUAGE_NAME_ENGLISH "ENGLISH"
--
--/* msimprpl version string of this plugin */
--#define MSIM_PRPL_VERSION_STRING "0.18"
--
--/* Default server */
--#define MSIM_SERVER "im.myspace.akadns.net"
--#define MSIM_PORT 1863 /* TODO: alternate ports and automatic */
--
--/* Time between keepalives (seconds) - if no data within this time, is dead. */
--#define MSIM_KEEPALIVE_INTERVAL (3 * 60)
--/*#define MSIM_USE_KEEPALIVE*/
--
--/* Time to check if alive (seconds) */
--#define MSIM_KEEPALIVE_INTERVAL_CHECK 30
--
--/* Time to check for new mail (milliseconds) */
--#define MSIM_MAIL_INTERVAL_CHECK (60 * 1000)
--
--/* Constants */
--#define HASH_SIZE 0x14 /**< Size of SHA-1 hash for login */
--#define NONCE_SIZE 0x20 /**< Half of decoded 'nc' field */
--#define MSIM_READ_BUF_SIZE (15 * 1024) /**< Receive buffer size */
--#define MSIM_FINAL_STRING "\\final\\" /**< Message end marker */
--
--/* Messages */
--#define MSIM_BM_ACTION_OR_IM_DELAYABLE 1
--#define MSIM_BM_STATUS 100
--#define MSIM_BM_ACTION_OR_IM_INSTANT 121
--#define MSIM_BM_MEDIA 122
--#define MSIM_BM_PROFILE 124
--#define MSIM_BM_STATUS_MOOD 126
--#define MSIM_BM_UNOFFICIAL_CLIENT 200
--
--/* Authentication algorithm for login2 */
--#define MSIM_AUTH_ALGORITHM 196610
--
--/* Recognized challenge length */
--#define MSIM_AUTH_CHALLENGE_LENGTH 0x40
--
--#ifdef SEND_OUR_IP_ADDRESSES
--/* TODO: obtain IPs of network interfaces from user's machine, instead of
-- * hardcoding these values below (used in msim_compute_login_response).
-- * This is not immediately
-- * important because you can still connect and perform basic
-- * functions of the protocol. There is also a high chance that the addreses
-- * are RFC1918 private, so the servers couldn't do anything with them
-- * anyways except make note of that fact. Probably important for any
-- * kind of direct connection, or file transfer functionality.
-- */
--
--#define MSIM_LOGIN_IP_LIST "\x00\x00\x00\x00\x05\x7f\x00\x00\x01\x00\x00\x00\x00\x0a\x00\x00\x40\xc0\xa8\x58\x01\xc0\xa8\x3c\x01"
--#define MSIM_LOGIN_IP_LIST_LEN 25
--#endif /* SEND_OUR_IP_ADDRESSES */
--
--/* Indexes into status string (0|1|2|3|..., but 0 always empty) */
--#define MSIM_STATUS_ORDINAL_EMPTY 0
--#define MSIM_STATUS_ORDINAL_UNKNOWNs 1
--#define MSIM_STATUS_ORDINAL_ONLINE 2
--#define MSIM_STATUS_ORDINAL_UNKNOWNss 3
--#define MSIM_STATUS_ORDINAL_HEADLINE 4
--#define MSIM_STATUS_ORDINAL_UNKNOWNls 5
--#define MSIM_STATUS_ORDINAL_UNKNOWN 6
--#define MSIM_STATUS_ORDINAL_UNKNOWN1 7
--#define MSIM_STATUS_ORDINAL_UNKNOWNp 8
--#define MSIM_STATUS_ORDINAL_UNKNOWN2 9
--
--/* Status codes - states a buddy (or you!) can be in. */
--#define MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN 0
--#define MSIM_STATUS_CODE_ONLINE 1
--#define MSIM_STATUS_CODE_IDLE 2
--#define MSIM_STATUS_CODE_AWAY 5
--
--/* Inbox status bitfield values for MsimSession.inbox_status. */
--#define MSIM_INBOX_MAIL (1 << 0)
--#define MSIM_INBOX_BLOG_COMMENT (1 << 1)
--#define MSIM_INBOX_PROFILE_COMMENT (1 << 2)
--#define MSIM_INBOX_FRIEND_REQUEST (1 << 3)
--#define MSIM_INBOX_PICTURE_COMMENT (1 << 4)
--
--/* Codes for msim_got_contact_list(), to tell what to do afterwards. */
--#define MSIM_CONTACT_LIST_INITIAL_FRIENDS 0
--#define MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS 1
--#define MSIM_CONTACT_LIST_IMPORT_TOP_FRIENDS 2
--
--/* Error codes */
--#define MSIM_ERROR_INCORRECT_PASSWORD 260
--#define MSIM_ERROR_LOGGED_IN_ELSEWHERE 6
--
--/* Functions */
--gboolean msim_send_raw(MsimSession *session, const gchar *msg);
--
--gboolean msim_send_bm(MsimSession *session, const gchar *who, const gchar *text, int type);
--
--gboolean msim_we_are_logged_on(MsimSession *session);
--
--void msim_unrecognized(MsimSession *session, MsimMessage *msg, gchar *note);
--guint msim_new_reply_callback(MsimSession *session, MSIM_USER_LOOKUP_CB cb, gpointer data);
--
--#endif /* !_MYSPACE_MYSPACE_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/persist.h pidgin-2.10.7-nonprism/libpurple/protocols/myspace/persist.h
---- pidgin-2.10.7/libpurple/protocols/myspace/persist.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/persist.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,92 +0,0 @@
--/* MySpaceIM Protocol Plugin, persist commands
-- *
-- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MYSPACE_PERSIST_H
--#define _MYSPACE_PERSIST_H
--
--/** Command codes */
--#define MSIM_CMD_GET 1
--#define MSIM_CMD_PUT 2
--#define MSIM_CMD_DELETE 3
--
--/** Command bit fields */
--#define MSIM_CMD_BIT_CODE 255 /*< Bits specifying command code */
--#define MSIM_CMD_BIT_REPLY 256 /**< 1=reply, 0=request */
--#define MSIM_CMD_BIT_ACTION 512 /**< 1=action, 0=information */
--#define MSIM_CMD_BIT_ERROR 1024 /**< 1=error, 0=normal */
--
--/** Macros to read cmd bitfield. */
--#define MSIM_CMD_GET_CODE(x) (x & MSIM_CMD_BIT_CODE)
--#define MSIM_CMD_IS_REPLY(x) (x & MSIM_CMD_BIT_REPLY)
--#define MSIM_CMD_IS_REQUEST(x) !(x & MSIM_CMD_BIT_REPLY)
--#define MSIM_CMD_IS_ACTION(x) (x & MSIM_CMD_BIT_ACTION)
--#define MSIM_CMD_IS_INFO(x) !(x & MSIM_CMD_BIT_ACTION)
--#define MSIM_CMD_IS_ERROR(x) (x & MSIM_CMD_BIT_ERROR)
--#define MSIM_CMD_IS_NORMAL(x) !(x & MSIM_CMD_BIT_ERROR)
--
--/** Define a set of _DSN and _LID constants for a persistance request. */
--#define MSIM_PERSIST_DSN_LID(name,dsn,lid) \
-- static const int name##_DSN = dsn; \
-- static const int name##_LID = lid;
--
--/* Can't do this, errors:
-- * persist.h:51:3: error: '#' is not followed by a macro parameter
-- * In file included from myspace.c:37:
-- * persist.h:56: error: expected ')' before numeric constant
-- * So instead, I define const ints above.
--#define MSIM_PERSIST_DSN_LID(name,dsn,lid) \
-- #define name##_DSN dsn \
-- #define name##_LID lid
--#endif
--*/
--
--/** Messages to Get information dsn lid */
--MSIM_PERSIST_DSN_LID(MG_LIST_ALL_CONTACTS, 0, 1)
--MSIM_PERSIST_DSN_LID(MG_USER_INFO_BY_ID, 0, 2)
--MSIM_PERSIST_DSN_LID(MG_OWN_IM_INFO, 1, 4)
--MSIM_PERSIST_DSN_LID(MG_IM_INFO_BY_ID, 1, 17)
--MSIM_PERSIST_DSN_LID(MG_LIST_ALL_GROUPS, 2, 6)
--MSIM_PERSIST_DSN_LID(MG_MYSPACE_INFO_BY_ID, 4, 3)
--MSIM_PERSIST_DSN_LID(MG_OWN_MYSPACE_INFO, 4, 5)
--MSIM_PERSIST_DSN_LID(MG_MYSPACE_INFO_BY_STRING, 5, 7)
--MSIM_PERSIST_DSN_LID(MG_CHECK_MAIL, 7, 18)
--MSIM_PERSIST_DSN_LID(MG_WEB_CHALLENGE, 17, 26)
--MSIM_PERSIST_DSN_LID(MG_USER_SONG, 21, 28)
--MSIM_PERSIST_DSN_LID(MG_SERVER_INFO, 101, 20)
--
--/** Messages to Change/send information */
--MSIM_PERSIST_DSN_LID(MC_USER_PREFERENCES, 1, 10)
--MSIM_PERSIST_DSN_LID(MC_DELETE_CONTACT_INFO, 0, 8)
--MSIM_PERSIST_DSN_LID(MC_CONTACT_INFO, 0, 9)
--MSIM_PERSIST_DSN_LID(MC_SET_USERNAME, 9, 14)
--MSIM_PERSIST_DSN_LID(MC_IMPORT_ALL_FRIENDS, 14, 21)
--MSIM_PERSIST_DSN_LID(MC_INVITE, 16, 25)
--
--/** Messages to Delete information */
--MSIM_PERSIST_DSN_LID(MD_DELETE_BUDDY, 0, 8)
--
--/** Error codes */
--#define MERR_PARSE 1
--#define MERR_NOT_LOGGED_IN 2
--#define MERR_ANOTHER_LOGIN 6
--#define MERR_BAD_EMAIL 259
--#define MERR_BAD_PASSWORD 260
--#define MERR_BAD_UID_IN_PERSISTR 4352
--
--#endif /* !_MYSPACE_PERSIST_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/README pidgin-2.10.7-nonprism/libpurple/protocols/myspace/README
---- pidgin-2.10.7/libpurple/protocols/myspace/README 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/README 1969-12-31 21:00:00.000000000 -0300
-@@ -1,27 +0,0 @@
--MySpaceIM Protocol Plugin for libpurple by Jeff Connelly 2007-08-07
--
--Greetings. This package contains a plugin for libpurple (as used in
--Pidgin, formerly Gaim) to connect to the new MySpaceIM instant messaging
--network and send/receive messages. Functionality is only basic as of yet,
--and this code should be considered alpha quality.
--
--This code was initially developed under Google Summer of Code 2007.
--
--For features and TODO, see http://developer.pidgin.im/wiki/MySpaceIM
--
--Usage:
--
--Login using your _email address_ you use to login to myspace.com. You can't
--login using your numeric ID or alias.
--
--To test it out, send a message to yourself (by your username or numeric
--uid (email not yet supported)) or tom (6221). In either case you should
--get a reply. You should also be able to talk to other MySpaceIM users if
--you desire. Replies will always be shown as coming from a user's username,
--even if you IM by email or userid.
--
--Feedback welcome. You can IM my test account at "msimprpl" if you feel like it.
--
--Enjoy,
---Jeff Connelly
--msimprpl@xyzzy.cjb.net
-diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/session.c pidgin-2.10.7-nonprism/libpurple/protocols/myspace/session.c
---- pidgin-2.10.7/libpurple/protocols/myspace/session.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/session.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,98 +0,0 @@
--/* MySpaceIM Protocol Plugin, session
-- *
-- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "myspace.h"
--
--/* Session methods */
--
--/**
-- * Create a new MSIM session.
-- *
-- * @param acct The account to create the session from.
-- *
-- * @return Pointer to a new session. Free with msim_session_destroy.
-- */
--MsimSession *
--msim_session_new(PurpleAccount *acct)
--{
-- MsimSession *session;
--
-- g_return_val_if_fail(acct != NULL, NULL);
--
-- session = g_new0(MsimSession, 1);
--
-- session->magic = MSIM_SESSION_STRUCT_MAGIC;
-- session->account = acct;
-- session->gc = purple_account_get_connection(acct);
-- session->sesskey = 0;
-- session->userid = 0;
-- session->username = NULL;
-- session->fd = -1;
--
-- /* TODO: Remove. */
-- session->user_lookup_cb = g_hash_table_new_full(g_direct_hash,
-- g_direct_equal, NULL, NULL); /* do NOT free function pointers! (values) */
-- session->user_lookup_cb_data = g_hash_table_new_full(g_direct_hash,
-- g_direct_equal, NULL, NULL);/* TODO: we don't know what the values are,
-- they could be integers inside gpointers
-- or strings, so I don't freed them.
-- Figure this out, once free cache. */
--
-- /* Created in msim_process_server_info() */
-- session->server_info = NULL;
--
-- session->rxoff = 0;
-- session->rxsize = MSIM_READ_BUF_SIZE;
-- session->rxbuf = g_new0(gchar, session->rxsize);
-- session->next_rid = 1;
-- session->last_comm = time(NULL);
-- session->inbox_status = 0;
-- session->inbox_handle = 0;
--
-- return session;
--}
--
--/**
-- * Free a session.
-- *
-- * @param session The session to destroy.
-- */
--void
--msim_session_destroy(MsimSession *session)
--{
-- session->magic = -1;
--
-- g_free(session->rxbuf);
-- g_free(session->username);
--
-- /* TODO: Remove. */
-- g_hash_table_destroy(session->user_lookup_cb);
-- g_hash_table_destroy(session->user_lookup_cb_data);
--
-- if (session->server_info) {
-- msim_msg_free(session->server_info);
-- }
--
-- /* Stop checking the inbox at the end of the session. */
-- if (session->inbox_handle) {
-- purple_timeout_remove(session->inbox_handle);
-- }
--
-- g_free(session);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/session.h pidgin-2.10.7-nonprism/libpurple/protocols/myspace/session.h
---- pidgin-2.10.7/libpurple/protocols/myspace/session.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/session.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,60 +0,0 @@
--/* MySpaceIM Protocol Plugin, session
-- *
-- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MYSPACE_SESSION_H
--#define _MYSPACE_SESSION_H
--
--#include "account.h"
--
--/* Random number in every MsimSession, to ensure it is valid. */
--#define MSIM_SESSION_STRUCT_MAGIC 0xe4a6752b
--
--/* Everything needed to keep track of a session (proto_data field in PurpleConnection) */
--typedef struct _MsimSession
--{
-- guint magic; /**< MSIM_SESSION_STRUCT_MAGIC */
-- PurpleAccount *account;
-- PurpleConnection *gc;
-- guint sesskey; /**< Session key from server */
-- guint userid; /**< This user's numeric user ID */
-- gchar *username; /**< This user's unique username */
-- gboolean show_only_to_list;
-- int privacy_mode; /**< This is a bitmask */
-- int offline_message_mode;
-- gint fd; /**< File descriptor to/from server */
--
-- /* TODO: Remove. */
-- GHashTable *user_lookup_cb; /**< Username -> userid lookup callback */
-- GHashTable *user_lookup_cb_data; /**< Username -> userid lookup callback data */
--
-- MsimMessage *server_info; /**< Parameters from server */
--
-- gchar *rxbuf; /**< Receive buffer */
-- guint rxoff; /**< Receive buffer offset */
-- guint rxsize; /**< Receive buffer size */
-- guint next_rid; /**< Next request/response ID */
-- time_t last_comm; /**< Time received last communication */
-- guint inbox_status; /**< Bit field of inbox notifications */
-- guint inbox_handle; /**< The handle for the mail check timer */
--} MsimSession;
--
--MsimSession *msim_session_new(PurpleAccount *acct);
--void msim_session_destroy(MsimSession *session);
--
--#endif /* !_MYSPACE_SESSION_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/user.c pidgin-2.10.7-nonprism/libpurple/protocols/myspace/user.c
---- pidgin-2.10.7/libpurple/protocols/myspace/user.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/user.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,890 +0,0 @@
--/* MySpaceIM Protocol Plugin, header file
-- *
-- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "myspace.h"
--
--static void msim_check_username_availability_cb(PurpleConnection *gc, const char *username_to_check);
--
--static char *msim_username_to_set;
--
--/**
-- * Format the "now playing" indicator, showing the artist and song.
-- *
-- * @return Return a new string (must be g_free()'d), or NULL.
-- */
--static gchar *
--msim_format_now_playing(const gchar *band, const gchar *song)
--{
-- if ((band && *band) || (song && *song)) {
-- return g_strdup_printf("%s - %s",
-- (band && *band) ? band : "Unknown Artist",
-- (song && *song) ? song : "Unknown Song");
-- } else {
-- return NULL;
-- }
--}
--
--/**
-- * Get the MsimUser from a PurpleBuddy, optionally creating it if needed.
-- */
--MsimUser *
--msim_get_user_from_buddy(PurpleBuddy *buddy, gboolean create)
--{
-- MsimUser *user;
--
-- if (!buddy) {
-- return NULL;
-- }
--
-- user = purple_buddy_get_protocol_data(buddy);
-- if (create && !user) {
-- PurpleBlistNode *node = PURPLE_BLIST_NODE(buddy);
--
-- /* No MsimUser for this buddy; make one. */
--
-- user = g_new0(MsimUser, 1);
-- user->buddy = buddy;
-- user->id = purple_blist_node_get_int(node, "UserID");
-- purple_buddy_set_protocol_data(buddy, user);
-- }
--
-- return user;
--}
--
--void msim_user_free(MsimUser *user)
--{
-- if (!user)
-- return;
--
-- if (user->url_data != NULL)
-- purple_util_fetch_url_cancel(user->url_data);
--
-- g_free(user->client_info);
-- g_free(user->gender);
-- g_free(user->location);
-- g_free(user->headline);
-- g_free(user->display_name);
-- g_free(user->username);
-- g_free(user->band_name);
-- g_free(user->song_name);
-- g_free(user->image_url);
-- g_free(user);
--}
--
--/**
-- * Find and return an MsimUser * representing a user on the buddy list, or NULL.
-- */
--MsimUser *
--msim_find_user(MsimSession *session, const gchar *username)
--{
-- PurpleBuddy *buddy;
--
-- buddy = purple_find_buddy(session->account, username);
-- if (!buddy) {
-- return NULL;
-- }
--
-- return msim_get_user_from_buddy(buddy, TRUE);
--}
--
--/**
-- * Append user information to a PurpleNotifyUserInfo, given an MsimUser.
-- * Used by msim_tooltip_text() and msim_get_info_cb() to show a user's profile.
-- */
--void
--msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full)
--{
-- PurplePresence *presence;
-- gchar *str;
-- guint cv;
--
-- /* Useful to identify the account the tooltip refers to.
-- * Other prpls show this. */
-- if (user->username) {
-- purple_notify_user_info_add_pair(user_info, _("User"), user->username);
-- }
--
-- /* a/s/l...the vitals */
-- if (user->age) {
-- char age[16];
-- g_snprintf(age, sizeof(age), "%d", user->age);
-- purple_notify_user_info_add_pair(user_info, _("Age"), age);
-- }
--
-- if (user->gender && *user->gender) {
-- purple_notify_user_info_add_pair(user_info, _("Gender"), user->gender);
-- }
--
-- if (user->location && *user->location) {
-- purple_notify_user_info_add_pair(user_info, _("Location"), user->location);
-- }
--
-- /* Other information */
-- if (user->headline && *user->headline) {
-- purple_notify_user_info_add_pair(user_info, _("Headline"), user->headline);
-- }
--
-- if (user->buddy != NULL) {
-- presence = purple_buddy_get_presence(user->buddy);
--
-- if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
-- PurpleStatus *status;
-- const char *artist, *title;
--
-- status = purple_presence_get_status(presence, "tune");
-- title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
-- artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
--
-- str = msim_format_now_playing(artist, title);
-- if (str && *str) {
-- purple_notify_user_info_add_pair(user_info, _("Song"), str);
-- }
-- g_free(str);
-- }
-- }
--
-- /* Note: total friends only available if looked up by uid, not username. */
-- if (user->total_friends) {
-- char friends[16];
-- g_snprintf(friends, sizeof(friends), "%d", user->total_friends);
-- purple_notify_user_info_add_pair(user_info, _("Total Friends"), friends);
-- }
--
-- if (full) {
-- /* Client information */
-- char *client = NULL;
--
-- str = user->client_info;
-- cv = user->client_cv;
--
-- if (str && cv != 0) {
-- client = g_strdup_printf("%s (build %d)", str, cv);
-- } else if (str) {
-- client = g_strdup(str);
-- } else if (cv) {
-- client = g_strdup_printf("Build %d", cv);
-- }
-- if (client && *client)
-- purple_notify_user_info_add_pair(user_info, _("Client Version"), client);
-- g_free(client);
-- }
--
-- if (full && user->id) {
-- /* TODO: link to username, if available */
-- char *profile;
-- purple_notify_user_info_add_section_break(user_info);
-- if (user->buddy != NULL)
-- profile = g_strdup_printf("<a href=\"http://myspace.com/%s\">%s</a>",
-- purple_buddy_get_name(user->buddy), _("View web profile"));
-- else
-- profile = g_strdup_printf("<a href=\"http://myspace.com/%d\">%s</a>",
-- user->id, _("View web profile"));
-- purple_notify_user_info_add_pair(user_info, NULL, profile);
-- g_free(profile);
-- }
--}
--
--/**
-- * Callback for when a buddy icon finished being downloaded.
-- */
--static void
--msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data,
-- gpointer user_data,
-- const gchar *url_text,
-- gsize len,
-- const gchar *error_message)
--{
-- MsimUser *user = (MsimUser *)user_data;
-- const char *name = purple_buddy_get_name(user->buddy);
-- PurpleAccount *account;
--
-- user->url_data = NULL;
--
-- purple_debug_info("msim_downloaded_buddy_icon",
-- "Downloaded %" G_GSIZE_FORMAT " bytes\n", len);
--
-- if (!url_text) {
-- purple_debug_info("msim_downloaded_buddy_icon",
-- "failed to download icon for %s",
-- name);
-- return;
-- }
--
-- account = purple_buddy_get_account(user->buddy);
-- purple_buddy_icons_set_for_user(account, name,
-- g_memdup((gchar *)url_text, len), len,
-- /* Use URL itself as buddy icon "checksum" (TODO: ETag) */
-- user->image_url); /* checksum */
--}
--
--/**
-- * Set the currently playing song artist and or title.
-- *
-- * @param user User associated with the now playing information.
-- *
-- * @param new_artist New artist to set, or NULL/empty to not change artist.
-- *
-- * @param new_title New title to set, or NULL/empty to not change title.
-- *
-- * If new_artist and new_title are NULL/empty, deactivate PURPLE_STATUS_TUNE.
-- *
-- * This function is useful because it lets you set the artist or title
-- * individually, which purple_prpl_got_user_status() doesn't do.
-- */
--static void msim_set_artist_or_title(MsimUser *user, const char *new_artist, const char *new_title)
--{
-- PurplePresence *presence;
-- PurpleAccount *account;
-- const char *prev_artist, *prev_title;
-- const char *name;
--
-- if (user->buddy == NULL)
-- /* User not on buddy list so nothing to do */
-- return;
--
-- prev_artist = NULL;
-- prev_title = NULL;
--
-- if (new_artist && !*new_artist)
-- new_artist = NULL;
-- if (new_title && !*new_title)
-- new_title = NULL;
--
-- account = purple_buddy_get_account(user->buddy);
-- name = purple_buddy_get_name(user->buddy);
--
-- if (!new_artist && !new_title) {
-- purple_prpl_got_user_status_deactive(account, name, "tune");
-- return;
-- }
--
-- presence = purple_buddy_get_presence(user->buddy);
--
-- if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
-- PurpleStatus *status;
--
-- status = purple_presence_get_status(presence, "tune");
-- prev_title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
-- prev_artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
-- }
--
-- if (!new_artist)
-- new_artist = prev_artist;
--
-- if (!new_title)
-- new_title = prev_title;
--
-- purple_prpl_got_user_status(account, name, "tune",
-- PURPLE_TUNE_TITLE, new_title,
-- PURPLE_TUNE_ARTIST, new_artist,
-- NULL);
--}
--
--/**
-- * Store a field of information about a buddy.
-- *
-- * @param key_str Key to store.
-- * @param value_str Value string, either user takes ownership of this string
-- * or it is freed if MsimUser doesn't store the string.
-- * @param user User to store data in. Existing data will be replaced.
-- */
--static void
--msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user)
--{
-- const char *name = user->buddy ? purple_buddy_get_name(user->buddy) : NULL;
--
-- if (g_str_equal(key_str, "UserID") || g_str_equal(key_str, "ContactID")) {
-- /* Save to buddy list, if it exists, for quick cached uid lookup with msim_uid2username_from_blist(). */
-- user->id = atol(value_str);
-- g_free(value_str);
-- if (user->buddy)
-- {
-- purple_debug_info("msim", "associating uid %s with username %s\n", key_str, name);
-- purple_blist_node_set_int(PURPLE_BLIST_NODE(user->buddy), "UserID", user->id);
-- }
-- /* Need to store in MsimUser, too? What if not on blist? */
-- } else if (g_str_equal(key_str, "Age")) {
-- user->age = atol(value_str);
-- g_free(value_str);
-- } else if (g_str_equal(key_str, "Gender")) {
-- g_free(user->gender);
-- user->gender = value_str;
-- } else if (g_str_equal(key_str, "Location")) {
-- g_free(user->location);
-- user->location = value_str;
-- } else if (g_str_equal(key_str, "TotalFriends")) {
-- user->total_friends = atol(value_str);
-- g_free(value_str);
-- } else if (g_str_equal(key_str, "DisplayName")) {
-- g_free(user->display_name);
-- user->display_name = value_str;
-- } else if (g_str_equal(key_str, "BandName")) {
-- msim_set_artist_or_title(user, value_str, NULL);
-- g_free(value_str);
-- } else if (g_str_equal(key_str, "SongName")) {
-- msim_set_artist_or_title(user, NULL, value_str);
-- g_free(value_str);
-- } else if (g_str_equal(key_str, "UserName") || g_str_equal(key_str, "IMName") || g_str_equal(key_str, "NickName")) {
-- /* Ignore because PurpleBuddy knows this already */
-- g_free(value_str);
-- } else if (g_str_equal(key_str, "ImageURL") || g_str_equal(key_str, "AvatarURL")) {
-- const gchar *previous_url;
--
-- if (user->temporary_user) {
-- /* This user will be destroyed soon; don't try to look up its image or avatar,
-- * since that won't return immediately and we will end up accessing freed data.
-- */
-- g_free(value_str);
-- return;
-- }
--
-- g_free(user->image_url);
--
-- user->image_url = value_str;
--
-- /* Instead of showing 'no photo' picture, show nothing. */
-- if (g_str_equal(user->image_url, "http://x.myspace.com/images/no_pic.gif"))
-- {
-- purple_buddy_icons_set_for_user(purple_buddy_get_account(user->buddy),
-- name, NULL, 0, NULL);
-- return;
-- }
--
-- /* TODO: use ETag for checksum */
-- previous_url = purple_buddy_icons_get_checksum_for_user(user->buddy);
--
-- /* Only download if URL changed */
-- if (!previous_url || !g_str_equal(previous_url, user->image_url)) {
-- if (user->url_data != NULL)
-- purple_util_fetch_url_cancel(user->url_data);
-- user->url_data = purple_util_fetch_url(user->image_url, TRUE, NULL, TRUE, msim_downloaded_buddy_icon, (gpointer)user);
-- }
-- } else if (g_str_equal(key_str, "LastImageUpdated")) {
-- /* TODO: use somewhere */
-- user->last_image_updated = atol(value_str);
-- g_free(value_str);
-- } else if (g_str_equal(key_str, "Headline")) {
-- g_free(user->headline);
-- user->headline = value_str;
-- } else {
-- /* TODO: other fields in MsimUser */
-- gchar *msg;
--
-- msg = g_strdup_printf("msim_store_user_info_each: unknown field %s=%s",
-- key_str, value_str);
-- g_free(value_str);
--
-- msim_unrecognized(NULL, NULL, msg);
--
-- g_free(msg);
-- }
--}
--
--/**
-- * Save buddy information to the buddy list from a user info reply message.
-- *
-- * @param session
-- * @param msg The user information reply, with any amount of information.
-- * @param user The structure to save to, or NULL to save in PurpleBuddy->proto_data.
-- *
-- * Variable information is saved to the passed MsimUser structure. Permanent
-- * information (UserID) is stored in the blist node of the buddy list (and
-- * ends up in blist.xml, persisted to disk) if it exists.
-- *
-- * If the function has no buddy information, this function
-- * is a no-op (and returns FALSE).
-- */
--gboolean
--msim_store_user_info(MsimSession *session, const MsimMessage *msg, MsimUser *user)
--{
-- gchar *username;
-- MsimMessage *body, *body_node;
--
-- g_return_val_if_fail(msg != NULL, FALSE);
--
-- body = msim_msg_get_dictionary(msg, "body");
-- if (!body) {
-- return FALSE;
-- }
--
-- if (msim_msg_get_integer(msg, "dsn") == MG_OWN_IM_INFO_DSN &&
-- msim_msg_get_integer(msg, "lid") == MG_OWN_IM_INFO_LID)
-- {
-- /*
-- * Some of this info will be available on the buddy list if the
-- * user has themselves as their own buddy.
-- *
-- * Much of the info is already available in MsimSession,
-- * stored in msim_we_are_logged_on().
-- */
-- gchar *tmpstr;
--
-- tmpstr = msim_msg_get_string(body, "ShowOnlyToList");
-- if (tmpstr != NULL) {
-- session->show_only_to_list = g_str_equal(tmpstr, "True");
-- g_free(tmpstr);
-- }
--
-- session->privacy_mode = msim_msg_get_integer(body, "PrivacyMode");
-- session->offline_message_mode = msim_msg_get_integer(body, "OfflineMessageMode");
--
-- msim_send(session,
-- "blocklist", MSIM_TYPE_BOOLEAN, TRUE,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- "idlist", MSIM_TYPE_STRING,
-- g_strdup_printf("w%d|c%d",
-- session->show_only_to_list ? 1 : 0,
-- session->privacy_mode & 1),
-- NULL);
-- } else if (msim_msg_get_integer(msg, "dsn") == MG_OWN_MYSPACE_INFO_DSN &&
-- msim_msg_get_integer(msg, "lid") == MG_OWN_MYSPACE_INFO_LID) {
-- /* TODO: same as above, but for MySpace info. */
-- }
--
-- username = msim_msg_get_string(body, "UserName");
--
-- if (!username) {
-- purple_debug_info("msim",
-- "msim_process_reply: not caching body, no UserName\n");
-- msim_msg_free(body);
-- g_free(username);
-- return FALSE;
-- }
--
-- /* Null user = find and store in PurpleBuddy's proto_data */
-- if (!user) {
-- user = msim_find_user(session, username);
-- if (!user) {
-- msim_msg_free(body);
-- g_free(username);
-- return FALSE;
-- }
-- }
--
-- /* TODO: make looping over MsimMessage's easier. */
-- for (body_node = body;
-- body_node != NULL;
-- body_node = msim_msg_get_next_element_node(body_node))
-- {
-- const gchar *key_str;
-- gchar *value_str;
-- MsimMessageElement *elem;
--
-- elem = (MsimMessageElement *)body_node->data;
-- key_str = elem->name;
--
-- value_str = msim_msg_get_string_from_element(elem);
-- msim_store_user_info_each(key_str, value_str, user);
-- }
--
-- msim_msg_free(body);
-- g_free(username);
--
-- return TRUE;
--}
--
--#if 0
--/**
-- * Return whether a given username is syntactically valid.
-- * Note: does not actually check that the user exists.
-- */
--static gboolean
--msim_is_valid_username(const gchar *user)
--{
-- return !msim_is_userid(user) && /* Not all numeric */
-- strlen(user) <= MSIM_MAX_USERNAME_LENGTH
-- && strspn(user, "0123456789"
-- "abcdefghijklmnopqrstuvwxyz"
-- "_"
-- "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == strlen(user);
--}
--#endif
--
--/**
-- * Check if a string is a userid (all numeric).
-- *
-- * @param user The user id, email, or name.
-- *
-- * @return TRUE if is userid, FALSE if not.
-- */
--gboolean
--msim_is_userid(const gchar *user)
--{
-- g_return_val_if_fail(user != NULL, FALSE);
--
-- return strspn(user, "0123456789") == strlen(user);
--}
--
--/**
-- * Check if a string is an email address (contains an @).
-- *
-- * @param user The user id, email, or name.
-- *
-- * @return TRUE if is an email, FALSE if not.
-- *
-- * This function is not intended to be used as a generic
-- * means of validating email addresses, but to distinguish
-- * between a user represented by an email address from
-- * other forms of identification.
-- */
--static gboolean
--msim_is_email(const gchar *user)
--{
-- g_return_val_if_fail(user != NULL, FALSE);
--
-- return strchr(user, '@') != NULL;
--}
--
--/**
-- * Asynchronously lookup user information, calling callback when receive result.
-- *
-- * @param session
-- * @param user The user id, email address, or username. Not freed.
-- * @param cb Callback, called with user information when available.
-- * @param data An arbitray data pointer passed to the callback.
-- */
--/* TODO: change to not use callbacks */
--void
--msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data)
--{
-- MsimMessage *body;
-- gchar *field_name;
-- guint rid, dsn, lid;
--
-- g_return_if_fail(user != NULL);
-- /* Callback can be null to not call anything, just lookup & store information. */
-- /*g_return_if_fail(cb != NULL);*/
--
-- purple_debug_info("msim", "msim_lookup_userid: "
-- "asynchronously looking up <%s>\n", user);
--
-- /* Setup callback. Response will be associated with request using 'rid'. */
-- rid = msim_new_reply_callback(session, cb, data);
--
-- /* Send request */
--
-- if (msim_is_userid(user)) {
-- field_name = "UserID";
-- dsn = MG_MYSPACE_INFO_BY_ID_DSN;
-- lid = MG_MYSPACE_INFO_BY_ID_LID;
-- } else if (msim_is_email(user)) {
-- field_name = "Email";
-- dsn = MG_MYSPACE_INFO_BY_STRING_DSN;
-- lid = MG_MYSPACE_INFO_BY_STRING_LID;
-- } else {
-- field_name = "UserName";
-- dsn = MG_MYSPACE_INFO_BY_STRING_DSN;
-- lid = MG_MYSPACE_INFO_BY_STRING_LID;
-- }
--
-- body = msim_msg_new(
-- field_name, MSIM_TYPE_STRING, g_strdup(user),
-- NULL);
--
-- g_return_if_fail(msim_send(session,
-- "persist", MSIM_TYPE_INTEGER, 1,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
-- "dsn", MSIM_TYPE_INTEGER, dsn,
-- "uid", MSIM_TYPE_INTEGER, session->userid,
-- "lid", MSIM_TYPE_INTEGER, lid,
-- "rid", MSIM_TYPE_INTEGER, rid,
-- "body", MSIM_TYPE_DICTIONARY, body,
-- NULL));
--}
--
--/**
-- * Called after username is set.
-- */
--static void msim_username_is_set_cb(MsimSession *session, const MsimMessage *userinfo, gpointer data)
--{
-- gchar *username;
-- const gchar *errmsg;
-- MsimMessage *body;
--
-- guint rid;
-- gint cmd,dsn,uid,lid,code;
-- /* \persistr\\cmd\258\dsn\9\uid\204084363\lid\14\rid\369\body\UserName=TheAlbinoRhino1.Code=0\final\ */
--
-- purple_debug_info("msim","username_is_set made\n");
--
-- cmd = msim_msg_get_integer(userinfo, "cmd");
-- dsn = msim_msg_get_integer(userinfo, "dsn");
-- uid = msim_msg_get_integer(userinfo, "uid");
-- lid = msim_msg_get_integer(userinfo, "lid");
-- body = msim_msg_get_dictionary(userinfo, "body");
-- errmsg = _("An error occurred while trying to set the username. "
-- "Please try again, or visit http://editprofile.myspace.com/index.cfm?"
-- "fuseaction=profile.username to set your username.");
--
-- if (!body) {
-- purple_debug_info("msim_username_is_set_cb", "No body");
-- /* Error: No body! */
-- purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
-- }
-- username = msim_msg_get_string(body, "UserName");
-- code = msim_msg_get_integer(body,"Code");
--
-- msim_msg_free(body);
--
-- purple_debug_info("msim_username_is_set_cb",
-- "cmd = %d, dsn = %d, lid = %d, code = %d, username = %s\n",
-- cmd, dsn, lid, code, username);
--
-- if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_PUT)
-- && dsn == MC_SET_USERNAME_DSN
-- && lid == MC_SET_USERNAME_LID)
-- {
-- purple_debug_info("msim_username_is_set_cb", "Proper cmd,dsn,lid for username_is_set!\n");
-- purple_debug_info("msim_username_is_set_cb", "Username Set with return code %d\n",code);
-- if (code == 0) {
-- /* Good! */
-- session->username = username;
-- msim_we_are_logged_on(session);
-- } else {
-- purple_debug_info("msim_username_is_set", "code is %d",code);
-- /* TODO: what to do here? */
-- }
-- } else if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_GET)
-- && dsn == MG_MYSPACE_INFO_BY_STRING_DSN
-- && lid == MG_MYSPACE_INFO_BY_STRING_LID) {
-- /* Not quite done... ONE MORE STEP :) */
-- rid = msim_new_reply_callback(session, msim_username_is_set_cb, data);
-- body = msim_msg_new("UserName", MSIM_TYPE_STRING, g_strdup(username), NULL);
-- if (!msim_send(session, "persist", MSIM_TYPE_INTEGER, 1,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_PUT,
-- "dsn", MSIM_TYPE_INTEGER, MC_SET_USERNAME_DSN,
-- "uid", MSIM_TYPE_INTEGER, session->userid,
-- "lid", MSIM_TYPE_INTEGER, MC_SET_USERNAME_LID,
-- "rid", MSIM_TYPE_INTEGER, rid,
-- "body", MSIM_TYPE_DICTIONARY, body,
-- NULL)) {
-- /* Error! */
-- /* Can't set... Disconnect */
-- purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
-- }
--
-- } else {
-- /* Error! */
-- purple_debug_info("msim","username_is_set Error: Invalid cmd/dsn/lid combination");
-- purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
-- }
--}
--
--/**
-- * Asynchronously set new username, calling callback when receive result.
-- *
-- * @param session
-- * @param username The username we're setting for ourselves. Not freed.
-- * @param cb Callback, called with user information when available.
-- * @param data An arbitray data pointer passed to the callback.
-- */
--static void
--msim_set_username(MsimSession *session, const gchar *username,
-- MSIM_USER_LOOKUP_CB cb, gpointer data)
--{
-- MsimMessage *body;
-- guint rid;
--
-- g_return_if_fail(username != NULL);
-- g_return_if_fail(cb != NULL);
--
-- purple_debug_info("msim", "msim_set_username: "
-- "Setting username %s\n", username);
--
-- /* Setup callback. Response will be associated with request using 'rid'. */
-- rid = msim_new_reply_callback(session, cb, data);
--
-- /* TODO: I dont know if the ContactType is -/ALWAYS/- 1 */
--
-- body = msim_msg_new("UserName", MSIM_TYPE_STRING, g_strdup(username),NULL);
--/* \setinfo\\sesskey\469958979\info\Age=21.AvatarUrl=.BandName=.ContactType=1.DisplayName=Msim.Gender=M.ImageURL=http:/1/1x.myspace.com/1images/1no_pic.gif.LastLogin=128335268400000000.Location=US.ShowAvatar=False.SongName=.TotalFriends=1.UserName=msimprpl2\final\
--*/
--
-- /* Send request */
-- g_return_if_fail(msim_send(session,
-- "setinfo", MSIM_TYPE_BOOLEAN, TRUE,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- "info", MSIM_TYPE_DICTIONARY, body,
-- NULL));
-- body = msim_msg_new("UserName", MSIM_TYPE_STRING, g_strdup(username),NULL);
-- g_return_if_fail(msim_send(session,
-- "persist", MSIM_TYPE_INTEGER, 1,
-- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
-- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
-- "dsn", MSIM_TYPE_INTEGER, MG_MYSPACE_INFO_BY_STRING_DSN,
-- "uid", MSIM_TYPE_INTEGER, session->userid,
-- "lid", MSIM_TYPE_INTEGER, MG_MYSPACE_INFO_BY_STRING_LID,
-- "rid", MSIM_TYPE_INTEGER, rid,
-- "body", MSIM_TYPE_DICTIONARY, body,
-- NULL));
--}
--
--/**
-- * They've confirmed that username that was available, Lets make the call to set it
-- */
--static void msim_set_username_confirmed_cb(PurpleConnection *gc)
--{
-- MsimMessage *user_msg;
-- MsimSession *session;
--
-- g_return_if_fail(gc != NULL);
--
-- session = (MsimSession *)gc->proto_data;
--
-- user_msg = msim_msg_new(
-- "user", MSIM_TYPE_STRING, g_strdup(msim_username_to_set),
-- NULL);
--
-- purple_debug_info("msim_set_username_confirmed_cb", "Setting username to %s\n", msim_username_to_set);
--
-- /* Sets our username... keep your fingers crossed :) */
-- msim_set_username(session, msim_username_to_set, msim_username_is_set_cb, user_msg);
-- g_free(msim_username_to_set);
--}
--
--/**
-- * This is where we do a bit more than merely prompt the user.
-- * Now we have some real data to tell us the state of their requested username
-- * \persistr\\cmd\257\dsn\5\uid\204084363\lid\7\rid\367\body\UserName=TheAlbinoRhino1\final\
-- */
--static void msim_username_is_available_cb(MsimSession *session, const MsimMessage *userinfo, gpointer data)
--{
-- MsimMessage *msg;
-- gchar *username;
-- MsimMessage *body;
-- gint userid;
--
-- purple_debug_info("msim_username_is_available_cb", "Look up username callback made\n");
--
-- msg = (MsimMessage *)data;
-- g_return_if_fail(msg != NULL);
--
-- username = msim_msg_get_string(msg, "user");
-- body = msim_msg_get_dictionary(userinfo, "body");
--
-- if (!body) {
-- purple_debug_info("msim_username_is_available_cb", "No body for %s?!\n", username);
-- purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-- _("An error occurred while trying to set the username. "
-- "Please try again, or visit http://editprofile.myspace.com/index.cfm?"
-- "fuseaction=profile.username to set your username."));
-- return;
-- }
--
-- userid = msim_msg_get_integer(body, "UserID");
--
-- purple_debug_info("msim_username_is_available_cb", "Returned username is %s and userid is %d\n", username, userid);
-- msim_msg_free(body);
-- msim_msg_free(msg);
--
-- /* The response for a free username will ONLY have the UserName in it..
-- * thus making UserID return 0 when we msg_get_integer it */
-- if (userid == 0) {
-- /* This username is currently unused */
-- purple_debug_info("msim_username_is_available_cb", "Username available. Prompting to Confirm.\n");
-- msim_username_to_set = g_strdup(username);
-- g_free(username);
-- purple_request_yes_no(session->gc,
-- _("MySpaceIM - Username Available"),
-- _("This username is available. Would you like to set it?"),
-- _("ONCE SET, THIS CANNOT BE CHANGED!"),
-- 0,
-- session->account,
-- NULL,
-- NULL,
-- session->gc,
-- G_CALLBACK(msim_set_username_confirmed_cb),
-- G_CALLBACK(msim_do_not_set_username_cb));
-- } else {
-- /* Looks like its in use or we have an invalid response */
-- purple_debug_info("msim_username_is_available_cb", "Username unavaiable. Prompting for new entry.\n");
-- purple_request_input(session->gc, _("MySpaceIM - Please Set a Username"),
-- _("This username is unavailable."),
-- _("Please try another username:"),
-- "", FALSE, FALSE, NULL,
-- _("OK"), G_CALLBACK(msim_check_username_availability_cb),
-- _("Cancel"), G_CALLBACK(msim_do_not_set_username_cb),
-- session->account,
-- NULL,
-- NULL,
-- session->gc);
-- }
--}
--
--/**
-- * Once they've submitted their desired new username,
-- * check if it is available here.
-- */
--static void msim_check_username_availability_cb(PurpleConnection *gc, const char *username_to_check)
--{
-- MsimMessage *user_msg;
-- MsimSession *session;
--
-- g_return_if_fail(gc != NULL);
--
-- session = (MsimSession *)gc->proto_data;
--
-- purple_debug_info("msim_check_username_availability_cb", "Checking username: %s\n", username_to_check);
--
-- user_msg = msim_msg_new(
-- "user", MSIM_TYPE_STRING, g_strdup(username_to_check),
-- NULL);
--
-- /* 25 characters: letters, numbers, underscores */
-- /* TODO: VERIFY ABOVE */
--
-- /* \persist\1\sesskey\288500516\cmd\1\dsn\5\uid\204084363\lid\7\rid\367\body\UserName=Jaywalker\final\ */
-- /* Official client uses a standard lookup... So do we! */
-- msim_lookup_user(session, username_to_check, msim_username_is_available_cb, user_msg);
--}
--
--/***
-- * If they hit cancel or no at any point in the Setting Username process,
-- * we come here. Currently we're safe letting them get by without
-- * setting it, unless we hear otherwise. So for now give them a menu.
-- * If this becomes an issue with the official client then boot them here.
-- */
--void msim_do_not_set_username_cb(PurpleConnection *gc)
--{
-- purple_debug_info("msim", "Don't set username");
--
-- /* Protocol won't log in now without a username set.. Disconnect */
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("No username set"));
--}
--
--/**
-- * They've decided to set a username! Yay!
-- */
--void msim_set_username_cb(PurpleConnection *gc)
--{
-- g_return_if_fail(gc != NULL);
-- purple_debug_info("msim","Set username\n");
-- purple_request_input(gc, _("MySpaceIM - Please Set a Username"),
-- _("Please enter a username to check its availability:"),
-- NULL,
-- "", FALSE, FALSE, NULL,
-- _("OK"), G_CALLBACK(msim_check_username_availability_cb),
-- _("Cancel"), G_CALLBACK(msim_do_not_set_username_cb),
-- purple_connection_get_account(gc),
-- NULL,
-- NULL,
-- gc);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/user.h pidgin-2.10.7-nonprism/libpurple/protocols/myspace/user.h
---- pidgin-2.10.7/libpurple/protocols/myspace/user.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/user.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,60 +0,0 @@
--/* MySpaceIM Protocol Plugin, header file
-- *
-- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MYSPACE_USER_H
--#define _MYSPACE_USER_H
--
--/* Hold ephemeral information about buddies, for proto_data of PurpleBuddy. */
--/* GHashTable? */
--typedef struct _MsimUser
--{
-- PurpleBuddy *buddy;
-- /* Note: id is also &buddy->node (set_blist_node_int), when buddy is non-NULL */
-- int id;
-- guint client_cv;
-- gchar *client_info;
-- guint age;
-- gchar *gender;
-- gchar *location;
-- guint total_friends;
-- gchar *headline;
-- gchar *display_name;
-- gchar *username;
-- gchar *band_name, *song_name;
-- gchar *image_url;
-- guint last_image_updated;
-- gboolean temporary_user;
-- PurpleUtilFetchUrlData *url_data;
--} MsimUser;
--
--/* Callback function pointer type for when a user's information is received,
-- * initiated from a user lookup. */
--typedef void (*MSIM_USER_LOOKUP_CB)(MsimSession *session, const MsimMessage *userinfo, gpointer data);
--
--MsimUser *msim_get_user_from_buddy(PurpleBuddy *buddy, gboolean create);
--void msim_user_free(MsimUser *user);
--MsimUser *msim_find_user(MsimSession *session, const gchar *username);
--void msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full);
--gboolean msim_store_user_info(MsimSession *session, const MsimMessage *msg, MsimUser *user);
--gboolean msim_is_userid(const gchar *user);
--void msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data);
--void msim_set_username_cb(PurpleConnection *gc);
--void msim_do_not_set_username_cb(PurpleConnection *gc);
--
--#endif /* !_MYSPACE_USER_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/zap.c pidgin-2.10.7-nonprism/libpurple/protocols/myspace/zap.c
---- pidgin-2.10.7/libpurple/protocols/myspace/zap.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/zap.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,246 +0,0 @@
--/* MySpaceIM Protocol Plugin - zap support
-- *
-- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "myspace.h"
--#include "zap.h"
--
--/** Get zap types. */
--GList *
--msim_attention_types(PurpleAccount *acct)
--{
-- static GList *types = NULL;
-- PurpleAttentionType* attn;
--
-- if (!types) {
--#define _MSIM_ADD_NEW_ATTENTION(icn, ulname, nme, incoming, outgoing) \
-- attn = purple_attention_type_new(ulname, nme, incoming, outgoing); \
-- purple_attention_type_set_icon_name(attn, icn); \
-- types = g_list_append(types, attn);
--
-- /* TODO: icons for each zap */
--
-- /* Lots of comments for translators: */
--
-- /* Zap means "to strike suddenly and forcefully as if with a
-- * projectile or weapon." This term often has an electrical
-- * connotation, for example, "he was zapped by electricity when
-- * he put a fork in the toaster." */
-- _MSIM_ADD_NEW_ATTENTION(NULL, "Zap", _("Zap"), _("%s has zapped you!"),
-- _("Zapping %s..."));
--
-- /* Whack means "to hit or strike someone with a sharp blow" */
-- _MSIM_ADD_NEW_ATTENTION(NULL, "Whack", _("Whack"),
-- _("%s has whacked you!"), _("Whacking %s..."));
--
-- /* Torch means "to set on fire." Don't worry, this doesn't
-- * make a whole lot of sense in English, either. Feel free
-- * to translate it literally. */
-- _MSIM_ADD_NEW_ATTENTION(NULL, "Torch", _("Torch"),
-- _("%s has torched you!"), _("Torching %s..."));
--
-- /* Smooch means "to kiss someone, often enthusiastically" */
-- _MSIM_ADD_NEW_ATTENTION(NULL, "Smooch", _("Smooch"),
-- _("%s has smooched you!"), _("Smooching %s..."));
--
-- /* A hug is a display of affection; wrapping your arms around someone */
-- _MSIM_ADD_NEW_ATTENTION(NULL, "Hug", _("Hug"), _("%s has hugged you!"),
-- _("Hugging %s..."));
--
-- /* Slap means "to hit someone with an open/flat hand" */
-- _MSIM_ADD_NEW_ATTENTION(NULL, "Slap", _("Slap"),
-- _("%s has slapped you!"), _("Slapping %s..."));
--
-- /* Goose means "to pinch someone on their butt" */
-- _MSIM_ADD_NEW_ATTENTION(NULL, "Goose", _("Goose"),
-- _("%s has goosed you!"), _("Goosing %s..."));
--
-- /* A high-five is when two people's hands slap each other
-- * in the air above their heads. It is done to celebrate
-- * something, often a victory, or to congratulate someone. */
-- _MSIM_ADD_NEW_ATTENTION(NULL, "High-five", _("High-five"),
-- _("%s has high-fived you!"), _("High-fiving %s..."));
--
-- /* We're not entirely sure what the MySpace people mean by
-- * this... but we think it's the equivalent of "prank." Or, for
-- * someone to perform a mischievous trick or practical joke. */
-- _MSIM_ADD_NEW_ATTENTION(NULL, "Punk", _("Punk"),
-- _("%s has punk'd you!"), _("Punking %s..."));
--
-- /* Raspberry is a slang term for the vibrating sound made
-- * when you stick your tongue out of your mouth with your
-- * lips closed and blow. It is typically done when
-- * gloating or bragging. Nowadays it's a pretty silly
-- * gesture, so it does not carry a harsh negative
-- * connotation. It is generally used in a playful tone
-- * with friends. */
-- _MSIM_ADD_NEW_ATTENTION(NULL, "Raspberry", _("Raspberry"),
-- _("%s has raspberried you!"), _("Raspberrying %s..."));
-- }
--
-- return types;
--}
--
--/** Send a zap to a user. */
--static gboolean
--msim_send_zap(MsimSession *session, const gchar *username, guint code)
--{
-- gchar *zap_string;
-- gboolean rc;
--
-- g_return_val_if_fail(session != NULL, FALSE);
-- g_return_val_if_fail(username != NULL, FALSE);
--
-- /* Construct and send the actual zap command. */
-- zap_string = g_strdup_printf("!!!ZAP_SEND!!!=RTE_BTN_ZAPS_%d", code);
--
-- if (!msim_send_bm(session, username, zap_string, MSIM_BM_ACTION_OR_IM_INSTANT)) {
-- purple_debug_info("msim_send_zap",
-- "msim_send_bm failed: zapping %s with %s\n",
-- username, zap_string);
-- rc = FALSE;
-- } else {
-- rc = TRUE;
-- }
--
-- g_free(zap_string);
--
-- return rc;
--}
--
--/** Send a zap */
--gboolean
--msim_send_attention(PurpleConnection *gc, const gchar *username, guint code)
--{
-- GList *types;
-- MsimSession *session;
-- PurpleAttentionType *attn;
-- PurpleBuddy *buddy;
--
-- session = (MsimSession *)gc->proto_data;
--
-- /* Look for this attention type, by the code index given. */
-- types = msim_attention_types(gc->account);
-- attn = (PurpleAttentionType *)g_list_nth_data(types, code);
--
-- if (!attn) {
-- purple_debug_info("msim_send_attention", "got invalid zap code %d\n", code);
-- return FALSE;
-- }
--
-- buddy = purple_find_buddy(session->account, username);
-- if (!buddy) {
-- return FALSE;
-- }
--
-- msim_send_zap(session, username, code);
--
-- return TRUE;
--}
--
--/** Zap someone. Callback from msim_blist_node_menu zap menu. */
--static void
--msim_send_zap_from_menu(PurpleBlistNode *node, gpointer zap_num_ptr)
--{
-- PurpleBuddy *buddy;
-- PurpleAccount *account;
-- PurpleConnection *gc;
-- MsimSession *session;
-- guint zap;
--
-- if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) {
-- /* Only know about buddies for now. */
-- return;
-- }
--
-- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
--
-- buddy = (PurpleBuddy *)node;
--
-- /* Find the session */
-- account = purple_buddy_get_account(buddy);
-- gc = purple_account_get_connection(account);
-- session = (MsimSession *)gc->proto_data;
--
-- zap = GPOINTER_TO_INT(zap_num_ptr);
--
-- purple_prpl_send_attention(session->gc, purple_buddy_get_name(buddy), zap);
--}
--
--/** Return menu, if any, for a buddy list node. */
--GList *
--msim_blist_node_menu(PurpleBlistNode *node)
--{
-- GList *menu, *zap_menu;
-- GList *types;
-- PurpleMenuAction *act;
-- guint i;
--
-- if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) {
-- /* Only know about buddies for now. */
-- return NULL;
-- }
--
-- zap_menu = NULL;
--
-- /* TODO: get rid of once is accessible directly in GUI */
-- types = msim_attention_types(NULL);
-- i = 0;
-- do
-- {
-- PurpleAttentionType *attn;
--
-- attn = (PurpleAttentionType *)types->data;
--
-- act = purple_menu_action_new(purple_attention_type_get_name(attn),
-- PURPLE_CALLBACK(msim_send_zap_from_menu), GUINT_TO_POINTER(i), NULL);
-- zap_menu = g_list_append(zap_menu, act);
--
-- ++i;
-- } while ((types = g_list_next(types)));
--
-- act = purple_menu_action_new(_("Zap"), NULL, NULL, zap_menu);
-- menu = g_list_append(NULL, act);
--
-- return menu;
--}
--
--/** Process an incoming zap. */
--gboolean
--msim_incoming_zap(MsimSession *session, MsimMessage *msg)
--{
-- gchar *msg_text, *username;
-- gint zap;
--
-- msg_text = msim_msg_get_string(msg, "msg");
-- username = msim_msg_get_string(msg, "_username");
--
-- g_return_val_if_fail(msg_text != NULL, FALSE);
-- g_return_val_if_fail(username != NULL, FALSE);
--
-- g_return_val_if_fail(sscanf(msg_text, "!!!ZAP_SEND!!!=RTE_BTN_ZAPS_%d", &zap) == 1, FALSE);
--
-- zap = CLAMP(zap, 0, 9);
--
-- purple_prpl_got_attention(session->gc, username, zap);
--
-- g_free(msg_text);
-- g_free(username);
--
-- return TRUE;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/zap.h pidgin-2.10.7-nonprism/libpurple/protocols/myspace/zap.h
---- pidgin-2.10.7/libpurple/protocols/myspace/zap.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/zap.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,28 +0,0 @@
--/* MySpaceIM Protocol Plugin - zap support
-- *
-- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _MYSPACE_ZAP_H
--#define _MYSPACE_ZAP_H
--
--GList *msim_attention_types(PurpleAccount *acct);
--gboolean msim_send_attention(PurpleConnection *gc, const gchar *username, guint code);
--GList *msim_blist_node_menu(PurpleBlistNode *node);
--gboolean msim_incoming_zap(MsimSession *session, MsimMessage *msg);
--
--#endif /* !_MYSPACE_ZAP_H */
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/novell/Makefile.am
---- pidgin-2.10.7/libpurple/protocols/novell/Makefile.am 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/Makefile.am 1969-12-31 21:00:00.000000000 -0300
-@@ -1,53 +0,0 @@
--EXTRA_DIST = \
-- Makefile.mingw
--
--pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
--
--NOVELLSOURCES = \
-- nmfield.h \
-- nmfield.c \
-- nmconn.h \
-- nmconn.c \
-- nmconference.h \
-- nmconference.c \
-- nmcontact.h \
-- nmcontact.c \
-- nmevent.h \
-- nmevent.c \
-- nmmessage.h \
-- nmmessage.c \
-- nmrequest.h \
-- nmrequest.c \
-- nmrtf.h \
-- nmrtf.c \
-- nmuser.h \
-- nmuser.c \
-- nmuserrecord.h \
-- nmuserrecord.c \
-- novell.c
--
--AM_CFLAGS = $(st)
--
--libnovell_la_LDFLAGS = -module -avoid-version
--
--if STATIC_NOVELL
--
--st = -DPURPLE_STATIC_PRPL
--noinst_LTLIBRARIES = libnovell.la
--libnovell_la_SOURCES = $(NOVELLSOURCES)
--libnovell_la_CFLAGS = $(AM_CFLAGS)
--
--else
--
--st =
--pkg_LTLIBRARIES = libnovell.la
--libnovell_la_SOURCES = $(NOVELLSOURCES)
--libnovell_la_LIBADD = $(GLIB_LIBS)
--
--endif
--
--AM_CPPFLAGS = \
-- -I$(top_srcdir)/libpurple \
-- -I$(top_builddir)/libpurple \
-- $(DEBUG_CFLAGS) \
-- $(GLIB_CFLAGS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/novell/Makefile.in
---- pidgin-2.10.7/libpurple/protocols/novell/Makefile.in 2013-02-11 07:17:21.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/Makefile.in 1969-12-31 21:00:00.000000000 -0300
-@@ -1,857 +0,0 @@
--# Makefile.in generated by automake 1.11.6 from Makefile.am.
--# @configure_input@
--
--# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
--# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
--# Foundation, Inc.
--# This Makefile.in is free software; the Free Software Foundation
--# gives unlimited permission to copy and/or distribute it,
--# with or without modifications, as long as this notice is preserved.
--
--# This program is distributed in the hope that it will be useful,
--# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
--# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
--# PARTICULAR PURPOSE.
--
--@SET_MAKE@
--
--VPATH = @srcdir@
--am__make_dryrun = \
-- { \
-- am__dry=no; \
-- case $$MAKEFLAGS in \
-- *\\[\ \ ]*) \
-- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
-- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
-- *) \
-- for am__flg in $$MAKEFLAGS; do \
-- case $$am__flg in \
-- *=*|--*) ;; \
-- *n*) am__dry=yes; break;; \
-- esac; \
-- done;; \
-- esac; \
-- test $$am__dry = yes; \
-- }
--pkgdatadir = $(datadir)/@PACKAGE@
--pkgincludedir = $(includedir)/@PACKAGE@
--pkglibdir = $(libdir)/@PACKAGE@
--pkglibexecdir = $(libexecdir)/@PACKAGE@
--am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
--install_sh_DATA = $(install_sh) -c -m 644
--install_sh_PROGRAM = $(install_sh) -c
--install_sh_SCRIPT = $(install_sh) -c
--INSTALL_HEADER = $(INSTALL_DATA)
--transform = $(program_transform_name)
--NORMAL_INSTALL = :
--PRE_INSTALL = :
--POST_INSTALL = :
--NORMAL_UNINSTALL = :
--PRE_UNINSTALL = :
--POST_UNINSTALL = :
--build_triplet = @build@
--host_triplet = @host@
--subdir = libpurple/protocols/novell
--DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
--ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
--am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
-- $(top_srcdir)/configure.ac
--am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-- $(ACLOCAL_M4)
--mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
--CONFIG_HEADER = $(top_builddir)/config.h
--CONFIG_CLEAN_FILES =
--CONFIG_CLEAN_VPATH_FILES =
--am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
--am__vpath_adj = case $$p in \
-- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
-- *) f=$$p;; \
-- esac;
--am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
--am__install_max = 40
--am__nobase_strip_setup = \
-- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
--am__nobase_strip = \
-- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
--am__nobase_list = $(am__nobase_strip_setup); \
-- for p in $$list; do echo "$$p $$p"; done | \
-- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
-- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
-- if (++n[$$2] == $(am__install_max)) \
-- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
-- END { for (dir in files) print dir, files[dir] }'
--am__base_list = \
-- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
-- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
--am__uninstall_files_from_dir = { \
-- test -z "$$files" \
-- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
-- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
-- $(am__cd) "$$dir" && rm -f $$files; }; \
-- }
--am__installdirs = "$(DESTDIR)$(pkgdir)"
--LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkg_LTLIBRARIES)
--am__DEPENDENCIES_1 =
--@STATIC_NOVELL_FALSE@libnovell_la_DEPENDENCIES = \
--@STATIC_NOVELL_FALSE@ $(am__DEPENDENCIES_1)
--am__libnovell_la_SOURCES_DIST = nmfield.h nmfield.c nmconn.h nmconn.c \
-- nmconference.h nmconference.c nmcontact.h nmcontact.c \
-- nmevent.h nmevent.c nmmessage.h nmmessage.c nmrequest.h \
-- nmrequest.c nmrtf.h nmrtf.c nmuser.h nmuser.c nmuserrecord.h \
-- nmuserrecord.c novell.c
--am__objects_1 = libnovell_la-nmfield.lo libnovell_la-nmconn.lo \
-- libnovell_la-nmconference.lo libnovell_la-nmcontact.lo \
-- libnovell_la-nmevent.lo libnovell_la-nmmessage.lo \
-- libnovell_la-nmrequest.lo libnovell_la-nmrtf.lo \
-- libnovell_la-nmuser.lo libnovell_la-nmuserrecord.lo \
-- libnovell_la-novell.lo
--@STATIC_NOVELL_FALSE@am_libnovell_la_OBJECTS = $(am__objects_1)
--@STATIC_NOVELL_TRUE@am_libnovell_la_OBJECTS = $(am__objects_1)
--libnovell_la_OBJECTS = $(am_libnovell_la_OBJECTS)
--AM_V_lt = $(am__v_lt_@AM_V@)
--am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
--am__v_lt_0 = --silent
--libnovell_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libnovell_la_CFLAGS) \
-- $(CFLAGS) $(libnovell_la_LDFLAGS) $(LDFLAGS) -o $@
--@STATIC_NOVELL_FALSE@am_libnovell_la_rpath = -rpath $(pkgdir)
--@STATIC_NOVELL_TRUE@am_libnovell_la_rpath =
--DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
--depcomp = $(SHELL) $(top_srcdir)/depcomp
--am__depfiles_maybe = depfiles
--am__mv = mv -f
--COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
--LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-- $(AM_CFLAGS) $(CFLAGS)
--AM_V_CC = $(am__v_CC_@AM_V@)
--am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
--am__v_CC_0 = @echo " CC " $@;
--AM_V_at = $(am__v_at_@AM_V@)
--am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
--am__v_at_0 = @
--CCLD = $(CC)
--LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-- $(AM_LDFLAGS) $(LDFLAGS) -o $@
--AM_V_CCLD = $(am__v_CCLD_@AM_V@)
--am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
--am__v_CCLD_0 = @echo " CCLD " $@;
--AM_V_GEN = $(am__v_GEN_@AM_V@)
--am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
--am__v_GEN_0 = @echo " GEN " $@;
--SOURCES = $(libnovell_la_SOURCES)
--DIST_SOURCES = $(am__libnovell_la_SOURCES_DIST)
--am__can_run_installinfo = \
-- case $$AM_UPDATE_INFO_DIR in \
-- n|no|NO) false;; \
-- *) (install-info --version) >/dev/null 2>&1;; \
-- esac
--ETAGS = etags
--CTAGS = ctags
--DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
--ACLOCAL = @ACLOCAL@
--ALLOCA = @ALLOCA@
--ALL_LINGUAS = @ALL_LINGUAS@
--AMTAR = @AMTAR@
--AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
--AR = @AR@
--AUTOCONF = @AUTOCONF@
--AUTOHEADER = @AUTOHEADER@
--AUTOMAKE = @AUTOMAKE@
--AVAHI_CFLAGS = @AVAHI_CFLAGS@
--AVAHI_LIBS = @AVAHI_LIBS@
--AWK = @AWK@
--CATALOGS = @CATALOGS@
--CATOBJEXT = @CATOBJEXT@
--CC = @CC@
--CCDEPMODE = @CCDEPMODE@
--CFLAGS = @CFLAGS@
--CHECK_CFLAGS = @CHECK_CFLAGS@
--CHECK_LIBS = @CHECK_LIBS@
--CPP = @CPP@
--CPPFLAGS = @CPPFLAGS@
--CYGPATH_W = @CYGPATH_W@
--DATADIRNAME = @DATADIRNAME@
--DBUS_CFLAGS = @DBUS_CFLAGS@
--DBUS_LIBS = @DBUS_LIBS@
--DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
--DEBUG_CFLAGS = @DEBUG_CFLAGS@
--DEFS = @DEFS@
--DEPDIR = @DEPDIR@
--DLLTOOL = @DLLTOOL@
--DOT = @DOT@
--DOXYGEN = @DOXYGEN@
--DSYMUTIL = @DSYMUTIL@
--DUMPBIN = @DUMPBIN@
--DYNALOADER_A = @DYNALOADER_A@
--DYNAMIC_PRPLS = @DYNAMIC_PRPLS@
--ECHO_C = @ECHO_C@
--ECHO_N = @ECHO_N@
--ECHO_T = @ECHO_T@
--EGREP = @EGREP@
--EVOLUTION_ADDRESSBOOK_CFLAGS = @EVOLUTION_ADDRESSBOOK_CFLAGS@
--EVOLUTION_ADDRESSBOOK_LIBS = @EVOLUTION_ADDRESSBOOK_LIBS@
--EXEEXT = @EXEEXT@
--FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
--FARSTREAM_LIBS = @FARSTREAM_LIBS@
--FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
--GCONFTOOL = @GCONFTOOL@
--GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
--GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
--GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
--GLIB_CFLAGS = @GLIB_CFLAGS@
--GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
--GLIB_LIBS = @GLIB_LIBS@
--GMOFILES = @GMOFILES@
--GMSGFMT = @GMSGFMT@
--GNT_CFLAGS = @GNT_CFLAGS@
--GNT_LIBS = @GNT_LIBS@
--GNT_LT_VERSION_INFO = @GNT_LT_VERSION_INFO@
--GNT_MAJOR_VERSION = @GNT_MAJOR_VERSION@
--GNT_MICRO_VERSION = @GNT_MICRO_VERSION@
--GNT_MINOR_VERSION = @GNT_MINOR_VERSION@
--GNT_VERSION = @GNT_VERSION@
--GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
--GNUTLS_LIBS = @GNUTLS_LIBS@
--GREP = @GREP@
--GSTINTERFACES_CFLAGS = @GSTINTERFACES_CFLAGS@
--GSTINTERFACES_LIBS = @GSTINTERFACES_LIBS@
--GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
--GSTREAMER_LIBS = @GSTREAMER_LIBS@
--GTKSPELL_CFLAGS = @GTKSPELL_CFLAGS@
--GTKSPELL_LIBS = @GTKSPELL_LIBS@
--GTK_CFLAGS = @GTK_CFLAGS@
--GTK_LIBS = @GTK_LIBS@
--IDN_CFLAGS = @IDN_CFLAGS@
--IDN_LIBS = @IDN_LIBS@
--INSTALL = @INSTALL@
--INSTALL_DATA = @INSTALL_DATA@
--INSTALL_PROGRAM = @INSTALL_PROGRAM@
--INSTALL_SCRIPT = @INSTALL_SCRIPT@
--INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
--INSTOBJEXT = @INSTOBJEXT@
--INTLLIBS = @INTLLIBS@
--INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
--INTLTOOL_MERGE = @INTLTOOL_MERGE@
--INTLTOOL_PERL = @INTLTOOL_PERL@
--INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
--INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
--INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
--INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
--INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
--KRB4_CFLAGS = @KRB4_CFLAGS@
--KRB4_LDFLAGS = @KRB4_LDFLAGS@
--KRB4_LIBS = @KRB4_LIBS@
--LD = @LD@
--LDADD = @LDADD@
--LDFLAGS = @LDFLAGS@
--LIBOBJS = @LIBOBJS@
--LIBPERL_A = @LIBPERL_A@
--LIBS = @LIBS@
--LIBTOOL = @LIBTOOL@
--LIBXML_CFLAGS = @LIBXML_CFLAGS@
--LIBXML_LIBS = @LIBXML_LIBS@
--LIPO = @LIPO@
--LN_S = @LN_S@
--LTLIBOBJS = @LTLIBOBJS@
--MAKEINFO = @MAKEINFO@
--MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
--MKDIR_P = @MKDIR_P@
--MKINSTALLDIRS = @MKINSTALLDIRS@
--MONO_CFLAGS = @MONO_CFLAGS@
--MONO_LIBS = @MONO_LIBS@
--MSGFMT = @MSGFMT@
--MSGFMT_OPTS = @MSGFMT_OPTS@
--MSGMERGE = @MSGMERGE@
--NETWORKMANAGER_CFLAGS = @NETWORKMANAGER_CFLAGS@
--NETWORKMANAGER_LIBS = @NETWORKMANAGER_LIBS@
--NM = @NM@
--NMEDIT = @NMEDIT@
--NSS_CFLAGS = @NSS_CFLAGS@
--NSS_LIBS = @NSS_LIBS@
--OBJDUMP = @OBJDUMP@
--OBJEXT = @OBJEXT@
--OTOOL = @OTOOL@
--OTOOL64 = @OTOOL64@
--PACKAGE = @PACKAGE@
--PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
--PACKAGE_NAME = @PACKAGE_NAME@
--PACKAGE_STRING = @PACKAGE_STRING@
--PACKAGE_TARNAME = @PACKAGE_TARNAME@
--PACKAGE_URL = @PACKAGE_URL@
--PACKAGE_VERSION = @PACKAGE_VERSION@
--PANGO_CFLAGS = @PANGO_CFLAGS@
--PANGO_LIBS = @PANGO_LIBS@
--PATH_SEPARATOR = @PATH_SEPARATOR@
--PERL = @PERL@
--PERL_CFLAGS = @PERL_CFLAGS@
--PERL_LIBS = @PERL_LIBS@
--PKG_CONFIG = @PKG_CONFIG@
--PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
--PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
--PLUGINS_DEFINE = @PLUGINS_DEFINE@
--POFILES = @POFILES@
--POSUB = @POSUB@
--PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
--PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
--PURPLE_LT_VERSION_INFO = @PURPLE_LT_VERSION_INFO@
--PURPLE_MAJOR_VERSION = @PURPLE_MAJOR_VERSION@
--PURPLE_MICRO_VERSION = @PURPLE_MICRO_VERSION@
--PURPLE_MINOR_VERSION = @PURPLE_MINOR_VERSION@
--PURPLE_VERSION = @PURPLE_VERSION@
--PYTHON = @PYTHON@
--PY_CFLAGS = @PY_CFLAGS@
--PY_LIBS = @PY_LIBS@
--RANLIB = @RANLIB@
--SASL_LIBS = @SASL_LIBS@
--SED = @SED@
--SET_MAKE = @SET_MAKE@
--SHELL = @SHELL@
--SILC_CFLAGS = @SILC_CFLAGS@
--SILC_LIBS = @SILC_LIBS@
--SM_LIBS = @SM_LIBS@
--SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
--SQLITE3_LIBS = @SQLITE3_LIBS@
--SSL_CERTIFICATES_DIR = @SSL_CERTIFICATES_DIR@
--STATIC_LINK_LIBS = @STATIC_LINK_LIBS@
--STATIC_PRPLS = @STATIC_PRPLS@
--STRIP = @STRIP@
--TCL_CFLAGS = @TCL_CFLAGS@
--TCL_LIBS = @TCL_LIBS@
--TK_LIBS = @TK_LIBS@
--USE_NLS = @USE_NLS@
--VERSION = @VERSION@
--X11_CFLAGS = @X11_CFLAGS@
--X11_LIBS = @X11_LIBS@
--XGETTEXT = @XGETTEXT@
--XMKMF = @XMKMF@
--XSLTPROC = @XSLTPROC@
--XSS_LIBS = @XSS_LIBS@
--X_CFLAGS = @X_CFLAGS@
--X_EXTRA_LIBS = @X_EXTRA_LIBS@
--X_LIBS = @X_LIBS@
--X_PRE_LIBS = @X_PRE_LIBS@
--ZEPHYR_CFLAGS = @ZEPHYR_CFLAGS@
--ZEPHYR_LDFLAGS = @ZEPHYR_LDFLAGS@
--ZEPHYR_LIBS = @ZEPHYR_LIBS@
--abs_builddir = @abs_builddir@
--abs_srcdir = @abs_srcdir@
--abs_top_builddir = @abs_top_builddir@
--abs_top_srcdir = @abs_top_srcdir@
--ac_ct_AR = @ac_ct_AR@
--ac_ct_CC = @ac_ct_CC@
--ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
--am__include = @am__include@
--am__leading_dot = @am__leading_dot@
--am__quote = @am__quote@
--am__tar = @am__tar@
--am__untar = @am__untar@
--bindir = @bindir@
--build = @build@
--build_alias = @build_alias@
--build_cpu = @build_cpu@
--build_os = @build_os@
--build_vendor = @build_vendor@
--builddir = @builddir@
--datadir = @datadir@
--datarootdir = @datarootdir@
--docdir = @docdir@
--dvidir = @dvidir@
--enable_dbus = @enable_dbus@
--enable_devhelp = @enable_devhelp@
--enable_dot = @enable_dot@
--enable_doxygen = @enable_doxygen@
--exec_prefix = @exec_prefix@
--host = @host@
--host_alias = @host_alias@
--host_cpu = @host_cpu@
--host_os = @host_os@
--host_vendor = @host_vendor@
--htmldir = @htmldir@
--includedir = @includedir@
--infodir = @infodir@
--install_sh = @install_sh@
--intltool__v_merge_options_ = @intltool__v_merge_options_@
--intltool__v_merge_options_0 = @intltool__v_merge_options_0@
--libdir = @libdir@
--libexecdir = @libexecdir@
--localedir = @localedir@
--localstatedir = @localstatedir@
--mandir = @mandir@
--mkdir_p = @mkdir_p@
--oldincludedir = @oldincludedir@
--pdfdir = @pdfdir@
--perlpath = @perlpath@
--pidginpath = @pidginpath@
--prefix = @prefix@
--program_transform_name = @program_transform_name@
--psdir = @psdir@
--sbindir = @sbindir@
--sedpath = @sedpath@
--sharedstatedir = @sharedstatedir@
--srcdir = @srcdir@
--sysconfdir = @sysconfdir@
--target_alias = @target_alias@
--top_build_prefix = @top_build_prefix@
--top_builddir = @top_builddir@
--top_srcdir = @top_srcdir@
--EXTRA_DIST = \
-- Makefile.mingw
--
--pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
--NOVELLSOURCES = \
-- nmfield.h \
-- nmfield.c \
-- nmconn.h \
-- nmconn.c \
-- nmconference.h \
-- nmconference.c \
-- nmcontact.h \
-- nmcontact.c \
-- nmevent.h \
-- nmevent.c \
-- nmmessage.h \
-- nmmessage.c \
-- nmrequest.h \
-- nmrequest.c \
-- nmrtf.h \
-- nmrtf.c \
-- nmuser.h \
-- nmuser.c \
-- nmuserrecord.h \
-- nmuserrecord.c \
-- novell.c
--
--AM_CFLAGS = $(st)
--libnovell_la_LDFLAGS = -module -avoid-version
--@STATIC_NOVELL_FALSE@st =
--@STATIC_NOVELL_TRUE@st = -DPURPLE_STATIC_PRPL
--@STATIC_NOVELL_TRUE@noinst_LTLIBRARIES = libnovell.la
--@STATIC_NOVELL_FALSE@libnovell_la_SOURCES = $(NOVELLSOURCES)
--@STATIC_NOVELL_TRUE@libnovell_la_SOURCES = $(NOVELLSOURCES)
--@STATIC_NOVELL_TRUE@libnovell_la_CFLAGS = $(AM_CFLAGS)
--@STATIC_NOVELL_FALSE@pkg_LTLIBRARIES = libnovell.la
--@STATIC_NOVELL_FALSE@libnovell_la_LIBADD = $(GLIB_LIBS)
--AM_CPPFLAGS = \
-- -I$(top_srcdir)/libpurple \
-- -I$(top_builddir)/libpurple \
-- $(DEBUG_CFLAGS) \
-- $(GLIB_CFLAGS)
--
--all: all-am
--
--.SUFFIXES:
--.SUFFIXES: .c .lo .o .obj
--$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
-- @for dep in $?; do \
-- case '$(am__configure_deps)' in \
-- *$$dep*) \
-- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
-- && { if test -f $@; then exit 0; else break; fi; }; \
-- exit 1;; \
-- esac; \
-- done; \
-- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpurple/protocols/novell/Makefile'; \
-- $(am__cd) $(top_srcdir) && \
-- $(AUTOMAKE) --gnu libpurple/protocols/novell/Makefile
--.PRECIOUS: Makefile
--Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-- @case '$?' in \
-- *config.status*) \
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-- *) \
-- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-- esac;
--
--$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--
--$(top_srcdir)/configure: $(am__configure_deps)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--$(ACLOCAL_M4): $(am__aclocal_m4_deps)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--$(am__aclocal_m4_deps):
--
--clean-noinstLTLIBRARIES:
-- -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-- @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
-- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-- test "$$dir" != "$$p" || dir=.; \
-- echo "rm -f \"$${dir}/so_locations\""; \
-- rm -f "$${dir}/so_locations"; \
-- done
--install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES)
-- @$(NORMAL_INSTALL)
-- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
-- list2=; for p in $$list; do \
-- if test -f $$p; then \
-- list2="$$list2 $$p"; \
-- else :; fi; \
-- done; \
-- test -z "$$list2" || { \
-- echo " $(MKDIR_P) '$(DESTDIR)$(pkgdir)'"; \
-- $(MKDIR_P) "$(DESTDIR)$(pkgdir)" || exit 1; \
-- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgdir)'"; \
-- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgdir)"; \
-- }
--
--uninstall-pkgLTLIBRARIES:
-- @$(NORMAL_UNINSTALL)
-- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
-- for p in $$list; do \
-- $(am__strip_dir) \
-- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgdir)/$$f'"; \
-- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgdir)/$$f"; \
-- done
--
--clean-pkgLTLIBRARIES:
-- -test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES)
-- @list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
-- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-- test "$$dir" != "$$p" || dir=.; \
-- echo "rm -f \"$${dir}/so_locations\""; \
-- rm -f "$${dir}/so_locations"; \
-- done
--libnovell.la: $(libnovell_la_OBJECTS) $(libnovell_la_DEPENDENCIES) $(EXTRA_libnovell_la_DEPENDENCIES)
-- $(AM_V_CCLD)$(libnovell_la_LINK) $(am_libnovell_la_rpath) $(libnovell_la_OBJECTS) $(libnovell_la_LIBADD) $(LIBS)
--
--mostlyclean-compile:
-- -rm -f *.$(OBJEXT)
--
--distclean-compile:
-- -rm -f *.tab.c
--
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmconference.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmconn.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmcontact.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmevent.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmfield.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmmessage.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmrequest.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmrtf.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmuser.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmuserrecord.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-novell.Plo@am__quote@
--
--.c.o:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
--
--.c.obj:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
--
--.c.lo:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
--
--libnovell_la-nmfield.lo: nmfield.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmfield.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmfield.Tpo -c -o libnovell_la-nmfield.lo `test -f 'nmfield.c' || echo '$(srcdir)/'`nmfield.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmfield.Tpo $(DEPDIR)/libnovell_la-nmfield.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmfield.c' object='libnovell_la-nmfield.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmfield.lo `test -f 'nmfield.c' || echo '$(srcdir)/'`nmfield.c
--
--libnovell_la-nmconn.lo: nmconn.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmconn.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmconn.Tpo -c -o libnovell_la-nmconn.lo `test -f 'nmconn.c' || echo '$(srcdir)/'`nmconn.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmconn.Tpo $(DEPDIR)/libnovell_la-nmconn.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmconn.c' object='libnovell_la-nmconn.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmconn.lo `test -f 'nmconn.c' || echo '$(srcdir)/'`nmconn.c
--
--libnovell_la-nmconference.lo: nmconference.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmconference.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmconference.Tpo -c -o libnovell_la-nmconference.lo `test -f 'nmconference.c' || echo '$(srcdir)/'`nmconference.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmconference.Tpo $(DEPDIR)/libnovell_la-nmconference.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmconference.c' object='libnovell_la-nmconference.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmconference.lo `test -f 'nmconference.c' || echo '$(srcdir)/'`nmconference.c
--
--libnovell_la-nmcontact.lo: nmcontact.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmcontact.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmcontact.Tpo -c -o libnovell_la-nmcontact.lo `test -f 'nmcontact.c' || echo '$(srcdir)/'`nmcontact.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmcontact.Tpo $(DEPDIR)/libnovell_la-nmcontact.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmcontact.c' object='libnovell_la-nmcontact.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmcontact.lo `test -f 'nmcontact.c' || echo '$(srcdir)/'`nmcontact.c
--
--libnovell_la-nmevent.lo: nmevent.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmevent.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmevent.Tpo -c -o libnovell_la-nmevent.lo `test -f 'nmevent.c' || echo '$(srcdir)/'`nmevent.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmevent.Tpo $(DEPDIR)/libnovell_la-nmevent.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmevent.c' object='libnovell_la-nmevent.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmevent.lo `test -f 'nmevent.c' || echo '$(srcdir)/'`nmevent.c
--
--libnovell_la-nmmessage.lo: nmmessage.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmmessage.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmmessage.Tpo -c -o libnovell_la-nmmessage.lo `test -f 'nmmessage.c' || echo '$(srcdir)/'`nmmessage.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmmessage.Tpo $(DEPDIR)/libnovell_la-nmmessage.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmmessage.c' object='libnovell_la-nmmessage.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmmessage.lo `test -f 'nmmessage.c' || echo '$(srcdir)/'`nmmessage.c
--
--libnovell_la-nmrequest.lo: nmrequest.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmrequest.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmrequest.Tpo -c -o libnovell_la-nmrequest.lo `test -f 'nmrequest.c' || echo '$(srcdir)/'`nmrequest.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmrequest.Tpo $(DEPDIR)/libnovell_la-nmrequest.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmrequest.c' object='libnovell_la-nmrequest.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmrequest.lo `test -f 'nmrequest.c' || echo '$(srcdir)/'`nmrequest.c
--
--libnovell_la-nmrtf.lo: nmrtf.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmrtf.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmrtf.Tpo -c -o libnovell_la-nmrtf.lo `test -f 'nmrtf.c' || echo '$(srcdir)/'`nmrtf.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmrtf.Tpo $(DEPDIR)/libnovell_la-nmrtf.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmrtf.c' object='libnovell_la-nmrtf.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmrtf.lo `test -f 'nmrtf.c' || echo '$(srcdir)/'`nmrtf.c
--
--libnovell_la-nmuser.lo: nmuser.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmuser.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmuser.Tpo -c -o libnovell_la-nmuser.lo `test -f 'nmuser.c' || echo '$(srcdir)/'`nmuser.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmuser.Tpo $(DEPDIR)/libnovell_la-nmuser.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmuser.c' object='libnovell_la-nmuser.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmuser.lo `test -f 'nmuser.c' || echo '$(srcdir)/'`nmuser.c
--
--libnovell_la-nmuserrecord.lo: nmuserrecord.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmuserrecord.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmuserrecord.Tpo -c -o libnovell_la-nmuserrecord.lo `test -f 'nmuserrecord.c' || echo '$(srcdir)/'`nmuserrecord.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmuserrecord.Tpo $(DEPDIR)/libnovell_la-nmuserrecord.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmuserrecord.c' object='libnovell_la-nmuserrecord.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmuserrecord.lo `test -f 'nmuserrecord.c' || echo '$(srcdir)/'`nmuserrecord.c
--
--libnovell_la-novell.lo: novell.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-novell.lo -MD -MP -MF $(DEPDIR)/libnovell_la-novell.Tpo -c -o libnovell_la-novell.lo `test -f 'novell.c' || echo '$(srcdir)/'`novell.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-novell.Tpo $(DEPDIR)/libnovell_la-novell.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='novell.c' object='libnovell_la-novell.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-novell.lo `test -f 'novell.c' || echo '$(srcdir)/'`novell.c
--
--mostlyclean-libtool:
-- -rm -f *.lo
--
--clean-libtool:
-- -rm -rf .libs _libs
--
--ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- mkid -fID $$unique
--tags: TAGS
--
--TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
-- $(TAGS_FILES) $(LISP)
-- set x; \
-- here=`pwd`; \
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- shift; \
-- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-- test -n "$$unique" || unique=$$empty_fix; \
-- if test $$# -gt 0; then \
-- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-- "$$@" $$unique; \
-- else \
-- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-- $$unique; \
-- fi; \
-- fi
--ctags: CTAGS
--CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
-- $(TAGS_FILES) $(LISP)
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- test -z "$(CTAGS_ARGS)$$unique" \
-- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-- $$unique
--
--GTAGS:
-- here=`$(am__cd) $(top_builddir) && pwd` \
-- && $(am__cd) $(top_srcdir) \
-- && gtags -i $(GTAGS_ARGS) "$$here"
--
--distclean-tags:
-- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
--
--distdir: $(DISTFILES)
-- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-- list='$(DISTFILES)'; \
-- dist_files=`for file in $$list; do echo $$file; done | \
-- sed -e "s|^$$srcdirstrip/||;t" \
-- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-- case $$dist_files in \
-- */*) $(MKDIR_P) `echo "$$dist_files" | \
-- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-- sort -u` ;; \
-- esac; \
-- for file in $$dist_files; do \
-- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-- if test -d $$d/$$file; then \
-- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-- if test -d "$(distdir)/$$file"; then \
-- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-- fi; \
-- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-- fi; \
-- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-- else \
-- test -f "$(distdir)/$$file" \
-- || cp -p $$d/$$file "$(distdir)/$$file" \
-- || exit 1; \
-- fi; \
-- done
--check-am: all-am
--check: check-am
--all-am: Makefile $(LTLIBRARIES)
--installdirs:
-- for dir in "$(DESTDIR)$(pkgdir)"; do \
-- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
-- done
--install: install-am
--install-exec: install-exec-am
--install-data: install-data-am
--uninstall: uninstall-am
--
--install-am: all-am
-- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
--
--installcheck: installcheck-am
--install-strip:
-- if test -z '$(STRIP)'; then \
-- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-- install; \
-- else \
-- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-- fi
--mostlyclean-generic:
--
--clean-generic:
--
--distclean-generic:
-- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
--
--maintainer-clean-generic:
-- @echo "This command is intended for maintainers to use"
-- @echo "it deletes files that may require special tools to rebuild."
--clean: clean-am
--
--clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
-- clean-pkgLTLIBRARIES mostlyclean-am
--
--distclean: distclean-am
-- -rm -rf ./$(DEPDIR)
-- -rm -f Makefile
--distclean-am: clean-am distclean-compile distclean-generic \
-- distclean-tags
--
--dvi: dvi-am
--
--dvi-am:
--
--html: html-am
--
--html-am:
--
--info: info-am
--
--info-am:
--
--install-data-am: install-pkgLTLIBRARIES
--
--install-dvi: install-dvi-am
--
--install-dvi-am:
--
--install-exec-am:
--
--install-html: install-html-am
--
--install-html-am:
--
--install-info: install-info-am
--
--install-info-am:
--
--install-man:
--
--install-pdf: install-pdf-am
--
--install-pdf-am:
--
--install-ps: install-ps-am
--
--install-ps-am:
--
--installcheck-am:
--
--maintainer-clean: maintainer-clean-am
-- -rm -rf ./$(DEPDIR)
-- -rm -f Makefile
--maintainer-clean-am: distclean-am maintainer-clean-generic
--
--mostlyclean: mostlyclean-am
--
--mostlyclean-am: mostlyclean-compile mostlyclean-generic \
-- mostlyclean-libtool
--
--pdf: pdf-am
--
--pdf-am:
--
--ps: ps-am
--
--ps-am:
--
--uninstall-am: uninstall-pkgLTLIBRARIES
--
--.MAKE: install-am install-strip
--
--.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
-- clean-libtool clean-noinstLTLIBRARIES clean-pkgLTLIBRARIES \
-- ctags distclean distclean-compile distclean-generic \
-- distclean-libtool distclean-tags distdir dvi dvi-am html \
-- html-am info info-am install install-am install-data \
-- install-data-am install-dvi install-dvi-am install-exec \
-- install-exec-am install-html install-html-am install-info \
-- install-info-am install-man install-pdf install-pdf-am \
-- install-pkgLTLIBRARIES install-ps install-ps-am install-strip \
-- installcheck installcheck-am installdirs maintainer-clean \
-- maintainer-clean-generic mostlyclean mostlyclean-compile \
-- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-- tags uninstall uninstall-am uninstall-pkgLTLIBRARIES
--
--
--# Tell versions [3.59,3.63) of GNU make to not export all variables.
--# Otherwise a system limit (for SysV at least) may be exceeded.
--.NOEXPORT:
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/novell/Makefile.mingw
---- pidgin-2.10.7/libpurple/protocols/novell/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,88 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of libnovell
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = libnovell
--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)
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = \
-- nmfield.c \
-- nmconn.c \
-- nmconference.c \
-- nmcontact.c \
-- nmevent.c \
-- nmmessage.c \
-- nmrequest.c \
-- nmrtf.c \
-- nmuser.c \
-- nmuserrecord.c \
-- novell.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lws2_32 \
-- -lintl \
-- -lpurple
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll
--
--install: all $(DLL_INSTALL_DIR)
-- cp $(TARGET).dll $(DLL_INSTALL_DIR)
--
--$(OBJECTS): $(PURPLE_CONFIG_H)
--
--$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -f $(OBJECTS)
-- rm -f $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmconference.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmconference.c
---- pidgin-2.10.7/libpurple/protocols/novell/nmconference.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmconference.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,232 +0,0 @@
--/*
-- * nmconference.c
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include <string.h>
--#include "nmconference.h"
--
--static int conf_count = 0;
--
--struct _NMConference
--{
--
-- /* The conference identifier */
-- char *guid;
--
-- /* The list of participants for the conference */
-- GSList *participants;
--
-- /* Flags for the conference */
-- guint32 flags;
--
-- /* User defined data */
-- gpointer data;
--
-- /* Reference count for this object */
-- int ref_count;
--
--};
--
--
--/*******************************************************************************
-- * Conference API -- see header file for comments
-- ******************************************************************************/
--
--NMConference *
--nm_create_conference(const char *guid)
--{
-- NMConference *conf = g_new0(NMConference, 1);
--
-- if (guid) {
-- conf->guid = g_strdup(guid);
-- } else {
-- conf->guid = g_strdup(BLANK_GUID);
-- }
-- conf->ref_count = 1;
--
-- purple_debug(PURPLE_DEBUG_INFO, "novell",
-- "Creating a conference %p, total=%d\n",
-- conf, conf_count++);
--
-- return conf;
--}
--
--void
--nm_release_conference(NMConference * conference)
--{
-- GSList *node;
--
-- g_return_if_fail(conference != NULL);
--
-- purple_debug(PURPLE_DEBUG_INFO, "novell",
-- "In release conference %p, refs=%d\n",
-- conference, conference->ref_count);
-- if (--conference->ref_count == 0) {
--
-- purple_debug(PURPLE_DEBUG_INFO, "novell",
-- "Releasing conference %p, total=%d\n",
-- conference, --conf_count);
--
-- if (conference->guid)
-- g_free(conference->guid);
--
-- if (conference->participants) {
-- for (node = conference->participants; node; node = node->next) {
-- if (node->data) {
-- NMUserRecord *user_record = node->data;
--
-- nm_release_user_record(user_record);
-- node->data = NULL;
-- }
-- }
--
-- g_slist_free(conference->participants);
-- }
--
-- g_free(conference);
-- }
--}
--
--gboolean
--nm_conference_is_instantiated(NMConference * conference)
--{
-- if (conference == NULL)
-- return FALSE;
--
-- return (strncmp(conference->guid, BLANK_GUID, CONF_GUID_END) != 0);
--}
--
--int
--nm_conference_get_participant_count(NMConference * conference)
--{
-- if (conference == NULL)
-- return 0;
--
-- return g_slist_length(conference->participants);
--}
--
--NMUserRecord *
--nm_conference_get_participant(NMConference * conference, int index)
--{
-- if (conference == NULL)
-- return NULL;
--
-- return (NMUserRecord *) g_slist_nth_data(conference->participants, index);
--}
--
--void
--nm_conference_add_participant(NMConference * conference,
-- NMUserRecord * user_record)
--{
-- if (conference == NULL || user_record == NULL) {
-- return;
-- }
--
-- nm_user_record_add_ref(user_record);
-- conference->participants = g_slist_append(conference->participants, user_record);
--}
--
--void
--nm_conference_remove_participant(NMConference * conference, const char *dn)
--{
-- GSList *node, *element = NULL;
--
-- if (conference == NULL || dn == NULL) {
-- return;
-- }
--
-- for (node = conference->participants; node; node = node->next) {
-- NMUserRecord *user_record = node->data;
--
-- if (user_record) {
-- if (nm_utf8_str_equal(dn, nm_user_record_get_dn(user_record))) {
-- element = node;
-- break;
-- }
-- }
-- }
--
-- if (element) {
-- nm_release_user_record((NMUserRecord *) element->data);
-- element->data = NULL;
-- conference->participants =
-- g_slist_remove_link(conference->participants, element);
-- g_slist_free_1(element);
-- }
--}
--
--void
--nm_conference_add_ref(NMConference * conference)
--{
-- if (conference)
-- conference->ref_count++;
--}
--
--void
--nm_conference_set_flags(NMConference * conference, guint32 flags)
--{
-- if (conference) {
-- conference->flags = flags;
-- }
--}
--
--void
--nm_conference_set_guid(NMConference * conference, const char *guid)
--{
-- if (conference) {
--
-- /* Release memory for old guid */
-- if (conference->guid) {
-- g_free(conference->guid);
-- }
--
-- /* Set the new guid */
-- if (guid)
-- conference->guid = g_strdup(guid);
-- else
-- conference->guid = g_strdup(BLANK_GUID);
-- }
--}
--
--void
--nm_conference_set_data(NMConference * conference, gpointer data)
--{
-- if (conference == NULL)
-- return;
--
-- conference->data = data;
--}
--
--gpointer
--nm_conference_get_data(NMConference * conference)
--{
-- if (conference == NULL)
-- return NULL;
--
-- return conference->data;
--}
--
--const char *
--nm_conference_get_guid(NMConference * conference)
--{
-- if (conference == NULL)
-- return NULL;
--
-- return conference->guid;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmconference.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmconference.h
---- pidgin-2.10.7/libpurple/protocols/novell/nmconference.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmconference.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,167 +0,0 @@
--/*
-- * nmconference.h
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#ifndef __NM_CONFERENCE_H__
--#define __NM_CONFERENCE_H__
--
--typedef struct _NMConference NMConference;
--
--#include "nmuserrecord.h"
--
--/* A blank GUID -- represents an uninstatiated conference */
--#define BLANK_GUID "[00000000-00000000-00000000-0000-0000]"
--
--/* This is how much of the conference GUIDs to compare when testing
-- * to see if two conferences are the same. We cannot compare the
-- * entire GUID because the last part is the session count.
-- */
--#define CONF_GUID_END 27
--
--/**
-- * Creates an conference object.
-- *
-- * The conference should be released by calling
-- * nm_release_conference
-- *
-- * @param guid The GUID for the conference.
-- *
-- * @return The new NMConference
-- */
--NMConference *nm_create_conference(const char *guid);
--
--/**
-- * Increments the reference count for the conference.
-- *
-- * The reference to the conference should be released
-- * by calling nm_release_conference
-- *
-- * @param conference The conference to reference
-- */
--void nm_conference_add_ref(NMConference * conference);
--
--/**
-- * Releases the resources associated with the conference
-- * if there are no more references to it, otherwise just
-- * decrements the reference count.
-- *
-- * @param conf The conference to release
-- *
-- */
--void nm_release_conference(NMConference * conf);
--
--/**
-- * Set the GUID for the conference.
-- *
-- * @param conference The conference
-- * @param guid The new conference GUID
-- *
-- */
--void nm_conference_set_guid(NMConference * conference, const char *guid);
--
--/**
-- * Return the GUID for the conference.
-- *
-- * @param conference The conference
-- *
-- * @return The GUID for the conference
-- */
--const char *nm_conference_get_guid(NMConference * conference);
--
--/**
-- * Add a participant to the conference.
-- *
-- * @param conference The conference
-- * @param user_record The user record to add as a participant
-- *
-- * @return
-- */
--void nm_conference_add_participant(NMConference * conference,
-- NMUserRecord * user_record);
--
--/**
-- * Remove a participant to the conference.
-- *
-- * @param conference The conference
-- * @param dn The dn of the participant to remove
-- *
-- */
--void nm_conference_remove_participant(NMConference * conference, const char *dn);
--
--/**
-- * Return the total number of participants in the conference.
-- *
-- * @param conference The conference
-- *
-- * @return The number of participants for the conference
-- *
-- */
--int nm_conference_get_participant_count(NMConference * conference);
--
--/**
-- * Return a participant given an index.
-- *
-- * @param conference The conference
-- * @param index The index of the participant to get
-- *
-- * @return The participant or NULL if the index is out of range.
-- *
-- */
--NMUserRecord *nm_conference_get_participant(NMConference * conference, int index);
--
--/**
-- * Check to see if the conference has been instantiated
-- *
-- * @param conference The conference
-- *
-- * @return TRUE if the conference has been instantiated,
-- * FALSE otherwise.
-- *
-- */
--gboolean nm_conference_is_instantiated(NMConference * conf);
--
--/**
-- * Set the flags for the conference.
-- *
-- * @param conference The conference
-- * @param flags The conference flags.
-- *
-- */
--void nm_conference_set_flags(NMConference * conference, guint32 flags);
--
--/**
-- * Set the user defined data for the conference.
-- *
-- * @param conference The conference
-- * @param data User defined data
-- *
-- */
--void nm_conference_set_data(NMConference * conference, gpointer data);
--
--/**
-- * Get the user defined data for the conference.
-- *
-- * @param conference The conference
-- *
-- * @return The data if it has been set, NULL otherwise.
-- *
-- */
--gpointer nm_conference_get_data(NMConference * conference);
--
--#endif
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmconn.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmconn.c
---- pidgin-2.10.7/libpurple/protocols/novell/nmconn.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmconn.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,701 +0,0 @@
--/*
-- * nmconn.c
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include <glib.h>
--#include <unistd.h>
--#include <errno.h>
--#include <string.h>
--#include <ctype.h>
--#include <time.h>
--#include "nmconn.h"
--
--#ifdef _WIN32
--#include <windows.h>
--#endif
--
--#define NO_ESCAPE(ch) ((ch == 0x20) || (ch >= 0x30 && ch <= 0x39) || \
-- (ch >= 0x41 && ch <= 0x5a) || (ch >= 0x61 && ch <= 0x7a))
--
--/* Read data from conn until the end of a line */
--static NMERR_T
--read_line(NMConn * conn, char *buff, int len)
--{
-- NMERR_T rc = NM_OK;
-- int total_bytes = 0;
--
-- while ((rc == NM_OK) && (total_bytes < (len - 1))) {
-- rc = nm_read_all(conn, &buff[total_bytes], 1);
-- if (rc == NM_OK) {
-- total_bytes += 1;
-- if (buff[total_bytes - 1] == '\n') {
-- break;
-- }
-- }
-- }
-- buff[total_bytes] = '\0';
--
-- return rc;
--}
--
--static char *
--url_escape_string(char *src)
--{
-- guint32 escape = 0;
-- char *p;
-- char *q;
-- char *encoded = NULL;
-- int ch;
--
-- static const char hex_table[16] = "0123456789abcdef";
--
-- if (src == NULL) {
-- return NULL;
-- }
--
-- /* Find number of chars to escape */
-- for (p = src; *p != '\0'; p++) {
-- ch = (guchar) *p;
-- if (!NO_ESCAPE(ch)) {
-- escape++;
-- }
-- }
--
-- encoded = g_malloc((p - src) + (escape * 2) + 1);
--
-- /* Escape the string */
-- for (p = src, q = encoded; *p != '\0'; p++) {
-- ch = (guchar) * p;
-- if (NO_ESCAPE(ch)) {
-- if (ch != 0x20) {
-- *q = ch;
-- q++;
-- } else {
-- *q = '+';
-- q++;
-- }
-- } else {
-- *q = '%';
-- q++;
--
-- *q = hex_table[ch >> 4];
-- q++;
--
-- *q = hex_table[ch & 15];
-- q++;
-- }
-- }
-- *q = '\0';
--
-- return encoded;
--}
--
--static char *
--encode_method(guint8 method)
--{
-- char *str;
--
-- switch (method) {
-- case NMFIELD_METHOD_EQUAL:
-- str = "G";
-- break;
-- case NMFIELD_METHOD_UPDATE:
-- str = "F";
-- break;
-- case NMFIELD_METHOD_GTE:
-- str = "E";
-- break;
-- case NMFIELD_METHOD_LTE:
-- str = "D";
-- break;
-- case NMFIELD_METHOD_NE:
-- str = "C";
-- break;
-- case NMFIELD_METHOD_EXIST:
-- str = "B";
-- break;
-- case NMFIELD_METHOD_NOTEXIST:
-- str = "A";
-- break;
-- case NMFIELD_METHOD_SEARCH:
-- str = "9";
-- break;
-- case NMFIELD_METHOD_MATCHBEGIN:
-- str = "8";
-- break;
-- case NMFIELD_METHOD_MATCHEND:
-- str = "7";
-- break;
-- case NMFIELD_METHOD_NOT_ARRAY:
-- str = "6";
-- break;
-- case NMFIELD_METHOD_OR_ARRAY:
-- str = "5";
-- break;
-- case NMFIELD_METHOD_AND_ARRAY:
-- str = "4";
-- break;
-- case NMFIELD_METHOD_DELETE_ALL:
-- str = "3";
-- break;
-- case NMFIELD_METHOD_DELETE:
-- str = "2";
-- break;
-- case NMFIELD_METHOD_ADD:
-- str = "1";
-- break;
-- default: /* NMFIELD_METHOD_VALID */
-- str = "0";
-- break;
-- }
--
-- return str;
--}
--
--NMConn *
--nm_create_conn(const char *addr, int port)
--{
-- NMConn *conn = g_new0(NMConn, 1);
-- conn->addr = g_strdup(addr);
-- conn->port = port;
-- return conn;
--}
--
--void nm_release_conn(NMConn *conn)
--{
-- if (conn) {
-- GSList *node;
-- for (node = conn->requests; node; node = node->next) {
-- if (node->data)
-- nm_release_request(node->data);
-- }
-- g_slist_free(conn->requests);
-- conn->requests = NULL;
-- if (conn->ssl_conn) {
-- g_free(conn->ssl_conn);
-- conn->ssl_conn = NULL;
-- }
-- g_free(conn->addr);
-- conn->addr = NULL;
-- g_free(conn);
-- }
--}
--
--int
--nm_tcp_write(NMConn * conn, const void *buff, int len)
--{
-- if (conn == NULL || buff == NULL)
-- return -1;
--
-- if (!conn->use_ssl)
-- return (write(conn->fd, buff, len));
-- else if (conn->ssl_conn && conn->ssl_conn->write)
-- return (conn->ssl_conn->write(conn->ssl_conn->data, buff, len));
-- else
-- return -1;
--}
--
--int
--nm_tcp_read(NMConn * conn, void *buff, int len)
--{
-- if (conn == NULL || buff == NULL)
-- return -1;
--
-- if (!conn->use_ssl)
-- return (read(conn->fd, buff, len));
-- else if (conn->ssl_conn && conn->ssl_conn->read)
-- return ((conn->ssl_conn->read)(conn->ssl_conn->data, buff, len));
-- else
-- return -1;
--}
--
--NMERR_T
--nm_read_all(NMConn * conn, char *buff, int len)
--{
-- NMERR_T rc = NM_OK;
-- int bytes_left = len;
-- int bytes_read;
-- int total_bytes = 0;
-- int retry = 1000;
--
-- if (conn == NULL || buff == NULL)
-- return NMERR_BAD_PARM;
--
-- /* Keep reading until buffer is full */
-- while (bytes_left) {
-- bytes_read = nm_tcp_read(conn, &buff[total_bytes], bytes_left);
-- if (bytes_read > 0) {
-- bytes_left -= bytes_read;
-- total_bytes += bytes_read;
-- } else {
-- if (errno == EAGAIN) {
-- if (--retry == 0) {
-- rc = NMERR_TCP_READ;
-- break;
-- }
--#ifdef _WIN32
-- Sleep(1);
--#else
-- usleep(1000);
--#endif
-- } else {
-- rc = NMERR_TCP_READ;
-- break;
-- }
-- }
-- }
-- return rc;
--}
--
--NMERR_T
--nm_read_uint32(NMConn *conn, guint32 *val)
--{
-- NMERR_T rc = NM_OK;
--
-- rc = nm_read_all(conn, (char *)val, sizeof(*val));
-- if (rc == NM_OK) {
-- *val = GUINT32_FROM_LE(*val);
-- }
--
-- return rc;
--}
--
--NMERR_T
--nm_read_uint16(NMConn *conn, guint16 *val)
--{
-- NMERR_T rc = NM_OK;
--
-- rc = nm_read_all(conn, (char *)val, sizeof(*val));
-- if (rc == NM_OK) {
-- *val = GUINT16_FROM_LE(*val);
-- }
--
-- return rc;
--}
--
--NMERR_T
--nm_write_fields(NMConn * conn, NMField * fields)
--{
-- NMERR_T rc = NM_OK;
-- NMField *field;
-- char *value = NULL;
-- char *method = NULL;
-- char buffer[4096];
-- int ret;
-- int bytes_to_send;
-- int val = 0;
--
-- if (conn == NULL || fields == NULL) {
-- return NMERR_BAD_PARM;
-- }
--
-- /* Format each field as valid "post" data and write it out */
-- for (field = fields; (rc == NM_OK) && (field->tag); field++) {
--
-- /* We don't currently handle binary types */
-- if (field->method == NMFIELD_METHOD_IGNORE ||
-- field->type == NMFIELD_TYPE_BINARY) {
-- continue;
-- }
--
-- /* Write the field tag */
-- bytes_to_send = g_snprintf(buffer, sizeof(buffer), "&tag=%s", field->tag);
-- ret = nm_tcp_write(conn, buffer, bytes_to_send);
-- if (ret < 0) {
-- rc = NMERR_TCP_WRITE;
-- }
--
-- /* Write the field method */
-- if (rc == NM_OK) {
-- method = encode_method(field->method);
-- bytes_to_send = g_snprintf(buffer, sizeof(buffer), "&cmd=%s", method);
-- ret = nm_tcp_write(conn, buffer, bytes_to_send);
-- if (ret < 0) {
-- rc = NMERR_TCP_WRITE;
-- }
-- }
--
-- /* Write the field value */
-- if (rc == NM_OK) {
-- switch (field->type) {
-- case NMFIELD_TYPE_UTF8:
-- case NMFIELD_TYPE_DN:
--
-- value = url_escape_string((char *) field->ptr_value);
-- bytes_to_send = g_snprintf(buffer, sizeof(buffer),
-- "&val=%s", value);
-- if (bytes_to_send > (int)sizeof(buffer)) {
-- ret = nm_tcp_write(conn, buffer, sizeof(buffer));
-- } else {
-- ret = nm_tcp_write(conn, buffer, bytes_to_send);
-- }
--
-- if (ret < 0) {
-- rc = NMERR_TCP_WRITE;
-- }
--
-- g_free(value);
--
-- break;
--
-- case NMFIELD_TYPE_ARRAY:
-- case NMFIELD_TYPE_MV:
--
-- val = nm_count_fields((NMField *) field->ptr_value);
-- bytes_to_send = g_snprintf(buffer, sizeof(buffer),
-- "&val=%u", val);
-- ret = nm_tcp_write(conn, buffer, bytes_to_send);
-- if (ret < 0) {
-- rc = NMERR_TCP_WRITE;
-- }
--
-- break;
--
-- default:
--
-- bytes_to_send = g_snprintf(buffer, sizeof(buffer),
-- "&val=%u", field->value);
-- ret = nm_tcp_write(conn, buffer, bytes_to_send);
-- if (ret < 0) {
-- rc = NMERR_TCP_WRITE;
-- }
--
-- break;
-- }
-- }
--
-- /* Write the field type */
-- if (rc == NM_OK) {
-- bytes_to_send = g_snprintf(buffer, sizeof(buffer),
-- "&type=%u", field->type);
-- ret = nm_tcp_write(conn, buffer, bytes_to_send);
-- if (ret < 0) {
-- rc = NMERR_TCP_WRITE;
-- }
-- }
--
-- /* If the field is a sub array then post its fields */
-- if (rc == NM_OK && val > 0) {
-- if (field->type == NMFIELD_TYPE_ARRAY ||
-- field->type == NMFIELD_TYPE_MV) {
--
-- rc = nm_write_fields(conn, (NMField *) field->ptr_value);
--
-- }
-- }
-- }
--
-- return rc;
--}
--
--NMERR_T
--nm_send_request(NMConn *conn, char *cmd, NMField *fields,
-- nm_response_cb cb, gpointer data, NMRequest **request)
--{
-- NMERR_T rc = NM_OK;
-- char buffer[512];
-- int bytes_to_send;
-- int ret;
-- NMField *request_fields = NULL;
-- char *str = NULL;
--
-- if (conn == NULL || cmd == NULL)
-- return NMERR_BAD_PARM;
--
-- /* Write the post */
-- bytes_to_send = g_snprintf(buffer, sizeof(buffer),
-- "POST /%s HTTP/1.0\r\n", cmd);
-- ret = nm_tcp_write(conn, buffer, bytes_to_send);
-- if (ret < 0) {
-- rc = NMERR_TCP_WRITE;
-- }
--
-- /* Write headers */
-- if (rc == NM_OK) {
-- if (strcmp("login", cmd) == 0) {
-- bytes_to_send = g_snprintf(buffer, sizeof(buffer),
-- "Host: %s:%d\r\n\r\n", conn->addr, conn->port);
-- ret = nm_tcp_write(conn, buffer, bytes_to_send);
-- if (ret < 0) {
-- rc = NMERR_TCP_WRITE;
-- }
-- } else {
-- bytes_to_send = g_snprintf(buffer, sizeof(buffer), "\r\n");
-- ret = nm_tcp_write(conn, buffer, bytes_to_send);
-- if (ret < 0) {
-- rc = NMERR_TCP_WRITE;
-- }
-- }
-- }
--
-- /* Add the transaction id to the request fields */
-- if (rc == NM_OK) {
-- if (fields)
-- request_fields = nm_copy_field_array(fields);
--
-- str = g_strdup_printf("%d", ++(conn->trans_id));
-- request_fields = nm_field_add_pointer(request_fields, NM_A_SZ_TRANSACTION_ID, 0,
-- NMFIELD_METHOD_VALID, 0,
-- str, NMFIELD_TYPE_UTF8);
-- }
--
-- /* Send the request to the server */
-- if (rc == NM_OK) {
-- rc = nm_write_fields(conn, request_fields);
-- }
--
-- /* Write the CRLF to terminate the data */
-- if (rc == NM_OK) {
-- ret = nm_tcp_write(conn, "\r\n", strlen("\r\n"));
-- if (ret < 0) {
-- rc = NMERR_TCP_WRITE;
-- }
-- }
--
-- /* Create a request struct, add it to our queue, and return it */
-- if (rc == NM_OK) {
-- NMRequest *new_request = nm_create_request(cmd, conn->trans_id,
-- time(0), cb, NULL, data);
-- nm_conn_add_request_item(conn, new_request);
--
-- /* Set the out param if it was sent in, otherwise release the request */
-- if (request)
-- *request = new_request;
-- else
-- nm_release_request(new_request);
-- }
--
-- if (request_fields != NULL)
-- nm_free_fields(&request_fields);
--
-- return rc;
--}
--
--NMERR_T
--nm_read_header(NMConn * conn)
--{
-- NMERR_T rc = NM_OK;
-- char buffer[512];
-- char *ptr = NULL;
-- int i;
-- char rtn_buf[8];
-- int rtn_code = 0;
--
-- if (conn == NULL)
-- return NMERR_BAD_PARM;
--
-- *buffer = '\0';
-- rc = read_line(conn, buffer, sizeof(buffer));
-- if (rc == NM_OK) {
--
-- /* Find the return code */
-- ptr = strchr(buffer, ' ');
-- if (ptr != NULL) {
-- ptr++;
--
-- i = 0;
-- while (isdigit(*ptr) && (i < 3)) {
-- rtn_buf[i] = *ptr;
-- i++;
-- ptr++;
-- }
-- rtn_buf[i] = '\0';
--
-- if (i > 0)
-- rtn_code = atoi(rtn_buf);
-- }
-- }
--
-- /* Finish reading header, in the future we might want to do more processing here */
-- /* TODO: handle more general redirects in the future */
-- while ((rc == NM_OK) && (strcmp(buffer, "\r\n") != 0)) {
-- rc = read_line(conn, buffer, sizeof(buffer));
-- }
--
-- if (rc == NM_OK && rtn_code == 301)
-- rc = NMERR_SERVER_REDIRECT;
--
-- return rc;
--}
--
--NMERR_T
--nm_read_fields(NMConn * conn, int count, NMField ** fields)
--{
-- NMERR_T rc = NM_OK;
-- guint8 type;
-- guint8 method;
-- guint32 val;
-- char tag[64];
-- NMField *sub_fields = NULL;
-- char *str = NULL;
--
-- if (conn == NULL || fields == NULL)
-- return NMERR_BAD_PARM;
--
-- do {
-- if (count > 0) {
-- count--;
-- }
--
-- /* Read the field type, method, and tag */
-- rc = nm_read_all(conn, (char *)&type, sizeof(type));
-- if (rc != NM_OK || type == 0)
-- break;
--
-- rc = nm_read_all(conn, (char *)&method, sizeof(method));
-- if (rc != NM_OK)
-- break;
--
-- rc = nm_read_uint32(conn, &val);
-- if (rc != NM_OK)
-- break;
--
-- if (val > sizeof(tag)) {
-- rc = NMERR_PROTOCOL;
-- break;
-- }
--
-- rc = nm_read_all(conn, tag, val);
-- if (rc != NM_OK)
-- break;
--
-- if (type == NMFIELD_TYPE_MV || type == NMFIELD_TYPE_ARRAY) {
--
-- /* Read the subarray (first read the number of items in the array) */
-- rc = nm_read_uint32(conn, &val);
-- if (rc != NM_OK)
-- break;
--
-- if (val > 0) {
-- rc = nm_read_fields(conn, val, &sub_fields);
-- if (rc != NM_OK)
-- break;
-- }
--
-- *fields = nm_field_add_pointer(*fields, tag, 0, method,
-- 0, sub_fields, type);
--
-- sub_fields = NULL;
--
-- } else if (type == NMFIELD_TYPE_UTF8 || type == NMFIELD_TYPE_DN) {
--
-- /* Read the string (first read the length) */
-- rc = nm_read_uint32(conn, &val);
-- if (rc != NM_OK)
-- break;
--
-- if (val >= NMFIELD_MAX_STR_LENGTH) {
-- rc = NMERR_PROTOCOL;
-- break;
-- }
--
-- if (val > 0) {
-- str = g_new0(char, val + 1);
--
-- rc = nm_read_all(conn, str, val);
-- if (rc != NM_OK)
-- break;
--
-- *fields = nm_field_add_pointer(*fields, tag, 0, method,
-- 0, str, type);
-- str = NULL;
-- }
--
-- } else {
--
-- /* Read the numerical value */
-- rc = nm_read_uint32(conn, &val);
-- if (rc != NM_OK)
-- break;
--
-- *fields = nm_field_add_number(*fields, tag, 0, method,
-- 0, val, type);
-- }
--
-- } while ((type != 0) && (count != 0));
--
--
-- if (str != NULL) {
-- g_free(str);
-- }
--
-- if (sub_fields != NULL) {
-- nm_free_fields(&sub_fields);
-- }
--
-- return rc;
--}
--
--void
--nm_conn_add_request_item(NMConn * conn, NMRequest * request)
--{
-- if (conn == NULL || request == NULL)
-- return;
--
-- nm_request_add_ref(request);
-- conn->requests = g_slist_append(conn->requests, request);
--}
--
--void
--nm_conn_remove_request_item(NMConn * conn, NMRequest * request)
--{
-- if (conn == NULL || request == NULL)
-- return;
--
-- conn->requests = g_slist_remove(conn->requests, request);
-- nm_release_request(request);
--}
--
--NMRequest *
--nm_conn_find_request(NMConn * conn, int trans_id)
--{
-- NMRequest *req = NULL;
-- GSList *itr = NULL;
--
-- if (conn == NULL)
-- return NULL;
--
-- itr = conn->requests;
-- while (itr) {
-- req = (NMRequest *) itr->data;
-- if (req != NULL && nm_request_get_trans_id(req) == trans_id) {
-- return req;
-- }
-- itr = g_slist_next(itr);
-- }
-- return NULL;
--}
--
--const char *
--nm_conn_get_addr(NMConn * conn)
--{
-- if (conn == NULL)
-- return NULL;
-- else
-- return conn->addr;
--}
--
--int
--nm_conn_get_port(NMConn * conn)
--{
-- if (conn == NULL)
-- return -1;
-- else
-- return conn->port;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmconn.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmconn.h
---- pidgin-2.10.7/libpurple/protocols/novell/nmconn.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmconn.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,246 +0,0 @@
--/*
-- * nmconn.h
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#ifndef __NM_CONN_H__
--#define __NM_CONN_H__
--
--typedef struct _NMConn NMConn;
--typedef struct _NMSSLConn NMSSLConn;
--
--#include "nmfield.h"
--#include "nmuser.h"
--
--typedef int (*nm_ssl_read_cb) (gpointer ssl_data, void *buff, int len);
--typedef int (*nm_ssl_write_cb) (gpointer ssl_data, const void *buff, int len);
--
--struct _NMConn
--{
--
-- /* The address of the server that we are connecting to. */
-- char *addr;
--
-- /* The port that we are connecting to. */
-- int port;
--
-- /* The file descriptor of the socket for the connection. */
-- int fd;
--
-- /* The transaction counter. */
-- int trans_id;
--
-- /* A list of requests currently awaiting a response. */
-- GSList *requests;
--
-- /* Are we connected? TRUE if so, FALSE if not. */
-- gboolean connected;
--
-- /* Are we running in secure mode? */
-- gboolean use_ssl;
--
-- /* Have we been redirected? */
-- gboolean redirect;
--
-- /* SSL connection */
-- NMSSLConn *ssl_conn;
--
--};
--
--struct _NMSSLConn
--{
--
-- /* Data to pass to the callbacks */
-- gpointer data;
--
-- /* Callbacks for reading/writing */
-- nm_ssl_read_cb read;
-- nm_ssl_write_cb write;
--
--};
--
--/**
-- * Allocate a new NMConn struct
-- *
-- * @param The address of the server that we are connecting to.
-- * @param The port that we are connecting to.
-- *
-- * @return A pointer to a newly allocated NMConn struct, should
-- * be freed by calling nm_release_conn()
-- */
--NMConn *nm_create_conn(const char *addr, int port);
--
--/**
-- * Release an NMConn
-- *
-- * @param Pointer to the NMConn to release.
-- *
-- */
--void nm_release_conn(NMConn *conn);
--
--/**
-- * Write len bytes from the given buffer.
-- *
-- * @param conn The connection to write to.
-- * @param buff The buffer to write from.
-- * @param len The number of bytes to write.
-- *
-- * @return The number of bytes written.
-- */
--int nm_tcp_write(NMConn * conn, const void *buff, int len);
--
--/**
-- * Read at most len bytes into the given buffer.
-- *
-- * @param conn The connection to read from.
-- * @param buff The buffer to write to.
-- * @param len The maximum number of bytes to read.
-- *
-- * @return The number of bytes read.
-- */
--int nm_tcp_read(NMConn * conn, void *buff, int len);
--
--/**
-- * Read exactly len bytes into the given buffer.
-- *
-- * @param conn The connection to read from.
-- * @param buff The buffer to write to.
-- * @param len The number of bytes to read.
-- *
-- * @return NM_OK on success, NMERR_TCP_READ if read fails.
-- */
--NMERR_T nm_read_all(NMConn * conn, char *buf, int len);
--
--/**
-- * Read a 32 bit value and convert it to the host byte order.
-- *
-- * @param conn The connection to read from.
-- * @param val A pointer to unsigned 32 bit integer
-- *
-- * @return NM_OK on success, NMERR_TCP_READ if read fails.
-- */
--NMERR_T
--nm_read_uint32(NMConn *conn, guint32 *val);
--
--/**
-- * Read a 16 bit value and convert it to the host byte order.
-- *
-- * @param conn The connection to read from.
-- * @param val A pointer to unsigned 16 bit integer
-- *
-- * @return NM_OK on success, NMERR_TCP_READ if read fails.
-- */
--NMERR_T
--nm_read_uint16(NMConn *conn, guint16 *val);
--
--/**
-- * Dispatch a request to the server.
-- *
-- * @param conn The connection.
-- * @param cmd The request to dispatch.
-- * @param fields The field list for the request.
-- * @param cb The response callback for the new request object.
-- * @param data The user defined data for the request (to be passed to the resp cb).
-- * @param req The request. Should be freed with nm_release_request.
-- *
-- * @return NM_OK on success.
-- */
--NMERR_T
--nm_send_request(NMConn *conn, char *cmd, NMField *fields,
-- nm_response_cb cb, gpointer data, NMRequest **request);
--
--/**
-- * Write out the given field list.
-- *
-- * @param conn The connection to write to.
-- * @param fields The field list to write.
-- *
-- * @return NM_OK on success.
-- */
--NMERR_T nm_write_fields(NMConn * conn, NMField * fields);
--
--/**
-- * Read the headers for a response.
-- *
-- * @param conn The connection to read from.
-- *
-- * @return NM_OK on success.
-- */
--NMERR_T nm_read_header(NMConn * conn);
--
--/**
-- * Read a field list from the connection.
-- *
-- * @param conn The connection to read from.
-- * @param count The maximum number of fields to read (or -1 for no max).
-- * @param fields The field list. This is an out param. It
-- * should be freed by calling nm_free_fields
-- * when finished.
-- *
-- * @return NM_OK on success.
-- */
--NMERR_T nm_read_fields(NMConn * conn, int count, NMField ** fields);
--
--/**
-- * Add a request to the connections request list.
-- *
-- * @param conn The connection.
-- * @param request The request to add to the list.
-- */
--void nm_conn_add_request_item(NMConn * conn, NMRequest * request);
--
--/**
-- * Remove a request from the connections list.
-- *
-- * @param conn The connection.
-- * @param request The request to remove from the list.
-- */
--void nm_conn_remove_request_item(NMConn * conn, NMRequest * request);
--
--/**
-- * Find the request with the given transaction id in the connections
-- * request list.
-- *
-- * @param conn The connection.
-- * @param trans_id The transaction id of the request to return.
-- *
-- * @return The request, or NULL if a matching request is not
-- * found.
-- */
--NMRequest *nm_conn_find_request(NMConn * conn, int trans_id);
--
--/**
-- * Get the server address for the connection.
-- *
-- * @param conn The connection.
-- *
-- * @return The server address for the connection.
-- *
-- */
--const char *nm_conn_get_addr(NMConn * conn);
--
--/**
-- * Get the port for the connection.
-- *
-- * @param conn The connection.
-- *
-- * @return The port that we are connected to.
-- */
--int nm_conn_get_port(NMConn * conn);
--
--#endif
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmcontact.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmcontact.c
---- pidgin-2.10.7/libpurple/protocols/novell/nmcontact.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmcontact.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,972 +0,0 @@
--/*
-- * nmcontact.c
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include <glib.h>
--#include <string.h>
--#include "nmcontact.h"
--#include "nmfield.h"
--#include "nmuser.h"
--
--struct _NMContact
--{
-- int id;
-- int parent_id;
-- int seq;
-- char *dn;
-- char *display_name;
-- NMUserRecord *user_record;
-- gpointer data;
-- int ref_count;
--};
--
--struct _NMFolder
--{
-- int id;
-- int seq;
-- char *name;
-- GSList *folders;
-- GSList *contacts;
-- int ref_count;
--};
--
--static int count = 0;
--
--static void _release_folder_contacts(NMFolder * folder);
--static void _release_folder_folders(NMFolder * folder);
--static void _add_contacts(NMUser * user, NMFolder * folder, NMField * fields);
--static void _add_folders(NMFolder * root, NMField * fields);
--
--/*********************************************************************
-- * Contact API
-- *********************************************************************/
--
--NMContact *
--nm_create_contact()
--{
-- NMContact *contact = g_new0(NMContact, 1);
--
-- contact->ref_count = 1;
--
-- purple_debug(PURPLE_DEBUG_INFO, "novell", "Creating contact, total=%d\n",
-- count++);
--
-- return contact;
--}
--
--/*
-- * This creates a contact for the contact list. The
-- * field array that is passed in should be a
-- * NM_A_FA_CONTACT array.
-- *
-- */
--NMContact *
--nm_create_contact_from_fields(NMField * fields)
--{
-- NMContact *contact;
-- NMField *field;
--
-- if ( fields == NULL || fields->tag == NULL || fields->ptr_value == 0 ||
-- strcmp(fields->tag, NM_A_FA_CONTACT) )
-- {
-- return NULL;
-- }
--
-- contact = nm_create_contact();
--
-- if ((field = nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) fields->ptr_value))) {
--
-- if (field->ptr_value)
-- contact->id = atoi((char *) field->ptr_value);
--
-- }
--
-- if ((field = nm_locate_field(NM_A_SZ_PARENT_ID, (NMField *) fields->ptr_value))) {
--
-- if (field->ptr_value)
-- contact->parent_id = atoi((char *) field->ptr_value);
--
-- }
--
-- if ((field =
-- nm_locate_field(NM_A_SZ_SEQUENCE_NUMBER, (NMField *) fields->ptr_value))) {
--
-- if (field->ptr_value)
-- contact->seq = atoi((char *) field->ptr_value);
--
-- }
--
-- if ((field =
-- nm_locate_field(NM_A_SZ_DISPLAY_NAME, (NMField *) fields->ptr_value))) {
--
-- if (field->ptr_value)
-- contact->display_name = g_strdup((char *) field->ptr_value);
--
-- }
--
-- if ((field = nm_locate_field(NM_A_SZ_DN, (NMField *) fields->ptr_value))) {
--
-- if (field->ptr_value)
-- contact->dn = g_strdup((char *) field->ptr_value);
--
-- }
--
-- return contact;
--}
--
--void
--nm_contact_update_list_properties(NMContact * contact, NMField * fields)
--{
-- NMField *field;
--
-- if (contact == NULL || fields == NULL || fields->ptr_value == 0)
-- return;
--
-- if ((field = nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) fields->ptr_value))) {
--
-- if (field->ptr_value)
-- contact->id = atoi((char *)field->ptr_value);
--
-- }
--
-- if ((field = nm_locate_field(NM_A_SZ_PARENT_ID, (NMField *) fields->ptr_value))) {
--
-- if (field->ptr_value)
-- contact->parent_id = atoi((char *) field->ptr_value);
--
-- }
--
-- if ((field =
-- nm_locate_field(NM_A_SZ_SEQUENCE_NUMBER, (NMField *) fields->ptr_value))) {
--
-- if (field->ptr_value)
-- contact->seq = atoi((char *) field->ptr_value);
--
-- }
--
-- if ((field =
-- nm_locate_field(NM_A_SZ_DISPLAY_NAME, (NMField *) fields->ptr_value))) {
--
-- if (field->ptr_value) {
-- if (contact->display_name)
-- g_free(contact->display_name);
--
-- contact->display_name = g_strdup((char *) field->ptr_value);
-- }
--
-- }
--
-- if ((field = nm_locate_field(NM_A_SZ_DN, (NMField *) fields->ptr_value))) {
--
-- if (field->ptr_value) {
-- if (contact->dn)
-- g_free(contact->dn);
--
-- contact->dn = g_strdup((char *) field->ptr_value);
-- }
--
-- }
--}
--
--NMField *
--nm_contact_to_fields(NMContact * contact)
--{
-- NMField *fields = NULL;
--
-- if (contact == NULL)
-- return NULL;
--
-- fields = nm_field_add_pointer(fields, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup_printf("%d", contact->id), NMFIELD_TYPE_UTF8);
--
-- fields = nm_field_add_pointer(fields, NM_A_SZ_PARENT_ID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup_printf("%d", contact->parent_id), NMFIELD_TYPE_UTF8);
--
-- fields = nm_field_add_pointer(fields, NM_A_SZ_SEQUENCE_NUMBER, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup_printf("%d", contact->seq), NMFIELD_TYPE_UTF8);
--
-- if (contact->display_name != NULL) {
-- fields = nm_field_add_pointer(fields, NM_A_SZ_DISPLAY_NAME, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(contact->display_name), NMFIELD_TYPE_UTF8);
-- }
--
-- if (contact->dn != NULL) {
-- fields = nm_field_add_pointer(fields, NM_A_SZ_DN, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(contact->dn), NMFIELD_TYPE_UTF8);
-- }
--
-- return fields;
--}
--
--void
--nm_contact_add_ref(NMContact * contact)
--{
-- if (contact)
-- contact->ref_count++;
--}
--
--void
--nm_release_contact(NMContact * contact)
--{
-- if (contact == NULL)
-- return;
--
-- if (--(contact->ref_count) == 0) {
--
-- purple_debug(PURPLE_DEBUG_INFO, "novell",
-- "Releasing contact, total=%d\n", --count);
--
-- if (contact->display_name) {
-- g_free(contact->display_name);
-- }
--
-- if (contact->dn) {
-- g_free(contact->dn);
-- }
--
-- if (contact->user_record) {
-- nm_release_user_record(contact->user_record);
-- }
--
-- g_free(contact);
-- }
--
--}
--
--const char *
--nm_contact_get_display_name(NMContact * contact)
--{
-- if (contact == NULL)
-- return NULL;
--
-- if (contact->user_record != NULL && contact->display_name == NULL) {
-- const char *full_name, *lname, *fname, *cn, *display_id;
--
-- full_name = nm_user_record_get_full_name(contact->user_record);
-- fname = nm_user_record_get_first_name(contact->user_record);
-- lname = nm_user_record_get_last_name(contact->user_record);
-- cn = nm_user_record_get_userid(contact->user_record);
-- display_id = nm_user_record_get_display_id(contact->user_record);
--
-- /* Try to build a display name. */
-- if (full_name) {
--
-- contact->display_name = g_strdup(full_name);
--
-- } else if (fname && lname) {
--
-- contact->display_name = g_strdup_printf("%s %s", fname, lname);
--
-- } else {
--
-- /* If auth attribute is set use it */
-- if (nm_user_record_get_auth_attr(contact->user_record) &&
-- display_id != NULL) {
--
-- contact->display_name = g_strdup(display_id);
--
-- } else {
--
-- /* Use CN or display id */
-- if (cn) {
--
-- contact->display_name = g_strdup(cn);
--
-- } else if (display_id) {
--
-- contact->display_name = g_strdup(display_id);
--
-- }
--
-- }
--
-- }
-- }
--
-- return contact->display_name;
--}
--
--void
--nm_contact_set_display_name(NMContact * contact, const char *display_name)
--{
-- if (contact == NULL)
-- return;
--
-- if (contact->display_name) {
-- g_free(contact->display_name);
-- contact->display_name = NULL;
-- }
--
-- if (display_name)
-- contact->display_name = g_strdup(display_name);
--}
--
--void
--nm_contact_set_dn(NMContact * contact, const char *dn)
--{
-- if (contact == NULL)
-- return;
--
-- if (contact->dn) {
-- g_free(contact->dn);
-- contact->dn = NULL;
-- }
--
-- if (dn)
-- contact->dn = g_strdup(dn);
--}
--
--const char *
--nm_contact_get_dn(NMContact * contact)
--{
-- if (contact == NULL)
-- return NULL;
--
-- return contact->dn;
--}
--
--gpointer
--nm_contact_get_data(NMContact * contact)
--{
-- if (contact == NULL)
-- return NULL;
--
-- return contact->data;
--}
--
--int
--nm_contact_get_id(NMContact * contact)
--{
-- if (contact == NULL)
-- return -1;
--
-- return contact->id;
--}
--
--int
--nm_contact_get_parent_id(NMContact * contact)
--{
-- if (contact == NULL)
-- return -1;
--
-- return contact->parent_id;
--}
--
--void
--nm_contact_set_data(NMContact * contact, gpointer data)
--{
-- if (contact == NULL)
-- return;
--
-- contact->data = data;
--}
--
--void
--nm_contact_set_user_record(NMContact * contact, NMUserRecord * user_record)
--{
-- if (contact == NULL)
-- return;
--
-- if (contact->user_record) {
-- nm_release_user_record(contact->user_record);
-- }
--
-- nm_user_record_add_ref(user_record);
-- contact->user_record = user_record;
--}
--
--NMUserRecord *
--nm_contact_get_user_record(NMContact * contact)
--{
-- if (contact == NULL)
-- return NULL;
--
-- return contact->user_record;
--}
--
--const char *
--nm_contact_get_userid(NMContact * contact)
--{
-- NMUserRecord *user_record;
-- const char *userid = NULL;
--
-- if (contact == NULL)
-- return NULL;
--
-- user_record = nm_contact_get_user_record(contact);
-- if (user_record) {
-- userid = nm_user_record_get_userid(user_record);
-- }
--
-- return userid;
--}
--
--const char *
--nm_contact_get_display_id(NMContact * contact)
--{
-- NMUserRecord *user_record;
-- const char *id = NULL;
--
-- if (contact == NULL)
-- return NULL;
--
-- user_record = nm_contact_get_user_record(contact);
-- if (user_record) {
-- id = nm_user_record_get_display_id(user_record);
-- }
--
-- return id;
--}
--
--
--/*********************************************************************
-- * Folder API
-- *********************************************************************/
--
--NMFolder *
--nm_create_folder(const char *name)
--{
-- NMFolder *folder = g_new0(NMFolder, 1);
--
-- if (name)
-- folder->name = g_strdup(name);
--
-- folder->ref_count = 1;
--
-- return folder;
--}
--
--NMFolder *
--nm_create_folder_from_fields(NMField * fields)
--{
-- NMField *field;
-- NMFolder *folder;
--
-- if (fields == NULL || fields->ptr_value == 0)
-- return NULL;
--
-- folder = g_new0(NMFolder, 1);
--
-- if ((field = nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) fields->ptr_value))) {
--
-- if (field->ptr_value)
-- folder->id = atoi((char *) field->ptr_value);
-- }
--
-- if ((field =
-- nm_locate_field(NM_A_SZ_SEQUENCE_NUMBER, (NMField *) fields->ptr_value))) {
--
-- if (field->ptr_value)
-- folder->seq = atoi((char *) field->ptr_value);
-- }
--
-- if ((field =
-- nm_locate_field(NM_A_SZ_DISPLAY_NAME, (NMField *) fields->ptr_value))) {
--
-- if (field->ptr_value)
-- folder->name = g_strdup((char *) field->ptr_value);
-- }
--
-- folder->ref_count = 1;
-- return folder;
--}
--
--NMField *
--nm_folder_to_fields(NMFolder * folder)
--{
-- NMField *fields = NULL;
--
-- if (folder == NULL)
-- return NULL;
--
-- fields = nm_field_add_pointer(fields, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup_printf("%d", folder->id), NMFIELD_TYPE_UTF8);
--
-- fields = nm_field_add_pointer(fields, NM_A_SZ_PARENT_ID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup("0"), NMFIELD_TYPE_UTF8);
--
-- fields = nm_field_add_pointer(fields, NM_A_SZ_TYPE, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup("1"), NMFIELD_TYPE_UTF8);
--
-- fields = nm_field_add_pointer(fields, NM_A_SZ_SEQUENCE_NUMBER, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup_printf("%d", folder->seq), NMFIELD_TYPE_UTF8);
--
-- if (folder->name != NULL) {
-- fields = nm_field_add_pointer(fields, NM_A_SZ_DISPLAY_NAME, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(folder->name), NMFIELD_TYPE_UTF8);
-- }
--
--
-- return fields;
--}
--
--void
--nm_folder_update_list_properties(NMFolder * folder, NMField * fields)
--{
-- NMField *field;
--
-- if (folder == NULL || fields == NULL || fields->ptr_value == 0)
-- return;
--
-- if ((field = nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) fields->ptr_value))) {
--
-- if (field->ptr_value)
-- folder->id = atoi((char *) field->ptr_value);
--
-- }
--
-- if ((field =
-- nm_locate_field(NM_A_SZ_SEQUENCE_NUMBER, (NMField *) fields->ptr_value))) {
--
-- if (field->ptr_value)
-- folder->seq = atoi((char *) field->ptr_value);
--
-- }
--
-- if ((field =
-- nm_locate_field(NM_A_SZ_DISPLAY_NAME, (NMField *) fields->ptr_value))) {
--
-- if (field->ptr_value) {
-- if (folder->name)
-- g_free(folder->name);
--
-- folder->name = g_strdup((char *) field->ptr_value);
-- }
--
-- }
--
--}
--
--void
--nm_release_folder(NMFolder * folder)
--{
-- if (folder == NULL)
-- return;
--
-- if (--(folder->ref_count) == 0) {
-- if (folder->name) {
-- g_free(folder->name);
-- }
--
-- if (folder->folders) {
-- _release_folder_folders(folder);
-- }
--
-- if (folder->contacts) {
-- _release_folder_contacts(folder);
-- }
--
-- g_free(folder);
-- }
--}
--
--
--void
--nm_folder_add_ref(NMFolder * folder)
--{
-- if (folder)
-- folder->ref_count++;
--}
--
--int
--nm_folder_get_subfolder_count(NMFolder * folder)
--{
-- if (folder == NULL)
-- return 0;
--
-- if (folder->folders)
-- return g_slist_length(folder->folders);
-- else
-- return 0;
--}
--
--NMFolder *
--nm_folder_get_subfolder(NMFolder * folder, int index)
--{
-- if (folder == NULL)
-- return NULL;
--
-- if (folder->folders)
-- return (NMFolder *) g_slist_nth_data(folder->folders, index);
-- else
-- return NULL;
--}
--
--int
--nm_folder_get_contact_count(NMFolder * folder)
--{
-- if (folder == NULL)
-- return 0;
--
-- if (folder->contacts != NULL)
-- return g_slist_length(folder->contacts);
-- else
-- return 0;
--}
--
--NMContact *
--nm_folder_get_contact(NMFolder * folder, int index)
--{
-- if (folder == NULL)
-- return NULL;
--
-- if (folder->contacts)
-- return (NMContact *) g_slist_nth_data(folder->contacts, index);
-- else
-- return NULL;
--}
--
--const char *
--nm_folder_get_name(NMFolder * folder)
--{
-- if (folder == NULL)
-- return NULL;
--
-- return folder->name;
--}
--
--void
--nm_folder_set_name(NMFolder * folder, const char *name)
--{
-- if (folder == NULL || name == NULL)
-- return;
--
-- if (folder->name)
-- g_free(folder->name);
--
-- folder->name = g_strdup(name);
--}
--
--int
--nm_folder_get_id(NMFolder * folder)
--{
-- if (folder == NULL) {
-- return -1;
-- }
--
-- return folder->id;
--}
--
--void
--nm_folder_add_folder_to_list(NMFolder * root, NMFolder * folder)
--{
-- GSList *node;
--
-- if (root == NULL || folder == NULL)
-- return;
--
-- node = root->folders;
-- while (node) {
-- if (folder->seq <= ((NMFolder *) node->data)->seq) {
-- nm_folder_add_ref(folder);
-- root->folders = g_slist_insert_before(root->folders, node, folder);
-- break;
-- }
-- node = g_slist_next(node);
-- }
-- if (node == NULL) {
-- nm_folder_add_ref(folder);
-- root->folders = g_slist_append(root->folders, folder);
-- }
--}
--
--void
--nm_folder_remove_contact(NMFolder * folder, NMContact * contact)
--{
-- GSList *node;
--
-- if (folder == NULL || contact == NULL)
-- return;
--
-- node = folder->contacts;
-- while (node) {
-- if (contact->id == ((NMContact *) (node->data))->id) {
-- folder->contacts = g_slist_remove(folder->contacts, node->data);
-- nm_release_contact(contact);
-- break;
-- }
-- node = g_slist_next(node);
-- }
--}
--
--void
--nm_folder_add_contact_to_list(NMFolder * root_folder, NMContact * contact)
--{
-- GSList *node = NULL;
-- NMFolder *folder = root_folder;
--
-- if (folder == NULL || contact == NULL)
-- return;
--
-- /* Find folder to add contact to */
-- if (contact->parent_id != 0) {
-- node = folder->folders;
-- while (node) {
-- folder = (NMFolder *) node->data;
-- if (contact->parent_id == folder->id) {
-- break;
-- }
-- folder = NULL;
-- node = g_slist_next(node);
-- }
-- }
--
-- /* Add contact to list */
-- if (folder) {
-- node = folder->contacts;
-- while (node) {
-- if (contact->seq <= ((NMContact *) (node->data))->seq) {
-- nm_contact_add_ref(contact);
-- folder->contacts =
-- g_slist_insert_before(folder->contacts, node, contact);
-- break;
-- }
-- node = g_slist_next(node);
-- }
--
-- if (node == NULL) {
-- nm_contact_add_ref(contact);
-- folder->contacts = g_slist_append(folder->contacts, contact);
-- }
-- }
--}
--
--void
--nm_folder_add_contacts_and_folders(NMUser * user, NMFolder * root,
-- NMField * fields)
--{
-- /* Add the contacts and folders from the field array */
-- if (user && root && fields) {
-- _add_folders(root, fields);
-- _add_contacts(user, root, fields);
-- }
--}
--
--gpointer
--nm_folder_find_item_by_object_id(NMFolder * root_folder, int object_id)
--{
-- int cnt, cnt2, i, j;
-- gpointer item = NULL;
-- NMFolder *folder;
-- NMContact *contact;
--
-- if (root_folder == NULL)
-- return NULL;
--
-- /* Check all contacts for the top level folder */
-- cnt = nm_folder_get_contact_count(root_folder);
-- for (i = 0; i < cnt; i++) {
-- contact = nm_folder_get_contact(root_folder, i);
-- if (contact && (contact->id == object_id)) {
-- item = contact;
-- break;
-- }
-- }
--
-- /* If we haven't found the item yet, check the subfolders */
-- if (item == NULL) {
-- cnt = nm_folder_get_subfolder_count(root_folder);
-- for (i = 0; (i < cnt) && (item == NULL); i++) {
-- folder = nm_folder_get_subfolder(root_folder, i);
--
-- /* Check the id of this folder */
-- if (folder && (folder->id == object_id)) {
-- item = folder;
-- break;
-- }
--
-- /* Check all contacts for this folder */
-- cnt2 = nm_folder_get_contact_count(folder);
-- for (j = 0; j < cnt2; j++) {
-- contact = nm_folder_get_contact(folder, j);
-- if (contact && (contact->id == object_id)) {
-- item = contact;
-- break;
-- }
-- }
-- }
-- }
--
-- return item;
--}
--
--NMContact *
--nm_folder_find_contact_by_userid(NMFolder * folder, const char *userid)
--{
-- int cnt, i;
-- NMContact *tmp, *contact = NULL;
--
-- if (folder == NULL || userid == NULL)
-- return NULL;
--
-- cnt = nm_folder_get_contact_count(folder);
-- for (i = 0; i < cnt; i++) {
-- tmp = nm_folder_get_contact(folder, i);
-- if (tmp && nm_utf8_str_equal(nm_contact_get_userid(tmp), userid)) {
-- contact = tmp;
-- break;
-- }
-- }
--
-- return contact;
--}
--
--NMContact *
--nm_folder_find_contact_by_display_id(NMFolder * folder, const char *display_id)
--{
-- int cnt, i;
-- NMContact *tmp, *contact = NULL;
--
-- if (folder == NULL || display_id == NULL)
-- return NULL;
--
-- cnt = nm_folder_get_contact_count(folder);
-- for (i = 0; i < cnt; i++) {
-- tmp = nm_folder_get_contact(folder, i);
-- if (tmp && nm_utf8_str_equal(nm_contact_get_display_id(tmp), display_id)) {
-- contact = tmp;
-- break;
-- }
-- }
--
-- return contact;
--}
--
--NMContact *
--nm_folder_find_contact(NMFolder * folder, const char *dn)
--{
-- int cnt, i;
-- NMContact *tmp, *contact = NULL;
--
-- if (folder == NULL || dn == NULL)
-- return NULL;
--
-- cnt = nm_folder_get_contact_count(folder);
-- for (i = 0; i < cnt; i++) {
-- tmp = nm_folder_get_contact(folder, i);
-- if (tmp && nm_utf8_str_equal(nm_contact_get_dn(tmp), dn)) {
-- contact = tmp;
-- break;
-- }
-- }
--
-- return contact;
--}
--
--
--/*********************************************************************
-- * Utility functions
-- *********************************************************************/
--
--static void
--_release_folder_contacts(NMFolder * folder)
--{
-- GSList *cnode;
-- NMContact *contact;
--
-- for (cnode = folder->contacts; cnode; cnode = cnode->next) {
-- contact = cnode->data;
-- cnode->data = NULL;
-- nm_release_contact(contact);
-- }
--
-- g_slist_free(folder->contacts);
-- folder->contacts = NULL;
--}
--
--static void
--_release_folder_folders(NMFolder * folder)
--{
-- GSList *fnode;
-- NMFolder *subfolder;
--
-- if (folder == NULL)
-- return;
--
-- for (fnode = folder->folders; fnode; fnode = fnode->next) {
-- subfolder = fnode->data;
-- fnode->data = NULL;
-- nm_release_folder(subfolder);
-- }
--
-- g_slist_free(folder->folders);
-- folder->folders = NULL;
--}
--
--static void
--_add_folders(NMFolder * root, NMField * fields)
--{
-- NMFolder *folder = NULL;
-- NMField *locate = NULL;
--
-- locate = nm_locate_field(NM_A_FA_FOLDER, fields);
-- while (locate != NULL) {
--
-- /* Create a new folder */
-- folder = nm_create_folder_from_fields(locate);
--
-- /* Add subfolder to roots folder list */
-- nm_folder_add_folder_to_list(root, folder);
--
-- /* Decrement the ref count */
-- nm_release_folder(folder);
--
-- /* Find the next folder */
-- locate = nm_locate_field(NM_A_FA_FOLDER, locate+1);
--
-- }
--}
--
--static void
--_add_contacts(NMUser * user, NMFolder * folder, NMField * fields)
--{
-- NMContact *contact = NULL;
-- NMField *locate = NULL, *details;
-- NMUserRecord *user_record = NULL;
--
-- locate = nm_locate_field(NM_A_FA_CONTACT, fields);
-- while (locate != NULL) {
--
-- /* Create a new contact from the fields */
-- contact = nm_create_contact_from_fields(locate);
--
-- /* Add it to our contact list */
-- nm_folder_add_contact_to_list(folder, contact);
--
-- /* Update the contact cache */
-- nm_user_add_contact(user, contact);
--
-- /* Update the user record cache */
-- if ((details = nm_locate_field(NM_A_FA_USER_DETAILS,
-- (NMField *) locate->ptr_value))) {
-- user_record = nm_find_user_record(user, nm_contact_get_dn(contact));
-- if (user_record == NULL) {
-- user_record = nm_create_user_record_from_fields(details);
-- nm_user_record_set_dn(user_record, nm_contact_get_dn(contact));
-- nm_user_add_user_record(user, user_record);
-- nm_release_user_record(user_record);
-- }
-- nm_contact_set_user_record(contact, user_record);
-- }
--
-- nm_release_contact(contact);
--
-- locate = nm_locate_field(NM_A_FA_CONTACT, locate+1);
-- }
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmcontact.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmcontact.h
---- pidgin-2.10.7/libpurple/protocols/novell/nmcontact.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmcontact.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,425 +0,0 @@
--/*
-- * nmcontact.h
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#ifndef __NM_CONTACT_H__
--#define __NM_CONTACT_H__
--
--#include <glib.h>
--
--typedef struct _NMContact NMContact;
--typedef struct _NMContactProperty NMContactProperty;
--typedef struct _NMFolder NMFolder;
--
--#include "nmfield.h"
--#include "nmuser.h"
--
--/**
-- * Creates a contact
-- *
-- * Should be released by calling nm_release_contact
-- *
-- * @return The new NMContact
-- *
-- */
--NMContact *nm_create_contact(void);
--
--/**
-- * Creates a contact from a field array representing the
-- * contact
-- *
-- * Should be released by calling nm_release_contact
-- *
-- * @param fields Should be the NM_A_FA_CONTACT for
-- * the contact
-- *
-- * @return The new contact
-- *
-- */
--NMContact *nm_create_contact_from_fields(NMField * fields);
--
--/**
-- * Add a reference to an existing contact
-- *
-- * The reference should be released by calling
-- * nm_release_contact
-- *
-- * @param contact The contact
-- *
-- */
--void nm_contact_add_ref(NMContact * contact);
--
--/**
-- * Update the contact list properties of the contact (sequence, parent id, etc.)
-- *
-- * @param contact The contact to update
-- * @param fields The fields to update from (should be a NM_A_FA_CONTACT array)
-- *
-- */
--void nm_contact_update_list_properties(NMContact * contact, NMField * fields);
--
--/**
-- * Release a contact reference
-- *
-- * @param contact The contact to release.
-- *
-- */
--void nm_release_contact(NMContact * contact);
--
--/**
-- * Get the display name of a contact
-- *
-- * @param contact The contact
-- *
-- * @return The display name of a contact
-- *
-- */
--const char *nm_contact_get_display_name(NMContact * contact);
--
--/**
-- * Get the DN of a contact
-- *
-- * @param contact The contact
-- *
-- * @return The DN of the contact
-- */
--const char *nm_contact_get_dn(NMContact * contact);
--
--/**
-- * Set the display name for a contact. This is called
-- * by nm_send_rename_contact. It should not be called
-- * directly (it does not change the display name on the
-- * server side list -- nm_send_rename_conact does).
-- *
-- * @param contact The contact
-- * @param display_name The new display name
-- *
-- */
--void nm_contact_set_display_name(NMContact * contact, const char * display_name);
--
--/**
-- * Set the DN for the contact
-- *
-- * @param contact The contact
-- * @param dn The new DN for the contact
-- *
-- */
--void nm_contact_set_dn(NMContact * contact, const char * dn);
--
--/**
-- * Return a field array (NM_A_FA_CONTACT) representing the contact
-- *
-- * @param contact The contact
-- *
-- * @return A field array representing the contact
-- */
--NMField *nm_contact_to_fields(NMContact * contact);
--
--/**
-- * Set the user record for the contact
-- *
-- * @param contact The contact
-- * @param user_record The user record
-- *
-- */
--void nm_contact_set_user_record(NMContact * contact, NMUserRecord * user_record);
--
--/**
-- * Get the user record for the contact
-- *
-- * @param contact The contact
-- *
-- * @return The user record associated with the contact
-- *
-- */
--NMUserRecord *nm_contact_get_user_record(NMContact * contact);
--
--/**
-- * Get the user defined data for the contact
-- *
-- * @param contact The contact
-- *
-- * @return The user defined data for the contact
-- *
-- */
--gpointer nm_contact_get_data(NMContact * contact);
--
--/**
-- * Get the Object ID for the contact
-- *
-- * @param contact The contact
-- *
-- * @return The ID for the contact
-- */
--int nm_contact_get_id(NMContact * contact);
--
--/**
-- * Get the ID for the folder that the contact is in
-- *
-- * @param contact The contact
-- *
-- * @return The ID of the folder that contains the contact
-- *
-- */
--int nm_contact_get_parent_id(NMContact * contact);
--
--/**
-- * Get The userid of the contact.
-- *
-- * @param contact The contact
-- *
-- * @return The userid of the contact
-- *
-- */
--const char *nm_contact_get_userid(NMContact * contact);
--
--/**
-- * Get the display id of the contact
-- *
-- * @param contact The contact
-- *
-- * @return The display id of the contact
-- */
--const char *nm_contact_get_display_id(NMContact * contact);
--
--/**
-- * Set the user defined data for the contact
-- *
-- * @param contact The contact
-- * @param data The user defined data
-- *
-- */
--void nm_contact_set_data(NMContact * contact, gpointer data);
--
--/**
-- * Create a folder with the given name
-- *
-- * @param name The name of the folder
-- *
-- * @return The new folder
-- *
-- */
--NMFolder *nm_create_folder(const char *name);
--
--/**
-- * Create a folder from a NM_A_FA_FOLDER field array
-- *
-- * @param fields The NM_A_FA_FOLDER field array
-- *
-- * @return The new folder
-- *
-- */
--NMFolder *nm_create_folder_from_fields(NMField * fields);
--
--/**
-- * Add a reference to an existing folder
-- *
-- * The reference should be released by calling
-- * nm_release_folder
-- *
-- * @param folder The folder
-- *
-- */
--void nm_folder_add_ref(NMFolder * folder);
--
--/**
-- * Release a reference to a folder.
-- *
-- * @param folder The folder to release
-- *
-- */
--void nm_release_folder(NMFolder * folder);
--
--/**
-- * Return the number of subfolders for the given
-- * folder
-- *
-- * @param folder The folder
-- *
-- * @return The number of subfolders contained by folder
-- */
--int nm_folder_get_subfolder_count(NMFolder * folder);
--
--/**
-- * Get a subfolder
-- *
-- * @param folder The root folder
-- * @param index The index of the folder to get
-- *
-- * @return The subfolder at the given index
-- *
-- */
--NMFolder *nm_folder_get_subfolder(NMFolder * folder, int index);
--
--/**
-- * Get the number of contacts in the given folder
-- *
-- * @param folder The folder
-- *
-- * @return The number of contacts contained by folder
-- *
-- */
--int nm_folder_get_contact_count(NMFolder * folder);
--
--/**
-- * Get a contact in the given folder
-- *
-- * @param folder The folder
-- * @param index The index of the contact to get
-- *
-- * @return The contact at the given index
-- *
-- */
--NMContact *nm_folder_get_contact(NMFolder * folder, int index);
--
--/**
-- * Get the name of the folder
-- *
-- * @param folder The folder
-- *
-- * @return The name of the folder.
-- *
-- */
--const char *nm_folder_get_name(NMFolder * folder);
--
--/**
-- * Set the name of a folder. Do not call this directly.
-- * It does not change the name of the folder in the
-- * server side contact list. You must call
-- * nm_send_set_folder_name().
-- *
-- * @param folder The folder
-- * @param name The new name for the folder
-- *
-- */
--void nm_folder_set_name(NMFolder * folder, const char *name);
--
--/**
-- * Get Object ID for folder
-- *
-- * @param folder The folder
-- *
-- * @return The ID of the folder
-- *
-- */
--int nm_folder_get_id(NMFolder * folder);
--
--/**
-- * Add contacts and folders from fields into root
-- *
-- * @param user The logged in user
-- * @param root The root folder
-- * @param fields The contact list field array
-- *
-- */
--void nm_folder_add_contacts_and_folders(NMUser * user, NMFolder * root,
-- NMField * fields);
--/**
-- * Add a contact to the contact list.
-- *
-- * @param root_folder The root folder of the contact list
-- * @param contact The contact to add
-- *
-- */
--void nm_folder_add_contact_to_list(NMFolder * root_folder,
-- NMContact * contact);
--
--/**
-- * Update the contact list properties of the folder (sequence, parent id, etc.)
-- *
-- * @param folder The folder to update
-- * @param fields The fields to update from (should be a NM_A_FA_FOLDER array)
-- *
-- */
--void nm_folder_update_list_properties(NMFolder * folder, NMField * fields);
--
--/**
-- * Add folder to the contact list
-- *
-- * @param root_folder The root folder of the contact list
-- * @param folder The folder to add to the contact list
-- *
-- */
--void nm_folder_add_folder_to_list(NMFolder * root_folder, NMFolder * folder);
--
--/**
-- * Find the object with the given id
-- *
-- * @param root_folder The root folder of the contact list
-- * @param object_id The object id of the object to find
-- *
-- * @return The object with object id (either a contact or a folder)
-- */
--gpointer nm_folder_find_item_by_object_id(NMFolder * root_folder,
-- int object_id);
--
--/**
-- * Remove a contact from the folder
-- *
-- * @param folder The folder
-- * @param contact The contact to remove
-- *
-- */
--void nm_folder_remove_contact(NMFolder * folder, NMContact * contact);
--
--/**
-- * Find a contact in a folder by DN
-- *
-- * @param folder The folder to search
-- * @param dn The DN of the contact to find
-- *
-- * @return The contact if found, NULL otherwise
-- *
-- */
--NMContact *nm_folder_find_contact(NMFolder * folder, const char *dn);
--
--/**
-- * Find a contact in a folder by userid
-- *
-- * @param folder The folder to search
-- * @param userid The userid of the contact to find
-- *
-- * @return The contact if found, NULL otherwise
-- *
-- */
--NMContact *nm_folder_find_contact_by_userid(NMFolder * folder,
-- const char *userid);
--
--/**
-- * Find a contact in a folder by display id
-- *
-- * @param folder The folder to search
-- * @param display_id The userid of the contact to find
-- *
-- * @return The contact if found, NULL otherwise
-- *
-- */
--NMContact *
--nm_folder_find_contact_by_display_id(NMFolder * folder, const char *display_id);
--
--/**
-- * Return a field array (NM_A_FA_FOLDER) representing the folder
-- *
-- * @param folder The folder
-- *
-- * @return A field array representing the folder
-- */
--NMField *nm_folder_to_fields(NMFolder * folder);
--
--#endif
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmevent.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmevent.c
---- pidgin-2.10.7/libpurple/protocols/novell/nmevent.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmevent.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,940 +0,0 @@
--/*
-- * nmevent.c
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include <glib.h>
--#include <string.h>
--#include <time.h>
--#include "nmevent.h"
--#include "nmfield.h"
--#include "nmconn.h"
--#include "nmuserrecord.h"
--#include "nmrtf.h"
--
--#define MAX_UINT32 0xFFFFFFFF
--
--struct _NMEvent
--{
--
-- /* Event type */
-- int type;
--
-- /* The DN of the event source */
-- char *source;
--
-- /* Timestamp of the event */
-- guint32 gmt;
--
-- /* Conference to associate with the event */
-- NMConference *conference;
--
-- /* User record to associate with the event */
-- NMUserRecord *user_record;
--
-- /* Text associated with the event */
-- char *text;
--
-- /* Reference count for event structure */
-- int ref_count;
--
--};
--
--/* Handle getdetails response and set the new user record into the event */
--static void
--_got_user_for_event(NMUser * user, NMERR_T ret_val,
-- gpointer resp_data, gpointer user_data)
--{
-- NMUserRecord *user_record;
-- NMEvent *event;
-- nm_event_cb cb;
--
-- if (user == NULL)
-- return;
--
-- user_record = resp_data;
-- event = user_data;
--
-- if (ret_val == NM_OK) {
-- if (event && user_record) {
--
-- /* Add the user record to the event structure
-- * and make the callback.
-- */
-- nm_event_set_user_record(event, user_record);
-- if ((cb = nm_user_get_event_callback(user))) {
-- cb(user, event);
-- }
-- }
--
-- } else {
-- /* Cleanup resp_data */
--
-- }
--
-- /* Clean up */
-- if (event)
-- nm_release_event(event);
--
--}
--
--/* Handle getdetails response, set the new user record into the event
-- * and add the user record as a participant in the conference
-- */
--static void
--_got_user_for_conference(NMUser * user, NMERR_T ret_val,
-- gpointer resp_data, gpointer user_data)
--{
-- NMUserRecord *user_record = resp_data;
-- NMEvent *event = user_data;
-- NMConference *conference;
-- nm_event_cb cb;
--
-- if (user == NULL)
-- return;
--
-- if (event && user_record) {
--
-- conference = nm_event_get_conference(event);
-- if (conference) {
--
-- /* Add source of event as recip of the conference */
-- nm_conference_add_participant(conference, user_record);
--
-- /* Add the user record to the event structure
-- * and make the callback.
-- */
-- nm_event_set_user_record(event, user_record);
-- if ((cb = nm_user_get_event_callback(user))) {
-- cb(user, event);
-- }
-- }
-- }
--
-- if (event)
-- nm_release_event(event);
--}
--
--/* Read the receive message event, set up the event object, and
-- * get details for the event source if we don't have them yet.
-- */
--static NMERR_T
--handle_receive_message(NMUser * user, NMEvent * event, gboolean autoreply)
--{
-- NMConference *conference;
-- NMUserRecord *user_record;
-- NMConn *conn;
-- NMERR_T rc = NM_OK;
-- guint32 size = 0, flags = 0;
-- char *msg = NULL;
-- char *nortf = NULL;
-- char *guid = NULL;
--
-- conn = nm_user_get_conn(user);
--
-- /* Read the conference guid */
-- rc = nm_read_uint32(conn, &size);
-- if (size == MAX_UINT32) return NMERR_PROTOCOL;
--
-- if (rc == NM_OK) {
-- guid = g_new0(char, size + 1);
-- rc = nm_read_all(conn, guid, size);
-- }
--
-- /* Read the conference flags */
-- if (rc == NM_OK) {
-- rc = nm_read_uint32(conn, &flags);
-- }
--
-- /* Read the message text */
-- if (rc == NM_OK) {
-- rc = nm_read_uint32(conn, &size);
-- if (size == MAX_UINT32) return NMERR_PROTOCOL;
--
-- if (rc == NM_OK) {
-- msg = g_new0(char, size + 1);
-- rc = nm_read_all(conn, msg, size);
--
-- purple_debug(PURPLE_DEBUG_INFO, "novell", "Message is %s\n", msg);
--
-- /* Auto replies are not in RTF format! */
-- if (!autoreply) {
-- NMRtfContext *ctx;
--
-- ctx = nm_rtf_init();
-- nortf = nm_rtf_strip_formatting(ctx, msg);
-- nm_rtf_deinit(ctx);
--
-- purple_debug(PURPLE_DEBUG_INFO, "novell",
-- "Message without RTF is %s\n", nortf);
--
-- /* Store the event data */
-- nm_event_set_text(event, nortf);
--
-- } else {
--
-- /* Store the event data */
-- nm_event_set_text(event, msg);
-- }
-- }
-- }
--
-- /* Check to see if we already know about the conference */
-- conference = nm_conference_list_find(user, guid);
-- if (conference) {
--
-- nm_conference_set_flags(conference, flags);
-- nm_event_set_conference(event, conference);
--
-- /* Add a reference to the user record in our event object */
-- user_record = nm_find_user_record(user, nm_event_get_source(event));
-- if (user_record) {
-- nm_event_set_user_record(event, user_record);
-- }
--
-- } else {
--
-- /* This is a new conference, so create one and add it to our list */
-- conference = nm_create_conference(guid);
-- nm_conference_set_flags(conference, flags);
--
-- /* Add a reference to the conference in the event */
-- nm_event_set_conference(event, conference);
--
-- /* Add new conference to the conference list */
-- nm_conference_list_add(user, conference);
--
-- /* Check to see if we have details for the event source yet */
-- user_record = nm_find_user_record(user, nm_event_get_source(event));
-- if (user_record) {
--
-- /* We do so add the user record as a recipient of the conference */
-- nm_conference_add_participant(conference, user_record);
--
-- /* Add a reference to the user record in our event object */
-- nm_event_set_user_record(event, user_record);
--
-- } else {
--
-- /* Need to go to the server to get details for the user */
-- rc = nm_send_get_details(user, nm_event_get_source(event),
-- _got_user_for_conference, event);
-- if (rc == NM_OK)
-- rc = -1; /* Not done processing the event yet! */
-- }
--
-- nm_release_conference(conference);
-- }
--
-- if (msg)
-- g_free(msg);
--
-- if (nortf)
-- g_free(nortf);
--
-- if (guid)
-- g_free(guid);
--
-- return rc;
--}
--
--/* Read the invite event, set up the event object, and
-- * get details for the event source if we don't have them yet.
-- */
--static NMERR_T
--handle_conference_invite(NMUser * user, NMEvent * event)
--{
-- NMERR_T rc = NM_OK;
-- guint32 size = 0;
-- char *guid = NULL;
-- char *msg = NULL;
-- NMConn *conn;
-- NMUserRecord *user_record;
--
-- conn = nm_user_get_conn(user);
--
-- /* Read the conference guid */
-- rc = nm_read_uint32(conn, &size);
-- if (size == MAX_UINT32) return NMERR_PROTOCOL;
--
-- if (rc == NM_OK) {
-- guid = g_new0(char, size + 1);
-- rc = nm_read_all(conn, guid, size);
-- }
--
-- /* Read the the message */
-- if (rc == NM_OK) {
-- rc = nm_read_uint32(conn, &size);
-- if (size == MAX_UINT32) return NMERR_PROTOCOL;
--
-- if (rc == NM_OK) {
-- msg = g_new0(char, size + 1);
-- rc = nm_read_all(conn, msg, size);
-- }
-- }
--
-- /* Store the event data */
-- if (rc == NM_OK) {
-- NMConference *conference;
--
-- nm_event_set_text(event, msg);
--
-- conference = nm_conference_list_find(user, guid);
-- if (conference == NULL) {
-- conference = nm_create_conference(guid);
--
-- /* Add new conference to the list and the event */
-- nm_conference_list_add(user, conference);
-- nm_event_set_conference(event, conference);
--
-- /* Check to see if we have details for the event source yet */
-- user_record = nm_find_user_record(user, nm_event_get_source(event));
-- if (user_record) {
--
-- /* Add a reference to the user record in our event object */
-- nm_event_set_user_record(event, user_record);
--
-- } else {
--
-- /* Need to go to the server to get details for the user */
-- rc = nm_send_get_details(user, nm_event_get_source(event),
-- _got_user_for_event, event);
-- if (rc == NM_OK)
-- rc = -1; /* Not done processing the event yet! */
-- }
--
-- nm_release_conference(conference);
--
-- }
-- }
--
-- if (msg)
-- g_free(msg);
--
-- if (guid)
-- g_free(guid);
--
-- return rc;
--}
--
--/* Read the invite notify event, set up the event object, and
-- * get details for the event source if we don't have them yet.
-- */
--static NMERR_T
--handle_conference_invite_notify(NMUser * user, NMEvent * event)
--{
-- NMERR_T rc = NM_OK;
-- guint32 size = 0;
-- char *guid = NULL;
-- NMConn *conn;
-- NMConference *conference;
-- NMUserRecord *user_record;
--
-- conn = nm_user_get_conn(user);
--
-- /* Read the conference guid */
-- rc = nm_read_uint32(conn, &size);
-- if (size == MAX_UINT32) return NMERR_PROTOCOL;
--
-- if (rc == NM_OK) {
-- guid = g_new0(char, size + 1);
-- rc = nm_read_all(conn, guid, size);
-- }
--
-- conference = nm_conference_list_find(user, guid);
-- if (conference) {
-- nm_event_set_conference(event, conference);
--
-- /* Check to see if we have details for the event source yet */
-- user_record = nm_find_user_record(user, nm_event_get_source(event));
-- if (user_record) {
--
-- /* Add a reference to the user record in our event object */
-- nm_event_set_user_record(event, user_record);
--
-- } else {
--
-- /* Need to go to the server to get details for the user */
-- rc = nm_send_get_details(user, nm_event_get_source(event),
-- _got_user_for_event, event);
-- if (rc == NM_OK)
-- rc = -1; /* Not done processing the event yet! */
-- }
--
-- } else {
-- rc = NMERR_CONFERENCE_NOT_FOUND;
-- }
--
--
-- if (guid)
-- g_free(guid);
--
-- return rc;
--}
--
--/* Read the conference reject event and set up the event object */
--static NMERR_T
--handle_conference_reject(NMUser * user, NMEvent * event)
--{
-- NMERR_T rc = NM_OK;
-- guint32 size = 0;
-- char *guid = NULL;
-- NMConn *conn;
-- NMConference *conference;
--
-- conn = nm_user_get_conn(user);
--
-- /* Read the conference guid */
-- rc = nm_read_uint32(conn, &size);
-- if (size == MAX_UINT32) return NMERR_PROTOCOL;
--
-- if (rc == NM_OK) {
-- guid = g_new0(char, size + 1);
-- rc = nm_read_all(conn, guid, size);
-- }
--
-- if (rc == NM_OK) {
-- conference = nm_conference_list_find(user, guid);
-- if (conference) {
-- nm_event_set_conference(event, conference);
-- } else {
-- rc = NMERR_CONFERENCE_NOT_FOUND;
-- }
-- }
--
-- if (guid)
-- g_free(guid);
--
-- return rc;
--}
--
--/* Read the conference left event, set up the event object, and
-- * remove the conference from the list if there are no more
-- * participants
-- */
--static NMERR_T
--handle_conference_left(NMUser * user, NMEvent * event)
--{
-- NMERR_T rc = NM_OK;
-- guint32 size = 0, flags = 0;
-- char *guid = NULL;
-- NMConference *conference;
-- NMConn *conn;
--
-- conn = nm_user_get_conn(user);
--
-- /* Read the conference guid */
-- rc = nm_read_uint32(conn, &size);
-- if (size == MAX_UINT32) return NMERR_PROTOCOL;
--
-- if (rc == NM_OK) {
-- guid = g_new0(char, size + 1);
-- rc = nm_read_all(conn, guid, size);
-- }
--
-- /* Read the conference flags */
-- if (rc == NM_OK) {
-- rc = nm_read_uint32(conn, &flags);
-- }
--
-- if (rc == NM_OK) {
-- conference = nm_conference_list_find(user, guid);
-- if (conference) {
-- nm_event_set_conference(event, conference);
-- nm_conference_set_flags(conference, flags);
--
-- nm_conference_remove_participant(conference, nm_event_get_source(event));
-- if (nm_conference_get_participant_count(conference) == 0) {
-- nm_conference_list_remove(user, conference);
-- }
--
-- } else {
-- rc = NMERR_CONFERENCE_NOT_FOUND;
-- }
-- }
--
-- if (guid)
-- g_free(guid);
--
-- return rc;
--}
--
--/* Read the conference closed, set up the event object, and
-- * remove the conference from the list
-- */
--static NMERR_T
--handle_conference_closed(NMUser * user, NMEvent * event)
--{
-- NMERR_T rc = NM_OK;
-- guint32 size = 0;
-- char *guid = NULL;
-- NMConference *conference;
-- NMConn *conn;
--
-- conn = nm_user_get_conn(user);
--
-- /* Read the conference guid */
-- rc = nm_read_uint32(conn, &size);
-- if (size == MAX_UINT32) return NMERR_PROTOCOL;
--
-- if (rc == NM_OK) {
-- guid = g_new0(char, size + 1);
-- rc = nm_read_all(conn, guid, size);
-- }
--
-- if (rc == NM_OK) {
-- conference = nm_conference_list_find(user, guid);
-- if (conference) {
-- nm_event_set_conference(event, conference);
-- nm_conference_list_remove(user, conference);
-- } else {
-- rc = NMERR_CONFERENCE_NOT_FOUND;
-- }
-- }
--
-- if (guid)
-- g_free(guid);
--
-- return rc;
--}
--
--/* Read the conference joined event, set up the event object, and
-- * get details for the event source if we don't have them yet.
-- */
--static NMERR_T
--handle_conference_joined(NMUser * user, NMEvent * event)
--{
-- NMERR_T rc = NM_OK;
-- guint32 size = 0, flags = 0;
-- char *guid = NULL;
-- NMConn *conn;
-- NMConference *conference;
-- NMUserRecord *user_record;
--
-- conn = nm_user_get_conn(user);
--
-- /* Read the conference guid */
-- rc = nm_read_uint32(conn, &size);
-- if (size == MAX_UINT32) return NMERR_PROTOCOL;
--
-- if (rc == NM_OK) {
-- guid = g_new0(char, size + 1);
-- rc = nm_read_all(conn, guid, size);
-- }
--
-- /* Read the conference flags */
-- if (rc == NM_OK) {
-- rc = nm_read_uint32(conn, &flags);
-- }
--
-- if (rc == NM_OK) {
-- conference = nm_conference_list_find(user, guid);
-- if (conference) {
-- nm_conference_set_flags(conference, flags);
--
-- nm_event_set_conference(event, conference);
--
-- /* Add the new user to the participants list */
-- user_record = nm_find_user_record(user, nm_event_get_source(event));
-- if (user_record) {
-- nm_conference_remove_participant(conference,
-- nm_user_record_get_dn(user_record));
-- nm_conference_add_participant(conference, user_record);
-- } else {
--
-- /* Need to go to the server to get details for the user */
-- rc = nm_send_get_details(user, nm_event_get_source(event),
-- _got_user_for_conference, event);
-- if (rc == NM_OK)
-- rc = -1; /* Not done processing the event yet! */
-- }
--
-- } else {
-- rc = NMERR_CONFERENCE_NOT_FOUND;
-- }
-- }
--
-- if (guid)
-- g_free(guid);
--
-- return rc;
--}
--
--/* Read the typing event and set up the event object */
--static NMERR_T
--handle_typing(NMUser * user, NMEvent * event)
--{
-- NMERR_T rc = NM_OK;
-- guint32 size = 0;
-- char *guid = NULL;
-- NMConference *conference;
-- NMConn *conn;
--
-- conn = nm_user_get_conn(user);
--
-- /* Read the conference guid */
-- rc = nm_read_uint32(conn, &size);
-- if (size == MAX_UINT32) return NMERR_PROTOCOL;
--
-- if (rc == NM_OK) {
-- guid = g_new0(char, size + 1);
-- rc = nm_read_all(conn, guid, size);
-- }
--
-- if (rc == NM_OK) {
-- conference = nm_conference_list_find(user, guid);
-- if (conference) {
-- nm_event_set_conference(event, conference);
-- } else {
-- rc = NMERR_CONFERENCE_NOT_FOUND;
-- }
-- }
--
-- if (guid)
-- g_free(guid);
--
-- return rc;
--}
--
--/* Read the event, set up the event object, and update
-- * the status in the user record (for the event source)
-- */
--static NMERR_T
--handle_status_change(NMUser * user, NMEvent * event)
--{
-- NMERR_T rc = NM_OK;
-- guint16 status;
-- guint32 size;
-- char *text = NULL;
-- NMUserRecord *user_record;
-- NMConn *conn;
--
-- conn = nm_user_get_conn(user);
--
-- /* Read new status */
-- rc = nm_read_uint16(conn, &status);
-- if (rc == NM_OK) {
--
-- /* Read the status text */
-- rc = nm_read_uint32(conn, &size);
-- if (size == MAX_UINT32) return NMERR_PROTOCOL;
--
-- if (rc == NM_OK) {
-- text = g_new0(char, size + 1);
-- rc = nm_read_all(conn, text, size);
-- }
-- }
--
-- if (rc == NM_OK) {
-- nm_event_set_text(event, text);
--
-- /* Get a reference to the user record and store the new status */
-- user_record = nm_find_user_record(user, nm_event_get_source(event));
-- if (user_record) {
-- nm_event_set_user_record(event, user_record);
-- nm_user_record_set_status(user_record, status, text);
-- }
-- }
--
-- if (text)
-- g_free(text);
--
-- return rc;
--}
--
--/* Read the undeliverable event */
--static NMERR_T
--handle_undeliverable_status(NMUser * user, NMEvent * event)
--{
-- NMERR_T rc = NM_OK;
-- guint32 size = 0;
-- char *guid = NULL;
-- NMConn *conn;
--
-- conn = nm_user_get_conn(user);
--
-- /* Read the conference guid */
-- rc = nm_read_uint32(conn, &size);
-- if (size == MAX_UINT32) return NMERR_PROTOCOL;
--
-- if (rc == NM_OK) {
-- guid = g_new0(char, size + 1);
-- rc = nm_read_all(conn, guid, size);
-- }
--
-- if (guid)
-- g_free(guid);
--
-- return rc;
--}
--
--/*******************************************************************************
-- * Event API -- see header file for comments
-- ******************************************************************************/
--
--NMEvent *
--nm_create_event(int type, const char *source, guint32 gmt)
--{
-- NMEvent *event = g_new0(NMEvent, 1);
--
-- event->type = type;
-- event->gmt = gmt;
--
-- if (source)
-- event->source = g_strdup(source);
--
-- event->ref_count = 1;
--
-- return event;
--}
--
--void
--nm_release_event(NMEvent * event)
--{
-- if (event == NULL) {
-- return;
-- }
--
-- if (--(event->ref_count) == 0) {
--
-- if (event->source)
-- g_free(event->source);
--
-- if (event->conference)
-- nm_release_conference(event->conference);
--
-- if (event->user_record)
-- nm_release_user_record(event->user_record);
--
-- if (event->text)
-- g_free(event->text);
--
-- g_free(event);
-- }
--}
--
--
--NMConference *
--nm_event_get_conference(NMEvent * event)
--{
-- if (event)
-- return event->conference;
-- else
-- return NULL;
--}
--
--void
--nm_event_set_conference(NMEvent * event, NMConference * conference)
--{
-- if (event && conference) {
-- nm_conference_add_ref(conference);
-- event->conference = conference;
-- }
--}
--
--NMUserRecord *
--nm_event_get_user_record(NMEvent * event)
--{
-- if (event)
-- return event->user_record;
-- else
-- return NULL;
--}
--
--void
--nm_event_set_user_record(NMEvent * event, NMUserRecord * user_record)
--{
-- if (event && user_record) {
-- nm_user_record_add_ref(user_record);
-- event->user_record = user_record;
-- }
--}
--
--const char *
--nm_event_get_text(NMEvent * event)
--{
-- if (event)
-- return event->text;
-- else
-- return NULL;
--}
--
--void
--nm_event_set_text(NMEvent * event, const char *text)
--{
-- if (event) {
-- if (text)
-- event->text = g_strdup(text);
-- else
-- event->text = NULL;
-- }
--}
--
--const char *
--nm_event_get_source(NMEvent * event)
--{
-- if (event)
-- return event->source;
-- else
-- return NULL;
--}
--
--int
--nm_event_get_type(NMEvent * event)
--{
-- if (event)
-- return event->type;
-- else
-- return -1;
--}
--
--time_t
--nm_event_get_gmt(NMEvent * event)
--{
-- if (event)
-- return event->gmt;
-- else
-- return (time_t)-1;
--}
--
--NMERR_T
--nm_process_event(NMUser * user, int type)
--{
-- NMERR_T rc = NM_OK;
-- guint32 size = 0;
-- NMEvent *event = NULL;
-- char *source = NULL;
-- nm_event_cb cb;
-- NMConn *conn;
--
-- if (user == NULL)
-- return NMERR_BAD_PARM;
--
-- if (type < NMEVT_START || type > NMEVT_STOP)
-- return NMERR_PROTOCOL;
--
-- conn = nm_user_get_conn(user);
--
-- /* Read the event source */
-- rc = nm_read_uint32(conn, &size);
-- if (rc == NM_OK) {
-- if (size > 0) {
-- source = g_new0(char, size);
--
-- rc = nm_read_all(conn, source, size);
-- }
-- }
--
-- /* Read the event data */
-- if (rc == NM_OK) {
-- event = nm_create_event(type, source, time(0));
--
-- if (event) {
--
-- switch (type) {
-- case NMEVT_STATUS_CHANGE:
-- rc = handle_status_change(user, event);
-- break;
--
-- case NMEVT_RECEIVE_MESSAGE:
-- rc = handle_receive_message(user, event, FALSE);
-- break;
--
-- case NMEVT_RECEIVE_AUTOREPLY:
-- rc = handle_receive_message(user, event, TRUE);
-- break;
--
-- case NMEVT_USER_TYPING:
-- case NMEVT_USER_NOT_TYPING:
-- rc = handle_typing(user, event);
-- break;
--
-- case NMEVT_CONFERENCE_LEFT:
-- rc = handle_conference_left(user, event);
-- break;
--
-- case NMEVT_CONFERENCE_CLOSED:
-- rc = handle_conference_closed(user, event);
-- break;
--
-- case NMEVT_CONFERENCE_JOINED:
-- rc = handle_conference_joined(user, event);
-- break;
--
-- case NMEVT_CONFERENCE_INVITE:
-- rc = handle_conference_invite(user, event);
-- break;
--
-- case NMEVT_CONFERENCE_REJECT:
-- rc = handle_conference_reject(user, event);
-- break;
--
-- case NMEVT_CONFERENCE_INVITE_NOTIFY:
-- rc = handle_conference_invite_notify(user, event);
-- break;
--
-- case NMEVT_UNDELIVERABLE_STATUS:
-- rc = handle_undeliverable_status(user, event);
-- break;
--
-- case NMEVT_INVALID_RECIPIENT:
-- /* Nothing else to read, just callback */
-- break;
--
-- case NMEVT_USER_DISCONNECT:
-- /* Nothing else to read, just callback */
-- break;
--
-- case NMEVT_SERVER_DISCONNECT:
-- /* Nothing else to read, just callback */
-- break;
--
-- case NMEVT_RECEIVE_FILE:
-- case NMEVT_CONTACT_ADD:
-- /* Safely ignored for now */
-- break;
--
-- default:
-- purple_debug(PURPLE_DEBUG_INFO, "novell",
-- "Unknown event %d received.\n", type);
-- rc = NMERR_PROTOCOL;
-- break;
-- }
-- }
-- }
--
-- if (rc == (NMERR_T)-1) {
-- /* -1 means that we are not ready to callback yet. */
-- rc = NM_OK;
-- } else if (rc == NM_OK && (cb = nm_user_get_event_callback(user))) {
--
-- cb(user, event);
--
-- if (event)
-- nm_release_event(event);
-- } else {
-- if (event)
-- nm_release_event(event);
-- }
--
-- /* Cleanup */
-- if (source)
-- g_free(source);
--
-- return rc;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmevent.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmevent.h
---- pidgin-2.10.7/libpurple/protocols/novell/nmevent.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmevent.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,178 +0,0 @@
--/*
-- * nmevent.h
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#ifndef __NM_EVENT_H__
--#define __NM_EVENT_H__
--
--typedef struct _NMEvent NMEvent;
--
--#include "nmuser.h"
--#include <sys/types.h>
--
--/**
-- * Defines for the event types
-- */
--#define NMEVT_INVALID_RECIPIENT 101
--#define NMEVT_UNDELIVERABLE_STATUS 102
--#define NMEVT_STATUS_CHANGE 103
--#define NMEVT_CONTACT_ADD 104
--#define NMEVT_CONFERENCE_CLOSED 105
--#define NMEVT_CONFERENCE_JOINED 106
--#define NMEVT_CONFERENCE_LEFT 107
--#define NMEVT_RECEIVE_MESSAGE 108
--#define NMEVT_RECEIVE_FILE 109
--#define NMEVT_USER_TYPING 112
--#define NMEVT_USER_NOT_TYPING 113
--#define NMEVT_USER_DISCONNECT 114
--#define NMEVT_SERVER_DISCONNECT 115
--#define NMEVT_CONFERENCE_RENAME 116
--#define NMEVT_CONFERENCE_INVITE 117
--#define NMEVT_CONFERENCE_INVITE_NOTIFY 118
--#define NMEVT_CONFERENCE_REJECT 119
--#define NMEVT_RECEIVE_AUTOREPLY 121
--#define NMEVT_START NMEVT_INVALID_RECIPIENT
--#define NMEVT_STOP NMEVT_RECEIVE_AUTOREPLY
--
--/**
-- * Process the event. The event will be read, an NMEvent will
-- * be created, and the event callback will be called.
-- *
-- * @param user The main user structure.
-- * @param type The type of the event to read.
-- *
-- * @return NM_OK on success
-- */
--NMERR_T nm_process_event(NMUser * user, int type);
--
--/**
-- * Creates an NMEvent
-- *
-- * The NMEvent should be released by calling
-- * nm_release_event.
-- *
-- * @param type The event type, see defines above.
-- * @param source The DN of the event source.
-- * @param gmt The time that the event occurred.
-- *
-- * @return The new NMEvent
-- */
--NMEvent *nm_create_event(int type, const char *source, guint32 gmt);
--
--/**
-- * Releases an NMEvent
-- *
-- * @param event The event to release
-- *
-- */
--void nm_release_event(NMEvent * event);
--
--/**
-- * Sets the conference object for the given event.
-- *
-- * @param event The event.
-- * @param conference The conference to associate with the event.
-- *
-- */
--void nm_event_set_conference(NMEvent * event, NMConference * conference);
--
--/**
-- * Returns the conference object associated with the given event. This should not
-- * be released. If it needs to be kept around call nm_conference_addref().
-- *
-- * @param event The event.
-- *
-- * @return The conference associated with the event, or NULL
-- * if no conference has been set for the event.
-- */
--NMConference *nm_event_get_conference(NMEvent * event);
--
--/**
-- * Sets the NMUserRecord object for the given event.
-- * The user record represents the event source.
-- *
-- * @param event The event.
-- * @param user_record The user record to associate with the event.
-- *
-- */
--void nm_event_set_user_record(NMEvent * event, NMUserRecord * user_record);
--
--/**
-- * Returns the NMUserRecord object associated with the given event.
-- * The user record represents the event source. This should not
-- * be released. If it needs to be kept around call
-- * nm_user_record_add_ref().
-- *
-- * @param event The event.
-- *
-- * @return The user record associated with the event, or NULL
-- * if no user record has been set for the event.
-- */
--NMUserRecord *nm_event_get_user_record(NMEvent * event);
--
--/**
-- * Sets the text to associate with the given event.
-- *
-- * @param event The event.
-- * @param text The text to associate with the event.
-- *
-- */
--void nm_event_set_text(NMEvent * event, const char *text);
--
--/**
-- * Returns the text associated with the given event.
-- *
-- * @param event The event.
-- *
-- * @return The text associated with the event, or NULL
-- * if no text has been set for the event.
-- */
--const char *nm_event_get_text(NMEvent * event);
--
--/**
-- * Returns the source of the event (this will be the full DN of the
-- * event source).
-- *
-- * @param event The event.
-- *
-- * @return The full DN of the event's source.
-- */
--const char *nm_event_get_source(NMEvent * event);
--
--/**
-- * Returns the type of the event. See the defines above for
-- * a list of possible event types.
-- *
-- * @param event The event.
-- *
-- * @return The type of the event.
-- *
-- */
--int nm_event_get_type(NMEvent * event);
--
--/**
-- * Returns the time that the event took place.
-- *
-- * @param event The event.
-- *
-- * @return The timestamp for the event.
-- */
--time_t nm_event_get_gmt(NMEvent * event);
--
--#endif
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmfield.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmfield.c
---- pidgin-2.10.7/libpurple/protocols/novell/nmfield.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmfield.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,364 +0,0 @@
--/*
-- * nmfield.c
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include <string.h>
--#include <stdio.h>
--#include "nmfield.h"
--
--/* Free a field value and tag */
--static void _free_field(NMField * field);
--
--/* Free a field value */
--static void _free_field_value(NMField * field);
--
--/* Make a deep copy of the field */
--static void _copy_field(NMField * dest, NMField * src);
--
--/* Make a deep copy of the field's value */
--static void _copy_field_value(NMField * dest, NMField * src);
--
--/* Create a string from a value -- for debugging */
--static char *_value_to_string(NMField * field);
--
--static NMField *
--_add_blank_field(NMField *fields, guint32 count)
--{
-- guint32 new_len;
--
-- if (fields == NULL) {
-- fields = g_new0(NMField, 10);
-- fields->len = 10;
-- } else {
-- if (fields->len < count + 2) {
-- new_len = count + 10;
-- fields = g_realloc(fields, new_len * sizeof(NMField));
-- fields->len = new_len;
-- }
-- }
-- return fields;
--}
--
--NMField *
--nm_field_add_number(NMField * fields, const char *tag, guint32 size, guint8 method,
-- guint8 flags, guint32 value, guint8 type)
--{
-- guint32 count;
-- NMField *field;
--
-- count = nm_count_fields(fields);
-- fields = _add_blank_field(fields, count);
--
-- field = &(fields[count]);
-- field->tag = g_strdup(tag);
-- field->size = size;
-- field->method = method;
-- field->flags = flags;
-- field->value = value;
-- field->type = type;
--
-- /* Null terminate the field array */
-- field = &((fields)[count + 1]);
-- field->tag = NULL;
-- field->value = 0;
-- field->ptr_value = NULL;
--
-- return fields;
--}
--
--NMField *
--nm_field_add_pointer(NMField * fields, const char *tag, guint32 size, guint8 method,
-- guint8 flags, gpointer value, guint8 type)
--{
-- guint32 count;
-- NMField *field = NULL;
--
-- count = nm_count_fields(fields);
-- fields = _add_blank_field(fields, count);
--
-- field = &(fields[count]);
-- field->tag = g_strdup(tag);
-- field->size = size;
-- field->method = method;
-- field->flags = flags;
-- field->ptr_value = value;
-- field->type = type;
--
-- /* Null terminate the field array */
-- field = &((fields)[count + 1]);
-- field->tag = NULL;
-- field->value = 0;
-- field->ptr_value = NULL;
--
-- return fields;
--}
--
--guint32
--nm_count_fields(NMField * fields)
--{
-- guint32 count = 0;
--
-- if (fields) {
-- while (fields->tag != NULL) {
-- count++;
-- fields++;
-- }
-- }
--
-- return count;
--}
--
--void
--nm_free_fields(NMField ** fields)
--{
-- NMField *field = NULL;
--
-- if ((fields == NULL) || (*fields == NULL))
-- return;
--
-- field = *fields;
--
-- while (field->tag != NULL) {
-- _free_field(field);
-- field++;
-- }
--
-- g_free(*fields);
-- *fields = NULL;
--}
--
--
--static void
--_free_field(NMField * field)
--{
-- if (field == NULL)
-- return;
--
-- _free_field_value(field);
-- g_free(field->tag);
--}
--
--static void
--_free_field_value(NMField * field)
--{
-- if (field == NULL)
-- return;
--
-- switch (field->type) {
-- case NMFIELD_TYPE_BINARY:
-- case NMFIELD_TYPE_UTF8:
-- case NMFIELD_TYPE_DN:
-- g_free(field->ptr_value);
-- break;
--
-- case NMFIELD_TYPE_ARRAY:
-- case NMFIELD_TYPE_MV:
-- nm_free_fields((NMField **)&field->ptr_value);
-- break;
--
-- default:
-- break;
-- }
--
-- field->size = 0;
-- field->ptr_value = NULL;
--}
--
--NMField *
--nm_locate_field(char *tag, NMField * fields)
--{
-- NMField *ret_fields = NULL;
--
-- if ((fields == NULL) || (tag == NULL)) {
-- return NULL;
-- }
--
-- while (fields->tag != NULL) {
-- if (g_ascii_strcasecmp(fields->tag, tag) == 0) {
-- ret_fields = fields;
-- break;
-- }
-- fields++;
-- }
--
-- return ret_fields;
--}
--
--NMField *
--nm_copy_field_array(NMField * src)
--{
-- NMField *ptr = NULL;
-- NMField *dest = NULL;
-- int count;
--
-- if (src != NULL) {
-- count = nm_count_fields(src) + 1;
-- dest = g_new0(NMField, count);
-- dest->len = count;
-- ptr = dest;
-- while (src->tag != NULL) {
-- _copy_field(ptr, src);
-- ptr++;
-- src++;
-- }
-- }
--
-- return dest;
--}
--
--static void
--_copy_field(NMField * dest, NMField * src)
--{
-- dest->type = src->type;
-- dest->flags = src->flags;
-- dest->method = src->method;
-- dest->tag = g_strdup(src->tag);
-- _copy_field_value(dest, src);
--}
--
--static void
--_copy_field_value(NMField * dest, NMField * src)
--{
-- dest->type = src->type;
-- switch (dest->type) {
-- case NMFIELD_TYPE_UTF8:
-- case NMFIELD_TYPE_DN:
-- if (src->size == 0 && src->ptr_value != NULL) {
-- src->size = strlen((char *) src->ptr_value) + 1;
-- }
-- /* fall through */
-- case NMFIELD_TYPE_BINARY:
-- if (src->size != 0 && src->ptr_value != NULL) {
-- dest->ptr_value = g_new0(char, src->size);
-- memcpy(dest->ptr_value, src->ptr_value, src->size);
-- }
-- break;
--
-- case NMFIELD_TYPE_ARRAY:
-- case NMFIELD_TYPE_MV:
-- dest->ptr_value = nm_copy_field_array((NMField *)src->ptr_value);
-- break;
--
-- default:
-- /* numeric value */
-- dest->value = src->value;
-- break;
-- }
--
-- dest->size = src->size;
--}
--
--void
--nm_remove_field(NMField * field)
--{
-- NMField *tmp;
-- guint32 len;
--
-- if ((field != NULL) && (field->tag != NULL)) {
-- _free_field(field);
--
-- /* Move fields down */
-- tmp = field + 1;
-- while (1) {
-- /* Don't overwrite the size of the array */
-- len = field->len;
--
-- *field = *tmp;
--
-- field->len = len;
--
-- if (tmp->tag == NULL)
-- break;
--
-- field++;
-- tmp++;
-- }
-- }
--}
--
--void
--nm_print_fields(NMField * fields)
--{
-- char *str = NULL;
-- NMField *field = fields;
--
-- if (fields == NULL)
-- return;
--
-- while (field->tag != NULL) {
-- if (field->type == NMFIELD_TYPE_ARRAY || field->type == NMFIELD_TYPE_MV) {
-- printf("Subarray START: %s Method = %d\n", field->tag, field->method);
-- nm_print_fields((NMField *) field->ptr_value);
-- printf("Subarray END: %s\n", field->tag);
-- } else {
-- str = _value_to_string(field);
-- printf("Tag=%s;Value=%s\n", field->tag, str);
-- g_free(str);
-- str = NULL;
-- }
-- field++;
-- }
--
--}
--
--static char *
--_value_to_string(NMField * field)
--{
-- char *value = NULL;
--
-- if (field == NULL)
-- return NULL;
--
-- /* This is a single value attribute */
-- if (((field->type == NMFIELD_TYPE_UTF8) ||
-- (field->type == NMFIELD_TYPE_DN)) && (field->ptr_value != NULL)) {
-- value = g_strdup((const char *) field->ptr_value);
-- } else if (field->type == NMFIELD_TYPE_BINARY && field->ptr_value != NULL) {
-- value = g_new0(char, field->size);
-- memcpy(value, (const char *) field->ptr_value, field->size);
-- } else if (field->type == NMFIELD_TYPE_BOOL) {
-- if (field->value) {
-- value = g_strdup(NM_FIELD_TRUE);
-- } else {
-- value = g_strdup(NM_FIELD_FALSE);
-- }
-- } else {
-- /* assume it is a number */
-- value = g_new0(char, 20);
--
-- switch (field->type) {
-- case NMFIELD_TYPE_BYTE:
-- case NMFIELD_TYPE_WORD:
-- case NMFIELD_TYPE_DWORD:
-- value = g_strdup_printf("%ld", (long) field->value);
-- break;
--
-- case NMFIELD_TYPE_UBYTE:
-- case NMFIELD_TYPE_UWORD:
-- case NMFIELD_TYPE_UDWORD:
-- value = g_strdup_printf("%lu", (unsigned long) field->value);
-- break;
-- }
-- }
--
-- if (value == NULL)
-- value = g_strdup("NULL");
--
-- return value;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmfield.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmfield.h
---- pidgin-2.10.7/libpurple/protocols/novell/nmfield.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmfield.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,225 +0,0 @@
--/*
-- * nmfield.h
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#ifndef NMFIELD_H
--#define NMFIELD_H
--
--#include <glib.h>
--
--typedef struct NMField_t
--{
-- char *tag; /* Field tag */
-- guint8 method; /* Method of the field */
-- guint8 flags; /* Flags */
-- guint8 type; /* Type of value */
-- guint32 size; /* Size of value if binary */
-- guint32 value; /* Value of a numeric field */
-- gpointer ptr_value; /* Value of a string or sub array field */
-- guint32 len; /* Length of the array */
--} NMField;
--
--/* Field types */
--#define NMFIELD_TYPE_INVALID 0
--#define NMFIELD_TYPE_NUMBER 1
--#define NMFIELD_TYPE_BINARY 2
--#define NMFIELD_TYPE_BYTE 3
--#define NMFIELD_TYPE_UBYTE 4
--#define NMFIELD_TYPE_WORD 5
--#define NMFIELD_TYPE_UWORD 6
--#define NMFIELD_TYPE_DWORD 7
--#define NMFIELD_TYPE_UDWORD 8
--#define NMFIELD_TYPE_ARRAY 9
--#define NMFIELD_TYPE_UTF8 10
--#define NMFIELD_TYPE_BOOL 11
--#define NMFIELD_TYPE_MV 12
--#define NMFIELD_TYPE_DN 13
--
--/* Field methods */
--#define NMFIELD_METHOD_VALID 0
--#define NMFIELD_METHOD_IGNORE 1
--#define NMFIELD_METHOD_DELETE 2
--#define NMFIELD_METHOD_DELETE_ALL 3
--#define NMFIELD_METHOD_EQUAL 4
--#define NMFIELD_METHOD_ADD 5
--#define NMFIELD_METHOD_UPDATE 6
--#define NMFIELD_METHOD_GTE 10
--#define NMFIELD_METHOD_LTE 12
--#define NMFIELD_METHOD_NE 14
--#define NMFIELD_METHOD_EXIST 15
--#define NMFIELD_METHOD_NOTEXIST 16
--#define NMFIELD_METHOD_SEARCH 17
--#define NMFIELD_METHOD_MATCHBEGIN 19
--#define NMFIELD_METHOD_MATCHEND 20
--#define NMFIELD_METHOD_NOT_ARRAY 40
--#define NMFIELD_METHOD_OR_ARRAY 41
--#define NMFIELD_METHOD_AND_ARRAY 42
--
--/* Attribute Names (field tags) */
--#define NM_A_IP_ADDRESS "nnmIPAddress"
--#define NM_A_PORT "nnmPort"
--#define NM_A_FA_FOLDER "NM_A_FA_FOLDER"
--#define NM_A_FA_CONTACT "NM_A_FA_CONTACT"
--#define NM_A_FA_CONVERSATION "NM_A_FA_CONVERSATION"
--#define NM_A_FA_MESSAGE "NM_A_FA_MESSAGE"
--#define NM_A_FA_CONTACT_LIST "NM_A_FA_CONTACT_LIST"
--#define NM_A_FA_RESULTS "NM_A_FA_RESULTS"
--#define NM_A_FA_INFO_DISPLAY_ARRAY "NM_A_FA_INFO_DISPLAY_ARRAY"
--#define NM_A_FA_USER_DETAILS "NM_A_FA_USER_DETAILS"
--#define NM_A_SZ_OBJECT_ID "NM_A_SZ_OBJECT_ID"
--#define NM_A_SZ_PARENT_ID "NM_A_SZ_PARENT_ID"
--#define NM_A_SZ_SEQUENCE_NUMBER "NM_A_SZ_SEQUENCE_NUMBER"
--#define NM_A_SZ_TYPE "NM_A_SZ_TYPE"
--#define NM_A_SZ_STATUS "NM_A_SZ_STATUS"
--#define NM_A_SZ_STATUS_TEXT "NM_A_SZ_STATUS_TEXT"
--#define NM_A_SZ_DN "NM_A_SZ_DN"
--#define NM_A_SZ_DISPLAY_NAME "NM_A_SZ_DISPLAY_NAME"
--#define NM_A_SZ_USERID "NM_A_SZ_USERID"
--#define NM_A_SZ_CREDENTIALS "NM_A_SZ_CREDENTIALS"
--#define NM_A_SZ_MESSAGE_BODY "NM_A_SZ_MESSAGE_BODY"
--#define NM_A_SZ_MESSAGE_TEXT "NM_A_SZ_MESSAGE_TEXT"
--#define NM_A_UD_MESSAGE_TYPE "NM_A_UD_MESSAGE_TYPE"
--#define NM_A_FA_PARTICIPANTS "NM_A_FA_PARTICIPANTS"
--#define NM_A_FA_INVITES "NM_A_FA_INVITES"
--#define NM_A_FA_EVENT "NM_A_FA_EVENT"
--#define NM_A_UD_COUNT "NM_A_UD_COUNT"
--#define NM_A_UD_DATE "NM_A_UD_DATE"
--#define NM_A_UD_EVENT "NM_A_UD_EVENT"
--#define NM_A_B_NO_CONTACTS "NM_A_B_NO_CONTACTS"
--#define NM_A_B_NO_CUSTOMS "NM_A_B_NO_CUSTOMS"
--#define NM_A_B_NO_PRIVACY "NM_A_B_NO_PRIVACY"
--#define NM_A_UW_STATUS "NM_A_UW_STATUS"
--#define NM_A_UD_OBJECT_ID "NM_A_UD_OBJECT_ID"
--#define NM_A_SZ_TRANSACTION_ID "NM_A_SZ_TRANSACTION_ID"
--#define NM_A_SZ_RESULT_CODE "NM_A_SZ_RESULT_CODE"
--#define NM_A_UD_BUILD "NM_A_UD_BUILD"
--#define NM_A_SZ_AUTH_ATTRIBUTE "NM_A_SZ_AUTH_ATTRIBUTE"
--#define NM_A_UD_KEEPALIVE "NM_A_UD_KEEPALIVE"
--#define NM_A_SZ_USER_AGENT "NM_A_SZ_USER_AGENT"
--#define NM_A_BLOCKING "nnmBlocking"
--#define NM_A_BLOCKING_DENY_LIST "nnmBlockingDenyList"
--#define NM_A_BLOCKING_ALLOW_LIST "nnmBlockingAllowList"
--#define NM_A_SZ_BLOCKING_ALLOW_ITEM "NM_A_SZ_BLOCKING_ALLOW_ITEM"
--#define NM_A_SZ_BLOCKING_DENY_ITEM "NM_A_SZ_BLOCKING_DENY_ITEM"
--#define NM_A_LOCKED_ATTR_LIST "nnmLockedAttrList"
--
--#define NM_PROTOCOL_VERSION 2
--
--#define NM_FIELD_TRUE "1"
--#define NM_FIELD_FALSE "0"
--
--#define NMFIELD_MAX_STR_LENGTH 32768
--
--/**
-- * Count the number of fields
-- *
-- * @param fields Field array
-- *
-- * @return The number of fields in the array.
-- *
-- */
--guint32 nm_count_fields(NMField * fields);
--
--/**
-- * Add a field to the field array. The field should be of type NMFIELD_TYPE_UTF8,
-- * NMFIELD_TYPE_DN, NMFIELD_TYPE_ARRAY, or NMFIELD_TYPE_MV
-- *
-- * NOTE: field array that is passed in may be realloc'd so you should use
-- * the returned field array pointer not the passed in pointer after calling
-- * this function.
-- *
-- * @param fields Field array
-- * @param tag Tag for the new field
-- * @param size Size of the field value (if type = binary)
-- * @param method Field method (see method defines above)
-- * @param flags Flags for new field
-- * @param value The value of the field
-- * @param type The type of the field value
-- *
-- * @return Pointer to the updated field array
-- *
-- */
--NMField *nm_field_add_pointer(NMField *fields, const char *tag, guint32 size, guint8 method,
-- guint8 flags, gpointer value, guint8 type);
--
--/**
-- * Add a numeric field to the field array.
-- *
-- * NOTE: field array that is passed in may be realloc'd so you should use
-- * the returned field array pointer not the passed in pointer after calling
-- * this function.
-- *
-- * @param fields Field array
-- * @param tag Tag for the new field
-- * @param size Size of the field value (if type = binary)
-- * @param method Field method (see method defines above)
-- * @param flags Flags for new field
-- * @param value The value of the field
-- * @param type The type of the field value
-- *
-- * @return Pointer to the updated field array
-- *
-- */
--NMField *nm_field_add_number(NMField *fields, const char *tag, guint32 size, guint8 method,
-- guint8 flags, guint32 value, guint8 type);
--
--/**
-- * Recursively free an array of fields and set pointer to NULL.
-- *
-- * @param fields Pointer to a field array
-- *
-- */
--void nm_free_fields(NMField ** fields);
--
--/**
-- * Find first field with given tag in field array.
-- *
-- * Note: this will only work for 7-bit ascii tags (which is all that
-- * we use currently).
-- *
-- * @param tag Tag to search for
-- * @param fields Field array
-- *
-- * @return The first matching field, or NULL if no fields match.
-- *
-- */
--NMField *nm_locate_field(char *tag, NMField * fields);
--
--/**
-- * Make a deep copy of a field array
-- *
-- * @param src The array to copy
-- *
-- * @return The new (copied) array, which must be freed.
-- *
-- */
--NMField *nm_copy_field_array(NMField * src);
--
--/**
-- * Remove a field and move other fields up to fill the gap
-- *
-- * @param field The field to remove
-- *
-- */
--void nm_remove_field(NMField * field);
--
--/* Print a field array (for debugging purposes) */
--void nm_print_fields(NMField * fields);
--
--#endif
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmmessage.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmmessage.c
---- pidgin-2.10.7/libpurple/protocols/novell/nmmessage.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmmessage.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,96 +0,0 @@
--/*
-- * nmmessage.c
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include "nmmessage.h"
--
--struct _NMMessage
--{
-- NMConference *conference;
-- char *text;
-- guint32 ref_count;
--};
--
--
--/** Message API **/
--
--NMMessage *
--nm_create_message(const char *text)
--{
-- NMMessage *msg = g_new0(NMMessage, 1);
--
-- if (text)
-- msg->text = g_strdup(text);
--
-- msg->ref_count = 1;
-- return msg;
--}
--
--void
--nm_message_add_ref(NMMessage * msg)
--{
-- if (msg)
-- msg->ref_count++;
--}
--
--void
--nm_release_message(NMMessage * msg)
--{
-- if (msg && (--(msg->ref_count) == 0)) {
-- if (msg->text)
-- g_free(msg->text);
--
-- if (msg->conference)
-- nm_release_conference(msg->conference);
--
-- g_free(msg);
-- }
--}
--
--const char *
--nm_message_get_text(NMMessage * msg)
--{
-- if (msg == NULL)
-- return NULL;
--
-- return msg->text;
--}
--
--void
--nm_message_set_conference(NMMessage * msg, NMConference * conf)
--{
-- if (msg == NULL || conf == NULL)
-- return;
--
-- /* Need to ref the conference first so that it doesn't
-- * get released out from under us
-- */
-- nm_conference_add_ref(conf);
--
-- msg->conference = conf;
--}
--
--NMConference *
--nm_message_get_conference(NMMessage * msg)
--{
-- if (msg == NULL)
-- return NULL;
--
-- return msg->conference;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmmessage.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmmessage.h
---- pidgin-2.10.7/libpurple/protocols/novell/nmmessage.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmmessage.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,83 +0,0 @@
--/*
-- * nmmessage.h
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#ifndef __NM_MESSAGE_H__
--#define __NM_MESSAGE_H__
--
--typedef struct _NMMessage NMMessage;
--
--#include "nmconference.h"
--
--/**
-- * Creates a new message.
-- *
-- * The returned message should be released by calling
-- * nm_release_message
-- *
-- * @param text The message text
-- * @return A newly allocated message
-- */
--NMMessage *nm_create_message(const char *text);
--
--/**
-- * Increment the reference count for the message object.
-- *
-- * @param msg The message
-- */
--void nm_message_add_ref(NMMessage * msg);
--
--/**
-- * Releases a message.
-- *
-- * @param msg The message
-- */
--void nm_release_message(NMMessage * msg);
--
--/**
-- * Returns the message text
-- *
-- * @param msg The message
-- * @return The message text
-- */
--const char *nm_message_get_text(NMMessage * msg);
--
--/**
-- * Sets the conference object for a message
-- *
-- * @param msg The message
-- * @param conf The conference to associate with the message
-- * @return RVALUE_OK on success
-- */
--void nm_message_set_conference(NMMessage * msg, NMConference * conf);
--
--/**
-- * Returns the conference object associated with the message
-- *
-- * Note: this does not increment the reference count for the
-- * conference and the conference should NOT be released with
-- * nm_release_conference. If the reference needs to be kept
-- * around nm_conference_add_ref should be called.
-- *
-- * @param msg The message
-- * @return The conference associated with this message
-- */
--NMConference *nm_message_get_conference(NMMessage * msg);
--
--#endif
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmrequest.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmrequest.c
---- pidgin-2.10.7/libpurple/protocols/novell/nmrequest.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmrequest.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,161 +0,0 @@
--/*
-- * nmrequest.c
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include "nmrequest.h"
--
--static int count = 0;
--
--struct _NMRequest
--{
-- int trans_id;
-- char *cmd;
-- int gmt;
-- gpointer data;
-- gpointer user_define;
-- nm_response_cb callback;
-- int ref_count;
-- NMERR_T ret_code;
--};
--
--NMRequest *nm_create_request(const char *cmd, int trans_id, int gmt, nm_response_cb cb,
-- gpointer resp_data, gpointer user_define)
--{
-- NMRequest *req;
--
-- if (cmd == NULL)
-- return NULL;
--
-- req = g_new0(NMRequest, 1);
-- req->cmd = g_strdup(cmd);
-- req->trans_id = trans_id;
-- req->gmt = gmt;
-- req->callback = cb;
-- req->data = resp_data;
-- req->user_define = user_define;
-- req->ref_count = 1;
--
-- purple_debug_info("novell", "Creating NMRequest instance, total=%d\n", ++count);
--
-- return req;
--}
--
--void
--nm_release_request(NMRequest * req)
--{
-- if (req && (--req->ref_count == 0)) {
-- if (req->cmd)
-- g_free(req->cmd);
-- g_free(req);
--
-- purple_debug_info("novell",
-- "Releasing NMRequest instance, total=%d\n", --count);
-- }
--
--}
--
--void
--nm_request_add_ref(NMRequest * req)
--{
-- if (req)
-- req->ref_count++;
--}
--
--void
--nm_request_set_callback(NMRequest * req, nm_response_cb callback)
--{
-- if (req)
-- req->callback = callback;
--}
--
--void
--nm_request_set_data(NMRequest * req, gpointer data)
--{
-- if (req)
-- req->data = data;
--}
--
--void
--nm_request_set_user_define(NMRequest * req, gpointer user_define)
--{
-- if (req)
-- req->user_define = user_define;
--}
--
--int
--nm_request_get_trans_id(NMRequest * req)
--{
-- if (req)
-- return req->trans_id;
-- else
-- return -1;
--}
--
--const char *
--nm_request_get_cmd(NMRequest * req)
--{
-- if (req == NULL)
-- return NULL;
--
-- return req->cmd;
--}
--
--gpointer
--nm_request_get_data(NMRequest * req)
--{
-- if (req == NULL)
-- return NULL;
--
-- return req->data;
--}
--
--gpointer
--nm_request_get_user_define(NMRequest * req)
--{
-- if (req == NULL)
-- return NULL;
--
-- return req->user_define;
--}
--
--nm_response_cb
--nm_request_get_callback(NMRequest * req)
--{
-- if (req == NULL)
-- return NULL;
--
-- return req->callback;
--}
--
--
--void
--nm_request_set_ret_code(NMRequest * req, NMERR_T rc)
--{
-- if (req)
-- req->ret_code = rc;
--}
--
--NMERR_T
--nm_request_get_ret_code(NMRequest * req)
--{
-- if (req)
-- return req->ret_code;
-- else
-- return (NMERR_T) - 1;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmrequest.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmrequest.h
---- pidgin-2.10.7/libpurple/protocols/novell/nmrequest.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmrequest.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,150 +0,0 @@
--/*
-- * nmrequest.h
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#ifndef __NM_REQUEST_H__
--#define __NM_REQUEST_H__
--
--typedef struct _NMRequest NMRequest;
--
--#include "nmuser.h"
--
--/**
-- * Create a new request object. Object must be release with nm_release_object.
-- *
-- * @param cmd The request command string (e.g. "login")
-- * @param trans_id The request transaction id
-- * @param gmt The time in seconds that the request was created
-- *
-- * @return The new request object
-- */
--NMRequest *nm_create_request(const char *cmd, int trans_id, int gmt, nm_response_cb cb,
-- gpointer resp_data, gpointer user_define);
--
--/**
-- * Release a request object.
-- *
-- * @param req The request to release
-- */
--void nm_release_request(NMRequest * req);
--
--/**
-- * Add a new reference to this object. This reference must be released by
-- * a call to nm_release_object.
-- *
-- * @param req The request object
-- */
--void nm_request_add_ref(NMRequest * req);
--
--/**
-- * Set the response callback for this request object. This is the callback
-- * that will be made when we get a response from the server.
-- *
-- * @param req The request object
-- * @param callback The response callback
-- *
-- */
--void nm_request_set_callback(NMRequest * req, nm_response_cb callback);
--
--/**
-- * Set the response data. This will be set differently depending on
-- * the request type (for example to nm_send_get_details will set this
-- * to be the newly create NMUserRecord object).
-- *
-- * @param req The request object
-- * @param data Pointer to some data
-- *
-- */
--void nm_request_set_data(NMRequest * req, gpointer data);
--
--/**
-- * Set the user defined data. This is the data that the client
-- * passes to the various nm_send_* functions. We will pass it
-- * back when we make the callback.
-- *
-- * @param req The request object
-- * @param user_define Pointer to some data
-- *
-- */
--void nm_request_set_user_define(NMRequest * req, gpointer user_define);
--
--/**
-- * Set the return code. This is the return code that we received in
-- * the server response fields.
-- *
-- * @param req The request object
-- * @param rc The return code to set
-- */
--void nm_request_set_ret_code(NMRequest * req, NMERR_T rc);
--
--/**
-- * Get the transaction id for this request.
-- *
-- * @param req The request object
-- *
-- * @return The transaction id.
-- */
--int nm_request_get_trans_id(NMRequest * req);
--
--/**
-- * Get the command (request type) for this request.
-- *
-- * @param req The request object
-- *
-- * @return The request cmd
-- */
--const char *nm_request_get_cmd(NMRequest * req);
--
--/**
-- * Get the response data for this request
-- *
-- * @param req The request object
-- *
-- * @return The response data
-- */
--gpointer nm_request_get_data(NMRequest * req);
--
--/**
-- * Get the user defined data for this request
-- *
-- * @param req The request object
-- *
-- * @return The user defined data
-- */
--gpointer nm_request_get_user_define(NMRequest * req);
--
--/**
-- * Get the response callback for this request
-- *
-- * @param req The request object
-- *
-- * @return The response callback
-- */
--nm_response_cb nm_request_get_callback(NMRequest * req);
--
--/**
-- * Get the return code
-- *
-- * @param req The request object
-- *
-- * @return The return code (from the response fields)
-- */
--NMERR_T nm_request_get_ret_code(NMRequest * req);
--
--#endif
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmrtf.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmrtf.c
---- pidgin-2.10.7/libpurple/protocols/novell/nmrtf.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmrtf.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,829 +0,0 @@
--/*
-- * nmrtf.c
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--/* This code was adapted from the sample RTF reader found here:
-- * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnrtfspec/html/rtfspec.asp
-- */
--
--#include <glib.h>
--#include <stdlib.h>
--#include <stdio.h>
--#include <stddef.h>
--#include <ctype.h>
--#include <string.h>
--#include "nmrtf.h"
--#include "debug.h"
--
--/* Internal RTF parser error codes */
--#define NMRTF_OK 0 /* Everything's fine! */
--#define NMRTF_STACK_UNDERFLOW 1 /* Unmatched '}' */
--#define NMRTF_STACK_OVERFLOW 2 /* Too many '{' -- memory exhausted */
--#define NMRTF_UNMATCHED_BRACE 3 /* RTF ended during an open group. */
--#define NMRTF_INVALID_HEX 4 /* invalid hex character found in data */
--#define NMRTF_BAD_TABLE 5 /* RTF table (sym or prop) invalid */
--#define NMRTF_ASSERTION 6 /* Assertion failure */
--#define NMRTF_EOF 7 /* End of file reached while reading RTF */
--#define NMRTF_CONVERT_ERROR 8 /* Error converting text */
--
--#define NMRTF_MAX_DEPTH 256
--
--typedef enum
--{
-- NMRTF_STATE_NORMAL,
-- NMRTF_STATE_SKIP,
-- NMRTF_STATE_FONTTABLE,
-- NMRTF_STATE_BIN,
-- NMRTF_STATE_HEX
--} NMRtfState; /* Rtf State */
--
--/* Property types that we care about */
--typedef enum
--{
-- NMRTF_PROP_FONT_IDX,
-- NMRTF_PROP_FONT_CHARSET,
-- NMRTF_PROP_MAX
--} NMRtfProperty;
--
--typedef enum
--{
-- NMRTF_SPECIAL_BIN,
-- NMRTF_SPECIAL_HEX,
-- NMRTF_SPECIAL_UNICODE,
-- NMRTF_SPECIAL_SKIP
--} NMRtfSpecialKwd;
--
--typedef enum
--{
-- NMRTF_DEST_FONTTABLE,
-- NMRTF_DEST_SKIP
--} NMRtfDestinationType;
--
--typedef enum
--{
-- NMRTF_KWD_CHAR,
-- NMRTF_KWD_DEST,
-- NMRTF_KWD_PROP,
-- NMRTF_KWD_SPEC
--} NMRtfKeywordType;
--
--typedef struct _NMRTFCharProp
--{
-- /* All we care about for now is the font.
-- * bold, italic, underline, etc. should be
-- * added here
-- */
-- int font_idx;
-- int font_charset;
--} NMRtfCharProp;
--
--typedef struct _NMRtfStateSave
--{
-- NMRtfCharProp chp;
-- NMRtfState rds;
-- NMRtfState ris;
--} NMRtfStateSave;
--
--typedef struct _NMRtfSymbol
--{
-- char *keyword; /* RTF keyword */
-- int default_val; /* default value to use */
-- gboolean pass_default; /* true to use default value from this table */
-- NMRtfKeywordType kwd_type; /* the type of the keyword */
-- int action; /* property type if the keyword represents a property */
-- /* destination type if the keyword represents a destination */
-- /* character to print if the keyword represents a character */
--} NMRtfSymbol;
--
--
--typedef struct _NMRtfFont
--{
-- int number;
-- char *name;
-- int charset;
--} NMRtfFont;
--
--/* RTF Context */
--struct _NMRtfContext
--{
-- NMRtfState rds; /* destination state */
-- NMRtfState ris; /* internal state */
-- NMRtfCharProp chp; /* current character properties (ie. font, bold, italic, etc.) */
-- GSList *font_table; /* the font table */
-- GSList *saved; /* saved state stack */
-- int param; /* numeric parameter for the current keyword */
-- long bytes_to_skip; /* number of bytes to skip (after encountering \bin) */
-- int depth; /* how many groups deep are we */
-- gboolean skip_unknown; /* if true, skip any unknown destinations (this is set after encountering '\*') */
-- char *input; /* input string */
-- char nextch; /* next char in input */
-- GString *ansi; /* Temporary ansi text, will be convert/flushed to the output string */
-- GString *output; /* The plain text UTF8 string */
--};
--
--static int rtf_parse(NMRtfContext *ctx);
--static int rtf_push_state(NMRtfContext *ctx);
--static int rtf_pop_state(NMRtfContext *ctx);
--static NMRtfFont *rtf_get_font(NMRtfContext *ctx, int index);
--static int rtf_get_char(NMRtfContext *ctx, guchar *ch);
--static int rtf_unget_char(NMRtfContext *ctx, guchar ch);
--static int rtf_flush_data(NMRtfContext *ctx);
--static int rtf_parse_keyword(NMRtfContext *ctx);
--static int rtf_dispatch_control(NMRtfContext *ctx, char *keyword, int param, gboolean param_set);
--static int rtf_dispatch_char(NMRtfContext *ctx, guchar ch);
--static int rtf_dispatch_unicode_char(NMRtfContext *ctx, gunichar ch);
--static int rtf_print_char(NMRtfContext *ctx, guchar ch);
--static int rtf_print_unicode_char(NMRtfContext *ctx, gunichar ch);
--static int rtf_change_destination(NMRtfContext *ctx, NMRtfDestinationType dest);
--static int rtf_dispatch_special(NMRtfContext *ctx, NMRtfSpecialKwd special);
--static int rtf_apply_property(NMRtfContext *ctx, NMRtfProperty prop, int val);
--
--/* RTF parser tables */
--
--/* Keyword descriptions */
--NMRtfSymbol rtf_symbols[] = {
-- /* keyword, default, pass_default, keyword_type, action */
-- {"fonttbl", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_FONTTABLE},
-- {"f", 0, FALSE, NMRTF_KWD_PROP, NMRTF_PROP_FONT_IDX},
-- {"fcharset", 0, FALSE, NMRTF_KWD_PROP, NMRTF_PROP_FONT_CHARSET},
-- {"par", 0, FALSE, NMRTF_KWD_CHAR, 0x0a},
-- {"line", 0, FALSE, NMRTF_KWD_CHAR, 0x0a},
-- {"\0x0a", 0, FALSE, NMRTF_KWD_CHAR, 0x0a},
-- {"\0x0d", 0, FALSE, NMRTF_KWD_CHAR, 0x0a},
-- {"tab", 0, FALSE, NMRTF_KWD_CHAR, 0x09},
-- {"\r", 0, FALSE, NMRTF_KWD_CHAR, '\r'},
-- {"\n", 0, FALSE, NMRTF_KWD_CHAR, '\n'},
-- {"ldblquote",0, FALSE, NMRTF_KWD_CHAR, '"'},
-- {"rdblquote",0, FALSE, NMRTF_KWD_CHAR, '"'},
-- {"{", 0, FALSE, NMRTF_KWD_CHAR, '{'},
-- {"}", 0, FALSE, NMRTF_KWD_CHAR, '}'},
-- {"\\", 0, FALSE, NMRTF_KWD_CHAR, '\\'},
-- {"bin", 0, FALSE, NMRTF_KWD_SPEC, NMRTF_SPECIAL_BIN},
-- {"*", 0, FALSE, NMRTF_KWD_SPEC, NMRTF_SPECIAL_SKIP},
-- {"'", 0, FALSE, NMRTF_KWD_SPEC, NMRTF_SPECIAL_HEX},
-- {"u", 0, FALSE, NMRTF_KWD_SPEC, NMRTF_SPECIAL_UNICODE},
-- {"colortbl", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"author", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"buptim", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"comment", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"creatim", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"doccomm", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"footer", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"footerf", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"footerl", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"footerr", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"footnote", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"ftncn", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"ftnsep", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"ftnsepc", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"header", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"headerf", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"headerl", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"headerr", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"info", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"keywords", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"operator", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"pict", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"printim", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"private1", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"revtim", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"rxe", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"stylesheet", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"subject", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"tc", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"title", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"txe", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
-- {"xe", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP}
--};
--int table_size = sizeof(rtf_symbols) / sizeof(NMRtfSymbol);
--
--NMRtfContext *
--nm_rtf_init()
--{
-- NMRtfContext *ctx = g_new0(NMRtfContext, 1);
-- ctx->nextch = -1;
-- ctx->ansi = g_string_new("");
-- ctx->output = g_string_new("");
-- return ctx;
--}
--
--char *
--nm_rtf_strip_formatting(NMRtfContext *ctx, const char *input)
--{
-- int status;
--
-- ctx->input = (char *)input;
-- status = rtf_parse(ctx);
-- if (status == NMRTF_OK)
-- return g_strdup(ctx->output->str);
--
-- purple_debug_info("novell", "RTF parser failed with error code %d\n", status);
-- return NULL;
--}
--
--void
--nm_rtf_deinit(NMRtfContext *ctx)
--{
-- GSList *node;
-- NMRtfFont *font;
-- NMRtfStateSave *save;
--
-- if (ctx) {
-- for (node = ctx->font_table; node; node = node->next) {
-- font = node->data;
-- g_free(font->name);
-- g_free(font);
-- node->data = NULL;
-- }
-- g_slist_free(ctx->font_table);
-- for (node = ctx->saved; node; node = node->next) {
-- save = node->data;
-- g_free(save);
-- node->data = NULL;
-- }
-- g_slist_free(ctx->saved);
-- g_string_free(ctx->ansi, TRUE);
-- g_string_free(ctx->output, TRUE);
-- g_free(ctx);
-- }
--}
--
--static const char *
--get_current_encoding(NMRtfContext *ctx)
--{
-- NMRtfFont *font;
--
-- font = rtf_get_font(ctx, ctx->chp.font_idx);
--
-- switch (font->charset) {
-- case 0:
-- return "CP1252";
-- case 77:
-- return "MACINTOSH";
-- case 78:
-- return "SJIS";
-- case 128:
-- return "CP932";
-- case 129:
-- return "CP949";
-- case 130:
-- return "CP1361";
-- case 134:
-- return "CP936";
-- case 136:
-- return "CP950";
-- case 161:
-- return "CP1253";
-- case 162:
-- return "CP1254";
-- case 163:
-- return "CP1258";
-- case 181:
-- case 177:
-- return "CP1255";
-- case 178:
-- case 179:
-- case 180:
-- return "CP1256";
-- case 186:
-- return "CP1257";
-- case 204:
-- return "CP1251";
-- case 222:
-- return "CP874";
-- case 238:
-- return "CP1250";
-- case 254:
-- return "CP437";
-- default:
-- purple_debug_info("novell", "Unhandled font charset %d\n", font->charset);
-- return "CP1252";
-- }
-- return "CP1252";
--}
--
--
--/*
-- * Add an entry to the font table
-- */
--static int
--rtf_add_font_entry(NMRtfContext *ctx, int number, const char *name, int charset)
--{
-- NMRtfFont *font = g_new0(NMRtfFont, 1);
--
-- font->number = number;
-- font->name = g_strdup(name);
-- font->charset = charset;
--
-- purple_debug_info("novell", "Adding font to table: #%d\t%s\t%d\n",
-- font->number, font->name, font->charset);
--
-- ctx->font_table = g_slist_append(ctx->font_table, font);
--
-- return NMRTF_OK;
--}
--
--/*
-- * Return the nth entry in the font table
-- */
--static NMRtfFont *
--rtf_get_font(NMRtfContext *ctx, int nth)
--{
-- NMRtfFont *font;
--
-- font = g_slist_nth_data(ctx->font_table, nth);
--
-- return font;
--}
--
--/*
-- * Step 1:
-- * Isolate RTF keywords and send them to rtf_parse_keyword;
-- * Push and pop state at the start and end of RTF groups;
-- * Send text to rtf_dispatch_char for further processing.
-- */
--static int
--rtf_parse(NMRtfContext *ctx)
--{
-- int status;
-- guchar ch;
-- guchar hex_byte = 0;
-- int hex_count = 2;
-- int len;
--
-- if (ctx->input == NULL)
-- return NMRTF_OK;
--
-- while (rtf_get_char(ctx, &ch) == NMRTF_OK) {
-- if (ctx->depth < 0)
-- return NMRTF_STACK_UNDERFLOW;
--
-- /* if we're parsing binary data, handle it directly */
-- if (ctx->ris == NMRTF_STATE_BIN) {
-- if ((status = rtf_dispatch_char(ctx, ch)) != NMRTF_OK)
-- return status;
-- } else {
-- switch (ch) {
-- case '{':
-- if (ctx->depth > NMRTF_MAX_DEPTH)
-- return NMRTF_STACK_OVERFLOW;
-- rtf_flush_data(ctx);
-- if ((status = rtf_push_state(ctx)) != NMRTF_OK)
-- return status;
-- break;
-- case '}':
-- rtf_flush_data(ctx);
--
-- /* for some reason there is always an unwanted '\par' at the end */
-- if (ctx->rds == NMRTF_STATE_NORMAL) {
-- len = ctx->output->len;
-- if (ctx->output->str[len-1] == '\n')
-- ctx->output = g_string_truncate(ctx->output, len-1);
-- }
--
-- if ((status = rtf_pop_state(ctx)) != NMRTF_OK)
-- return status;
--
-- if (ctx->depth < 0)
-- return NMRTF_STACK_OVERFLOW;
-- break;
-- case '\\':
-- if ((status = rtf_parse_keyword(ctx)) != NMRTF_OK)
-- return status;
-- break;
-- case 0x0d:
-- case 0x0a: /* cr and lf are noise characters... */
-- break;
-- default:
-- if (ctx->ris == NMRTF_STATE_NORMAL) {
-- if ((status = rtf_dispatch_char(ctx, ch)) != NMRTF_OK)
-- return status;
-- } else { /* parsing a hex encoded character */
-- if (ctx->ris != NMRTF_STATE_HEX)
-- return NMRTF_ASSERTION;
--
-- hex_byte = hex_byte << 4;
-- if (isdigit(ch))
-- hex_byte += (char) ch - '0';
-- else {
-- if (islower(ch)) {
-- if (ch < 'a' || ch > 'f')
-- return NMRTF_INVALID_HEX;
-- hex_byte += (char) ch - 'a' + 10;
-- } else {
-- if (ch < 'A' || ch > 'F')
-- return NMRTF_INVALID_HEX;
-- hex_byte += (char) ch - 'A' + 10;
-- }
-- }
-- hex_count--;
-- if (hex_count == 0) {
-- if ((status = rtf_dispatch_char(ctx, hex_byte)) != NMRTF_OK)
-- return status;
-- hex_count = 2;
-- hex_byte = 0;
-- ctx->ris = NMRTF_STATE_NORMAL;
-- }
-- }
-- break;
-- }
-- }
-- }
-- if (ctx->depth < 0)
-- return NMRTF_STACK_OVERFLOW;
-- if (ctx->depth > 0)
-- return NMRTF_UNMATCHED_BRACE;
-- return NMRTF_OK;
--}
--
--/*
-- * Push the current state onto stack
-- */
--static int
--rtf_push_state(NMRtfContext *ctx)
--{
-- NMRtfStateSave *save = g_new0(NMRtfStateSave, 1);
-- save->chp = ctx->chp;
-- save->rds = ctx->rds;
-- save->ris = ctx->ris;
-- ctx->saved = g_slist_prepend(ctx->saved, save);
-- ctx->ris = NMRTF_STATE_NORMAL;
-- (ctx->depth)++;
-- return NMRTF_OK;
--}
--
--/*
-- * Restore the state at the top of the stack
-- */
--static int
--rtf_pop_state(NMRtfContext *ctx)
--{
-- NMRtfStateSave *save_old;
-- GSList *link_old;
--
-- if (ctx->saved == NULL)
-- return NMRTF_STACK_UNDERFLOW;
--
-- save_old = ctx->saved->data;
-- ctx->chp = save_old->chp;
-- ctx->rds = save_old->rds;
-- ctx->ris = save_old->ris;
-- (ctx->depth)--;
--
-- g_free(save_old);
-- link_old = ctx->saved;
-- ctx->saved = g_slist_remove_link(ctx->saved, link_old);
-- g_slist_free_1(link_old);
-- return NMRTF_OK;
--}
--
--/*
-- * Step 2:
-- * Get a control word (and its associated value) and
-- * dispatch the control.
-- */
--static int
--rtf_parse_keyword(NMRtfContext *ctx)
--{
-- int status = NMRTF_OK;
-- guchar ch;
-- gboolean param_set = FALSE;
-- gboolean is_neg = FALSE;
-- int param = 0;
-- char keyword[30];
-- char parameter[20];
-- int i;
--
-- keyword[0] = '\0';
-- parameter[0] = '\0';
-- if ((status = rtf_get_char(ctx, &ch)) != NMRTF_OK)
-- return status;
--
-- if (!isalpha(ch)) {
-- /* a control symbol; no delimiter. */
-- keyword[0] = (char) ch;
-- keyword[1] = '\0';
-- return rtf_dispatch_control(ctx, keyword, 0, param_set);
-- }
--
-- /* parse keyword */
-- for (i = 0; isalpha(ch) && (i < sizeof(keyword) - 1); rtf_get_char(ctx, &ch)) {
-- keyword[i] = (char) ch;
-- i++;
-- }
-- keyword[i] = '\0';
--
-- /* check for '-' indicated a negative parameter value */
-- if (ch == '-') {
-- is_neg = TRUE;
-- if ((status = rtf_get_char(ctx, &ch)) != NMRTF_OK)
-- return status;
-- }
--
-- /* check for numerical param */
-- if (isdigit(ch)) {
--
-- param_set = TRUE;
-- for (i = 0; isdigit(ch) && (i < sizeof(parameter) - 1); rtf_get_char(ctx, &ch)) {
-- parameter[i] = (char) ch;
-- i++;
-- }
-- parameter[i] = '\0';
--
-- ctx->param = param = atoi(parameter);
-- if (is_neg)
-- ctx->param = param = -param;
-- }
--
-- /* space after control is optional, put character back if it is not a space */
-- if (ch != ' ')
-- rtf_unget_char(ctx, ch);
--
-- return rtf_dispatch_control(ctx, keyword, param, param_set);
--}
--
--/*
-- * Route the character to the appropriate destination
-- */
--static int
--rtf_dispatch_char(NMRtfContext *ctx, guchar ch)
--{
-- if (ctx->ris == NMRTF_STATE_BIN && --(ctx->bytes_to_skip) <= 0)
-- ctx->ris = NMRTF_STATE_NORMAL;
--
-- switch (ctx->rds) {
-- case NMRTF_STATE_SKIP:
-- return NMRTF_OK;
-- case NMRTF_STATE_NORMAL:
-- return rtf_print_char(ctx, ch);
-- case NMRTF_STATE_FONTTABLE:
-- if (ch == ';') {
-- rtf_add_font_entry(ctx, ctx->chp.font_idx,
-- ctx->ansi->str, ctx->chp.font_charset);
-- g_string_truncate(ctx->ansi, 0);
-- }
-- else {
-- return rtf_print_char(ctx, ch);
-- }
-- return NMRTF_OK;
-- default:
-- return NMRTF_OK;
-- }
--}
--
--/* Handle a unicode character */
--static int
--rtf_dispatch_unicode_char(NMRtfContext *ctx, gunichar ch)
--{
-- switch (ctx->rds) {
-- case NMRTF_STATE_SKIP:
-- return NMRTF_OK;
-- case NMRTF_STATE_NORMAL:
-- case NMRTF_STATE_FONTTABLE:
-- return rtf_print_unicode_char(ctx, ch);
-- default:
-- return NMRTF_OK;
-- }
--}
--
--/*
-- * Output a character
-- */
--static int
--rtf_print_char(NMRtfContext *ctx, guchar ch)
--{
--
-- ctx->ansi = g_string_append_c(ctx->ansi, ch);
--
-- return NMRTF_OK;
--}
--
--/*
-- * Output a unicode character
-- */
--static int
--rtf_print_unicode_char(NMRtfContext *ctx, gunichar ch)
--{
-- char buf[7];
-- int num;
--
-- /* convert and flush the ansi buffer to the utf8 buffer */
-- rtf_flush_data(ctx);
--
-- /* convert the unicode character to utf8 and add directly to the output buffer */
-- num = g_unichar_to_utf8((gunichar) ch, buf);
-- buf[num] = 0;
-- purple_debug_info("novell", "converted unichar 0x%X to utf8 char %s\n", ch, buf);
--
-- ctx->output = g_string_append(ctx->output, buf);
-- return NMRTF_OK;
--}
--
--/*
-- * Flush the output text
-- */
--static int
--rtf_flush_data(NMRtfContext *ctx)
--{
-- int status = NMRTF_OK;
-- char *conv_data = NULL;
-- const char *enc = NULL;
-- GError *gerror = NULL;
--
-- if (ctx->rds == NMRTF_STATE_NORMAL && ctx->ansi->len > 0) {
-- enc = get_current_encoding(ctx);
-- conv_data = g_convert(ctx->ansi->str, ctx->ansi->len, "UTF-8", enc,
-- NULL, NULL, &gerror);
-- if (conv_data) {
-- ctx->output = g_string_append(ctx->output, conv_data);
-- g_free(conv_data);
-- ctx->ansi = g_string_truncate(ctx->ansi, 0);
-- } else {
-- status = NMRTF_CONVERT_ERROR;
-- purple_debug_info("novell", "failed to convert data! error code = %d msg = %s\n",
-- gerror->code, gerror->message);
-- g_free(gerror);
-- }
-- }
--
-- return status;
--}
--
--/*
-- * Handle a property change
-- */
--static int
--rtf_apply_property(NMRtfContext *ctx, NMRtfProperty prop, int val)
--{
-- if (ctx->rds == NMRTF_STATE_SKIP) /* If we're skipping text, */
-- return NMRTF_OK; /* don't do anything. */
--
-- /* Need to flush any temporary data before a property change*/
-- rtf_flush_data(ctx);
--
-- switch (prop) {
-- case NMRTF_PROP_FONT_IDX:
-- ctx->chp.font_idx = val;
-- break;
-- case NMRTF_PROP_FONT_CHARSET:
-- ctx->chp.font_charset = val;
-- break;
-- default:
-- return NMRTF_BAD_TABLE;
-- }
--
-- return NMRTF_OK;
--}
--
--/*
-- * Step 3.
-- * Search the table for keyword and evaluate it appropriately.
-- *
-- * Inputs:
-- * keyword: The RTF control to evaluate.
-- * param: The parameter of the RTF control.
-- * param_set: TRUE if the control had a parameter; (that is, if param is valid)
-- * FALSE if it did not.
-- */
--static int
--rtf_dispatch_control(NMRtfContext *ctx, char *keyword, int param, gboolean param_set)
--{
-- int idx;
--
-- for (idx = 0; idx < table_size; idx++) {
-- if (strcmp(keyword, rtf_symbols[idx].keyword) == 0)
-- break;
-- }
--
-- if (idx == table_size) {
-- if (ctx->skip_unknown)
-- ctx->rds = NMRTF_STATE_SKIP;
-- ctx->skip_unknown = FALSE;
-- return NMRTF_OK;
-- }
--
-- /* found it! use kwd_type and action to determine what to do with it. */
-- ctx->skip_unknown = FALSE;
-- switch (rtf_symbols[idx].kwd_type) {
-- case NMRTF_KWD_PROP:
-- if (rtf_symbols[idx].pass_default || !param_set)
-- param = rtf_symbols[idx].default_val;
-- return rtf_apply_property(ctx, rtf_symbols[idx].action, param);
-- case NMRTF_KWD_CHAR:
-- return rtf_dispatch_char(ctx, rtf_symbols[idx].action);
-- case NMRTF_KWD_DEST:
-- return rtf_change_destination(ctx, rtf_symbols[idx].action);
-- case NMRTF_KWD_SPEC:
-- return rtf_dispatch_special(ctx, rtf_symbols[idx].action);
-- default:
-- return NMRTF_BAD_TABLE;
-- }
-- return NMRTF_BAD_TABLE;
--}
--
--/*
-- * Change to the destination specified.
-- */
--static int
--rtf_change_destination(NMRtfContext *ctx, NMRtfDestinationType type)
--{
-- /* if we're skipping text, don't do anything */
-- if (ctx->rds == NMRTF_STATE_SKIP)
-- return NMRTF_OK;
--
-- switch (type) {
-- case NMRTF_DEST_FONTTABLE:
-- ctx->rds = NMRTF_STATE_FONTTABLE;
-- g_string_truncate(ctx->ansi, 0);
-- break;
-- default:
-- ctx->rds = NMRTF_STATE_SKIP; /* when in doubt, skip it... */
-- break;
-- }
-- return NMRTF_OK;
--}
--
--/*
-- * Dispatch an RTF control that needs special processing
-- */
--static int
--rtf_dispatch_special(NMRtfContext *ctx, NMRtfSpecialKwd type)
--{
-- int status = NMRTF_OK;
-- guchar ch;
--
-- if (ctx->rds == NMRTF_STATE_SKIP && type != NMRTF_SPECIAL_BIN) /* if we're skipping, and it's not */
-- return NMRTF_OK; /* the \bin keyword, ignore it. */
--
-- switch (type) {
-- case NMRTF_SPECIAL_BIN:
-- ctx->ris = NMRTF_STATE_BIN;
-- ctx->bytes_to_skip = ctx->param;
-- break;
-- case NMRTF_SPECIAL_SKIP:
-- ctx->skip_unknown = TRUE;
-- break;
-- case NMRTF_SPECIAL_HEX:
-- ctx->ris = NMRTF_STATE_HEX;
-- break;
-- case NMRTF_SPECIAL_UNICODE:
-- purple_debug_info("novell", "parsing unichar\n");
-- status = rtf_dispatch_unicode_char(ctx, ctx->param);
-- /* Skip next char */
-- if (status == NMRTF_OK)
-- status = rtf_get_char(ctx, &ch);
-- break;
-- default:
-- status = NMRTF_BAD_TABLE;
-- break;
-- }
--
-- return status;
--}
--
--/*
-- * Get the next character from the input stream
-- */
--static int
--rtf_get_char(NMRtfContext *ctx, guchar *ch)
--{
-- if (ctx->nextch >= 0) {
-- *ch = ctx->nextch;
-- ctx->nextch = -1;
-- }
-- else {
-- *ch = *(ctx->input);
-- ctx->input++;
-- }
--
-- if (*ch)
-- return NMRTF_OK;
-- else
-- return NMRTF_EOF;
--}
--
--/*
-- * Move a character back into the input stream
-- */
--static int
--rtf_unget_char(NMRtfContext *ctx, guchar ch)
--{
-- ctx->nextch = ch;
-- return NMRTF_OK;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmrtf.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmrtf.h
---- pidgin-2.10.7/libpurple/protocols/novell/nmrtf.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmrtf.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,30 +0,0 @@
--/*
-- * nmrtf.h
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#ifndef __NMRTF_H__
--#define __NMRTF_H__
--
--typedef struct _NMRtfContext NMRtfContext;
--
--NMRtfContext *nm_rtf_init(void);
--char *nm_rtf_strip_formatting(NMRtfContext *ctx, const char *input);
--void nm_rtf_deinit(NMRtfContext *ctx);
--
--#endif
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmuser.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmuser.c
---- pidgin-2.10.7/libpurple/protocols/novell/nmuser.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmuser.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,2137 +0,0 @@
--/*
-- * nmuser.c
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include "internal.h"
--#include <string.h>
--#include "nmfield.h"
--#include "nmuser.h"
--#include "nmconn.h"
--#include "nmcontact.h"
--#include "nmuserrecord.h"
--#include "util.h"
--
--/* This is the template that we wrap outgoing messages in, since the other
-- * GW Messenger clients expect messages to be in RTF.
-- */
--#define RTF_TEMPLATE "{\\rtf1\\ansi\n"\
-- "{\\fonttbl{\\f0\\fnil Unknown;}}\n"\
-- "{\\colortbl ;\\red0\\green0\\blue0;}\n"\
-- "\\uc1\\cf1\\f0\\fs24 %s\\par\n}"
--#define NM_MAX_MESSAGE_SIZE 2048
--
--static NMERR_T nm_process_response(NMUser * user);
--static void _update_contact_list(NMUser * user, NMField * fields);
--static void _handle_multiple_get_details_login_cb(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data);
--static char * nm_rtfize_text(char *text);
--
--/**
-- * See header for comments on on "public" functions
-- */
--
--NMUser *
--nm_initialize_user(const char *name, const char *server_addr,
-- int port, gpointer data, nm_event_cb event_callback)
--{
-- NMUser *user;
-- if (name == NULL || server_addr == NULL || event_callback == NULL)
-- return NULL;
--
-- user = g_new0(NMUser, 1);
--
--
--
-- user->contacts =
-- g_hash_table_new_full(g_str_hash, nm_utf8_str_equal,
-- g_free, (GDestroyNotify) nm_release_contact);
--
-- user->user_records =
-- g_hash_table_new_full(g_str_hash, nm_utf8_str_equal, g_free,
-- (GDestroyNotify) nm_release_user_record);
--
-- user->display_id_to_dn = g_hash_table_new_full(g_str_hash, nm_utf8_str_equal,
-- g_free, g_free);
--
-- user->name = g_strdup(name);
-- user->conn = nm_create_conn(server_addr, port);
-- user->conn->addr = g_strdup(server_addr);
-- user->conn->port = port;
-- user->evt_callback = event_callback;
-- user->client_data = data;
--
-- return user;
--}
--
--
--void
--nm_deinitialize_user(NMUser * user)
--{
-- nm_release_conn(user->conn);
--
-- if (user->contacts) {
-- g_hash_table_destroy(user->contacts);
-- }
--
-- if (user->user_records) {
-- g_hash_table_destroy(user->user_records);
-- }
--
-- if (user->display_id_to_dn) {
-- g_hash_table_destroy(user->display_id_to_dn);
-- }
--
-- if (user->name) {
-- g_free(user->name);
-- }
--
-- if (user->user_record) {
-- nm_release_user_record(user->user_record);
-- }
--
-- nm_conference_list_free(user);
-- nm_destroy_contact_list(user);
--
-- g_free(user);
--}
--
--NMERR_T
--nm_send_login(NMUser * user, const char *pwd, const char *my_addr,
-- const char *user_agent, nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL;
--
-- if (user == NULL || pwd == NULL || user_agent == NULL) {
-- return NMERR_BAD_PARM;
-- }
--
-- fields = nm_field_add_pointer(fields, NM_A_SZ_USERID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(user->name), NMFIELD_TYPE_UTF8);
--
-- fields = nm_field_add_pointer(fields, NM_A_SZ_CREDENTIALS, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(pwd), NMFIELD_TYPE_UTF8);
--
-- fields = nm_field_add_pointer(fields, NM_A_SZ_USER_AGENT, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(user_agent), NMFIELD_TYPE_UTF8);
--
-- fields = nm_field_add_number(fields, NM_A_UD_BUILD, 0, NMFIELD_METHOD_VALID, 0,
-- NM_PROTOCOL_VERSION, NMFIELD_TYPE_UDWORD);
-- if (my_addr) {
-- fields = nm_field_add_pointer(fields, NM_A_IP_ADDRESS, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(my_addr), NMFIELD_TYPE_UTF8);
-- }
--
-- /* Send the login */
-- rc = nm_send_request(user->conn, "login", fields, callback, data, NULL);
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_set_status(NMUser * user, int status, const char *text,
-- const char *auto_resp, nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL;
--
-- if (user == NULL)
-- return NMERR_BAD_PARM;
--
-- /* Add the status */
-- fields = nm_field_add_pointer(fields, NM_A_SZ_STATUS, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup_printf("%d", status), NMFIELD_TYPE_UTF8);
--
-- /* Add the status text and auto reply text if there is any */
-- if (text) {
-- fields = nm_field_add_pointer(fields, NM_A_SZ_STATUS_TEXT, 0,
-- NMFIELD_METHOD_VALID, 0, g_strdup(text),
-- NMFIELD_TYPE_UTF8);
-- }
--
-- if (auto_resp) {
-- fields = nm_field_add_pointer(fields, NM_A_SZ_MESSAGE_BODY, 0,
-- NMFIELD_METHOD_VALID, 0, g_strdup(auto_resp),
-- NMFIELD_TYPE_UTF8);
-- }
--
-- rc = nm_send_request(user->conn, "setstatus", fields, callback, data, NULL);
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_multiple_get_details(NMUser * user, GSList *names,
-- nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL;
-- GSList *node;
--
-- if (user == NULL || names == NULL)
-- return NMERR_BAD_PARM;
--
-- /* Add in DN or display id */
-- for (node = names; node; node = node->next) {
-- fields = nm_field_add_pointer(fields, NM_A_SZ_USERID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(node->data), NMFIELD_TYPE_UTF8);
-- }
--
-- rc = nm_send_request(user->conn, "getdetails", fields, callback, data, NULL);
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_get_details(NMUser * user, const char *name,
-- nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL;
--
-- if (user == NULL || name == NULL)
-- return NMERR_BAD_PARM;
--
-- /* Add in DN or display id */
-- if (strstr("=", name)) {
-- fields = nm_field_add_pointer(fields, NM_A_SZ_DN, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(name), NMFIELD_TYPE_DN);
-- } else {
--
-- const char *dn = nm_lookup_dn(user, name);
-- if (dn) {
-- fields = nm_field_add_pointer(fields, NM_A_SZ_DN, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(name), NMFIELD_TYPE_DN);
-- } else {
-- fields =
-- nm_field_add_pointer(fields, NM_A_SZ_USERID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(name), NMFIELD_TYPE_UTF8);
-- }
--
-- }
--
-- rc = nm_send_request(user->conn, "getdetails", fields, callback, data, NULL);
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_create_conference(NMUser * user, NMConference * conference,
-- nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL;
-- NMField *tmp = NULL;
-- NMField *field = NULL;
-- NMRequest *req = NULL;
-- int count, i;
--
-- if (user == NULL || conference == NULL)
-- return NMERR_BAD_PARM;
--
-- /* Add in a blank guid */
-- tmp = nm_field_add_pointer(tmp, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(BLANK_GUID), NMFIELD_TYPE_UTF8);
--
-- fields = nm_field_add_pointer(fields, NM_A_FA_CONVERSATION, 0,
-- NMFIELD_METHOD_VALID, 0, tmp,
-- NMFIELD_TYPE_ARRAY);
-- tmp = NULL;
--
--
-- /* Add participants in */
-- count = nm_conference_get_participant_count(conference);
-- for (i = 0; i < count; i++) {
-- NMUserRecord *user_record = nm_conference_get_participant(conference, i);
--
-- if (user_record) {
-- fields = nm_field_add_pointer(fields, NM_A_SZ_DN,
-- 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(nm_user_record_get_dn(user_record)),
-- NMFIELD_TYPE_DN);
-- }
-- }
--
-- /* Add our user in */
-- field = nm_locate_field(NM_A_SZ_DN, user->fields);
-- if (field) {
-- fields = nm_field_add_pointer(fields, NM_A_SZ_DN,
-- 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup((char *) field->ptr_value),
-- NMFIELD_TYPE_DN);
-- }
--
-- rc = nm_send_request(user->conn, "createconf", fields, callback, data, &req);
-- if (rc == NM_OK && req) {
-- nm_conference_add_ref(conference);
-- nm_request_set_data(req, conference);
-- }
--
-- if (req)
-- nm_release_request(req);
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_leave_conference(NMUser * user, NMConference * conference,
-- nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL;
-- NMField *tmp = NULL;
-- NMRequest *req = NULL;
--
-- if (user == NULL || conference == NULL)
-- return NMERR_BAD_PARM;
--
-- /* Add in the conference guid */
-- tmp = nm_field_add_pointer(tmp, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(nm_conference_get_guid(conference)),
-- NMFIELD_TYPE_UTF8);
--
-- fields = nm_field_add_pointer(fields, NM_A_FA_CONVERSATION, 0,
-- NMFIELD_METHOD_VALID, 0, tmp,
-- NMFIELD_TYPE_ARRAY);
-- tmp = NULL;
--
-- /* Send the request to the server */
-- rc = nm_send_request(user->conn, "leaveconf", fields, callback, data, &req);
-- if (rc == NM_OK && req)
-- nm_request_set_data(req, conference);
--
-- if (req)
-- nm_release_request(req);
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_join_conference(NMUser * user, NMConference * conference,
-- nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL, *tmp = NULL;
-- NMRequest *req = NULL;
--
-- if (user == NULL || conference == NULL)
-- return NMERR_BAD_PARM;
--
-- /* Add in the conference guid */
-- tmp = nm_field_add_pointer(tmp, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(nm_conference_get_guid(conference)),
-- NMFIELD_TYPE_UTF8);
--
-- fields = nm_field_add_pointer(fields, NM_A_FA_CONVERSATION, 0,
-- NMFIELD_METHOD_VALID, 0, tmp,
-- NMFIELD_TYPE_ARRAY);
-- tmp = NULL;
--
-- /* Send the request to the server */
-- rc = nm_send_request(user->conn, "joinconf", fields, callback, data, &req);
-- if (rc == NM_OK && req)
-- nm_request_set_data(req, conference);
--
-- if (req)
-- nm_release_request(req);
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_reject_conference(NMUser * user, NMConference * conference,
-- nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL;
-- NMField *tmp = NULL;
-- NMRequest *req = NULL;
--
-- if (user == NULL || conference == NULL)
-- return NMERR_BAD_PARM;
--
-- /* Add in the conference guid */
-- tmp = nm_field_add_pointer(tmp, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(nm_conference_get_guid(conference)),
-- NMFIELD_TYPE_UTF8);
--
-- fields = nm_field_add_pointer(fields, NM_A_FA_CONVERSATION, 0,
-- NMFIELD_METHOD_VALID, 0, tmp,
-- NMFIELD_TYPE_ARRAY);
-- tmp = NULL;
--
-- /* Send the request to the server */
-- rc = nm_send_request(user->conn, "rejectconf", fields, callback, data, &req);
-- if (rc == NM_OK && req)
-- nm_request_set_data(req, conference);
--
-- if (req)
-- nm_release_request(req);
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_conference_invite(NMUser *user, NMConference *conference, NMUserRecord *user_record,
-- const char *message, nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL;
-- NMField *tmp = NULL;
-- NMRequest *req = NULL;
--
-- if (user == NULL || conference == NULL || user_record == NULL)
-- return NMERR_BAD_PARM;
--
-- /* Add in the conference guid */
-- tmp = nm_field_add_pointer(tmp, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(nm_conference_get_guid(conference)),
-- NMFIELD_TYPE_UTF8);
--
-- fields = nm_field_add_pointer(fields, NM_A_FA_CONVERSATION, 0,
-- NMFIELD_METHOD_VALID, 0, tmp,
-- NMFIELD_TYPE_ARRAY);
-- tmp = NULL;
--
-- /* Add in DN of user to invite */
-- fields = nm_field_add_pointer(fields, NM_A_SZ_DN, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(nm_user_record_get_dn(user_record)),
-- NMFIELD_TYPE_DN);
--
-- /* Add the invite message if there is one */
-- if (message)
-- fields = nm_field_add_pointer(fields, NM_A_SZ_MESSAGE_BODY, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(message), NMFIELD_TYPE_UTF8);
--
-- /* Send the request to the server */
-- rc = nm_send_request(user->conn, "sendinvite", fields, callback, data, &req);
-- if (rc == NM_OK && req)
-- nm_request_set_data(req, conference);
--
-- if (req)
-- nm_release_request(req);
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_message(NMUser * user, NMMessage * message, nm_response_cb callback)
--{
-- NMERR_T rc = NM_OK;
-- char *text, *rtfized;
-- NMField *fields = NULL, *tmp = NULL;
-- NMConference *conf;
-- NMUserRecord *user_record;
-- int count, i;
--
-- if (user == NULL || message == NULL) {
-- return NMERR_BAD_PARM;
-- }
--
-- conf = nm_message_get_conference(message);
-- if (!nm_conference_is_instantiated(conf)) {
-- rc = NMERR_CONFERENCE_NOT_INSTANTIATED;
-- } else {
--
-- tmp = nm_field_add_pointer(tmp, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(nm_conference_get_guid(conf)),
-- NMFIELD_TYPE_UTF8);
--
-- fields =
-- nm_field_add_pointer(fields, NM_A_FA_CONVERSATION, 0, NMFIELD_METHOD_VALID, 0,
-- tmp, NMFIELD_TYPE_ARRAY);
-- tmp = NULL;
--
-- /* Add RTF and plain text versions of the message */
-- text = g_strdup(nm_message_get_text(message));
--
-- /* Truncate if necessary */
-- if (strlen(text) > NM_MAX_MESSAGE_SIZE)
-- text[NM_MAX_MESSAGE_SIZE] = 0;
--
-- rtfized = nm_rtfize_text(text);
--
-- purple_debug_info("novell", "message text is: %s\n", text);
-- purple_debug_info("novell", "message rtf is: %s\n", rtfized);
--
-- tmp = nm_field_add_pointer(tmp, NM_A_SZ_MESSAGE_BODY, 0, NMFIELD_METHOD_VALID, 0,
-- rtfized, NMFIELD_TYPE_UTF8);
--
-- tmp = nm_field_add_number(tmp, NM_A_UD_MESSAGE_TYPE, 0, NMFIELD_METHOD_VALID, 0,
-- 0, NMFIELD_TYPE_UDWORD);
--
-- tmp = nm_field_add_pointer(tmp, NM_A_SZ_MESSAGE_TEXT, 0, NMFIELD_METHOD_VALID, 0,
-- text, NMFIELD_TYPE_UTF8);
--
-- fields = nm_field_add_pointer(fields, NM_A_FA_MESSAGE, 0, NMFIELD_METHOD_VALID, 0,
-- tmp, NMFIELD_TYPE_ARRAY);
-- tmp = NULL;
--
-- /* Add participants */
-- count = nm_conference_get_participant_count(conf);
-- for (i = 0; i < count; i++) {
-- user_record = nm_conference_get_participant(conf, i);
-- if (user_record) {
-- fields =
-- nm_field_add_pointer(fields, NM_A_SZ_DN, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(nm_user_record_get_dn(user_record)),
-- NMFIELD_TYPE_DN);
-- }
-- }
--
-- /* Send the request */
-- rc = nm_send_request(user->conn, "sendmessage", fields, callback, NULL, NULL);
-- }
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_typing(NMUser * user, NMConference * conf,
-- gboolean typing, nm_response_cb callback)
--{
-- NMERR_T rc = NM_OK;
-- char *str = NULL;
-- NMField *fields = NULL, *tmp = NULL;
--
-- if (user == NULL || conf == NULL) {
-- return NMERR_BAD_PARM;
-- }
--
-- if (!nm_conference_is_instantiated(conf)) {
-- rc = NMERR_CONFERENCE_NOT_INSTANTIATED;
-- } else {
-- /* Add the conference GUID */
-- tmp = nm_field_add_pointer(tmp, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(nm_conference_get_guid(conf)),
-- NMFIELD_TYPE_UTF8);
--
-- /* Add typing type */
-- str = g_strdup_printf("%d",
-- (typing ? NMEVT_USER_TYPING :
-- NMEVT_USER_NOT_TYPING));
--
-- tmp = nm_field_add_pointer(tmp, NM_A_SZ_TYPE, 0, NMFIELD_METHOD_VALID, 0,
-- str, NMFIELD_TYPE_UTF8);
--
-- fields =
-- nm_field_add_pointer(fields, NM_A_FA_CONVERSATION, 0, NMFIELD_METHOD_VALID, 0,
-- tmp, NMFIELD_TYPE_ARRAY);
-- tmp = NULL;
--
-- rc = nm_send_request(user->conn, "sendtyping", fields, callback, NULL, NULL);
-- }
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_create_contact(NMUser * user, NMFolder * folder,
-- NMContact * contact, nm_response_cb callback,
-- gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL;
-- NMRequest *req = NULL;
-- const char *name = NULL;
-- const char *display_name = NULL;
--
-- if (user == NULL || folder == NULL || contact == NULL) {
-- return NMERR_BAD_PARM;
-- }
--
-- /* Add parent ID */
-- fields = nm_field_add_pointer(fields, NM_A_SZ_PARENT_ID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup_printf("%d", nm_folder_get_id(folder)),
-- NMFIELD_TYPE_UTF8);
--
-- /* Check to see if userid is current user and return an error? */
--
-- /* Check to see if contact already exists and return an error? */
--
-- /* Add userid or dn */
-- name = nm_contact_get_dn(contact);
-- if (name == NULL)
-- return NMERR_BAD_PARM;
--
-- if (strstr("=", name)) {
-- fields = nm_field_add_pointer(fields, NM_A_SZ_DN, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(name), NMFIELD_TYPE_DN);
-- } else {
-- fields = nm_field_add_pointer(fields, NM_A_SZ_USERID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(name), NMFIELD_TYPE_UTF8);
-- }
--
-- /* Add display name */
-- display_name = nm_contact_get_display_name(contact);
-- if (display_name)
-- fields = nm_field_add_pointer(fields, NM_A_SZ_DISPLAY_NAME, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(display_name), NMFIELD_TYPE_UTF8);
--
-- /* Dispatch the request */
-- rc = nm_send_request(user->conn, "createcontact", fields, callback, data, &req);
-- if (rc == NM_OK && req)
-- nm_request_set_data(req, contact);
--
-- if (req)
-- nm_release_request(req);
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_remove_contact(NMUser * user, NMFolder * folder,
-- NMContact * contact, nm_response_cb callback,
-- gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL;
-- NMRequest *req = NULL;
--
-- if (user == NULL || folder == NULL || contact == NULL) {
-- return NMERR_BAD_PARM;
-- }
--
-- /* Add parent id */
-- fields = nm_field_add_pointer(fields, NM_A_SZ_PARENT_ID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup_printf("%d", nm_folder_get_id(folder)),
-- NMFIELD_TYPE_UTF8);
--
-- /* Add object id */
-- fields = nm_field_add_pointer(fields, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup_printf("%d", nm_contact_get_id(contact)),
-- NMFIELD_TYPE_UTF8);
--
-- /* Dispatch the request */
-- rc = nm_send_request(user->conn, "deletecontact", fields, callback, data, &req);
-- if (rc == NM_OK && req)
-- nm_request_set_data(req, contact);
--
-- if (req)
-- nm_release_request(req);
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_create_folder(NMUser * user, const char *name,
-- nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL;
-- NMRequest *req = NULL;
--
-- if (user == NULL || name == NULL) {
-- return NMERR_BAD_PARM;
-- }
--
-- /* Add parent ID */
-- fields = nm_field_add_pointer(fields, NM_A_SZ_PARENT_ID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup("0"), NMFIELD_TYPE_UTF8);
--
-- /* Add name of the folder to add */
-- fields =
-- nm_field_add_pointer(fields, NM_A_SZ_DISPLAY_NAME, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(name), NMFIELD_TYPE_UTF8);
--
-- /* Add sequence, for now just put it at the bottom */
-- fields =
-- nm_field_add_pointer(fields, NM_A_SZ_SEQUENCE_NUMBER, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup("-1"), NMFIELD_TYPE_UTF8);
--
-- /* Dispatch the request */
-- rc = nm_send_request(user->conn, "createfolder", fields, callback, data, &req);
-- if (rc == NM_OK && req)
-- nm_request_set_data(req, g_strdup(name));
--
-- if (req)
-- nm_release_request(req);
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_remove_folder(NMUser * user, NMFolder * folder,
-- nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL;
-- NMRequest *req = NULL;
--
-- if (user == NULL || folder == NULL) {
-- return NMERR_BAD_PARM;
-- }
--
-- /* Add the object id */
-- fields = nm_field_add_pointer(fields, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup_printf("%d", nm_folder_get_id(folder)),
-- NMFIELD_TYPE_UTF8);
--
-- /* Dispatch the request */
-- rc = nm_send_request(user->conn, "deletecontact", fields, callback, data, &req);
-- if (rc == NM_OK && req)
-- nm_request_set_data(req, folder);
--
-- if (req)
-- nm_release_request(req);
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_get_status(NMUser * user, NMUserRecord * user_record,
-- nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL;
-- NMRequest *req = NULL;
-- const char *dn;
--
-- if (user == NULL || user_record == NULL)
-- return NMERR_BAD_PARM;
--
-- /* Add DN to field list */
-- dn = nm_user_record_get_dn(user_record);
-- if (dn == NULL)
-- return (NMERR_T) -1;
--
-- fields = nm_field_add_pointer(fields, NM_A_SZ_DN, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup(dn), NMFIELD_TYPE_UTF8);
--
-- /* Dispatch the request */
-- rc = nm_send_request(user->conn, "getstatus", fields, callback, data, &req);
-- if (rc == NM_OK && req)
-- nm_request_set_data(req, user_record);
--
-- if (req)
-- nm_release_request(req);
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_rename_contact(NMUser * user, NMContact * contact,
-- const char *new_name, nm_response_cb callback,
-- gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *field = NULL, *fields = NULL, *list = NULL;
-- NMRequest *req = NULL;
--
-- if (user == NULL || contact == NULL || new_name == NULL)
-- return NMERR_BAD_PARM;
--
-- /* Create field list for current contact */
-- field = nm_contact_to_fields(contact);
-- if (field) {
--
-- fields =
-- nm_field_add_pointer(fields, NM_A_FA_CONTACT, 0, NMFIELD_METHOD_DELETE, 0,
-- field, NMFIELD_TYPE_ARRAY);
-- field = NULL;
--
-- /* Update the contacts display name locally */
-- nm_contact_set_display_name(contact, new_name);
--
-- /* Create field list for updated contact */
-- field = nm_contact_to_fields(contact);
-- if (field) {
-- fields =
-- nm_field_add_pointer(fields, NM_A_FA_CONTACT, 0, NMFIELD_METHOD_ADD, 0,
-- field, NMFIELD_TYPE_ARRAY);
-- field = NULL;
--
-- /* Package it up */
-- list =
-- nm_field_add_pointer(list, NM_A_FA_CONTACT_LIST, 0, NMFIELD_METHOD_VALID,
-- 0, fields, NMFIELD_TYPE_ARRAY);
-- fields = NULL;
--
-- rc = nm_send_request(user->conn, "updateitem", list, callback, data, &req);
-- if (rc == NM_OK && req)
-- nm_request_set_data(req, contact);
-- }
-- }
--
-- if (req)
-- nm_release_request(req);
--
-- if (list)
-- nm_free_fields(&list);
--
-- return rc;
--}
--
--NMERR_T
--nm_send_rename_folder(NMUser * user, NMFolder * folder, const char *new_name,
-- nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *field = NULL, *fields = NULL, *list = NULL;
-- NMRequest *req = NULL;
--
-- if (user == NULL || folder == NULL || new_name == NULL)
-- return NMERR_BAD_PARM;
--
-- /* Make sure folder does not already exist!? */
-- if (nm_find_folder(user, new_name))
-- return NMERR_FOLDER_EXISTS;
--
-- /* Create field list for current folder */
-- field = nm_folder_to_fields(folder);
-- if (field) {
--
-- fields = nm_field_add_pointer(fields, NM_A_FA_FOLDER, 0, NMFIELD_METHOD_DELETE, 0,
-- field, NMFIELD_TYPE_ARRAY);
-- field = NULL;
--
-- /* Update the folders display name locally */
-- nm_folder_set_name(folder, new_name);
--
-- /* Create field list for updated folder */
-- field = nm_folder_to_fields(folder);
-- if (field) {
-- fields = nm_field_add_pointer(fields, NM_A_FA_FOLDER, 0, NMFIELD_METHOD_ADD, 0,
-- field, NMFIELD_TYPE_ARRAY);
-- field = NULL;
--
-- /* Package it up */
-- list = nm_field_add_pointer(list, NM_A_FA_CONTACT_LIST, 0, NMFIELD_METHOD_VALID,
-- 0, fields, NMFIELD_TYPE_ARRAY);
-- fields = NULL;
--
-- rc = nm_send_request(user->conn, "updateitem", list, callback, data, &req);
-- if (rc == NM_OK && req)
-- nm_request_set_data(req, folder);
-- }
-- }
--
-- if (req)
-- nm_release_request(req);
--
-- if (list)
-- nm_free_fields(&list);
--
-- return rc;
--}
--
--NMERR_T
--nm_send_move_contact(NMUser * user, NMContact * contact, NMFolder * folder,
-- nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *field = NULL, *fields = NULL, *list = NULL;
-- NMRequest *req = NULL;
--
-- if (user == NULL || contact == NULL || folder == NULL)
-- return NMERR_BAD_PARM;
--
-- /* Create field list for the contact */
-- field = nm_contact_to_fields(contact);
-- if (field) {
--
-- fields = nm_field_add_pointer(fields, NM_A_FA_CONTACT, 0, NMFIELD_METHOD_DELETE, 0,
-- field, NMFIELD_TYPE_ARRAY);
-- field = NULL;
--
-- /* Wrap the contact up and add it to the request field list */
-- list = nm_field_add_pointer(list, NM_A_FA_CONTACT_LIST, 0, NMFIELD_METHOD_VALID, 0,
-- fields, NMFIELD_TYPE_ARRAY);
-- fields = NULL;
--
-- /* Add sequence number */
-- list = nm_field_add_pointer(list, NM_A_SZ_SEQUENCE_NUMBER, 0, NMFIELD_METHOD_VALID,
-- 0, g_strdup("-1"), NMFIELD_TYPE_UTF8);
--
-- /* Add parent ID */
-- list = nm_field_add_pointer(list, NM_A_SZ_PARENT_ID, 0, NMFIELD_METHOD_VALID, 0,
-- g_strdup_printf("%d", nm_folder_get_id(folder)),
-- NMFIELD_TYPE_UTF8);
--
-- /* Dispatch the request */
-- rc = nm_send_request(user->conn, "movecontact", list, callback, data, &req);
-- if (rc == NM_OK && req)
-- nm_request_set_data(req, contact);
--
-- }
--
-- if (req)
-- nm_release_request(req);
--
-- if (list)
-- nm_free_fields(&list);
--
-- return rc;
--}
--
--
--NMERR_T
--nm_send_create_privacy_item(NMUser *user, const char *who, gboolean allow_list,
-- nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL;
-- const char *tag;
--
-- if (user == NULL || who == NULL)
-- return NMERR_BAD_PARM;
--
-- if (allow_list)
-- tag = NM_A_SZ_BLOCKING_ALLOW_ITEM;
-- else
-- tag = NM_A_SZ_BLOCKING_DENY_ITEM;
--
-- fields = nm_field_add_pointer(fields, tag, 0, NMFIELD_METHOD_ADD, 0,
-- g_strdup(who), NMFIELD_TYPE_UTF8);
--
-- rc = nm_send_request(user->conn, "createblock", fields, callback, data, NULL);
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_remove_privacy_item(NMUser *user, const char *dn, gboolean allow_list,
-- nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL;
-- const char *tag;
-- GSList **list_ptr, *node;
--
-- if (user == NULL || dn == NULL)
-- return NMERR_BAD_PARM;
--
-- if (allow_list) {
-- tag = NM_A_BLOCKING_ALLOW_LIST;
-- list_ptr = &user->allow_list;
-- } else {
-- tag = NM_A_BLOCKING_DENY_LIST;
-- list_ptr = &user->deny_list;
-- }
--
-- /* Remove item from the cached list */
-- if ((node = g_slist_find_custom(*list_ptr, dn, (GCompareFunc)purple_utf8_strcasecmp))) {
-- *list_ptr = g_slist_remove_link(*list_ptr, node);
-- g_slist_free_1(node);
-- }
--
-- fields = nm_field_add_pointer(fields, tag, 0, NMFIELD_METHOD_DELETE, 0,
-- g_strdup(dn), NMFIELD_TYPE_DN);
--
-- rc = nm_send_request(user->conn, "updateblocks", fields, callback, data, NULL);
--
-- nm_free_fields(&fields);
-- return rc;
--
--}
--
--NMERR_T
--nm_send_set_privacy_default(NMUser *user, gboolean default_deny,
-- nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL;
--
-- if (user == NULL)
-- return NMERR_BAD_PARM;
--
-- fields = nm_field_add_pointer(fields, NM_A_BLOCKING, 0, NMFIELD_METHOD_UPDATE, 0,
-- (default_deny ? g_strdup("1") : g_strdup("0")),
-- NMFIELD_TYPE_UTF8);
--
-- rc = nm_send_request(user->conn, "updateblocks", fields, callback, data, NULL);
--
-- nm_free_fields(&fields);
-- return rc;
--}
--
--NMERR_T
--nm_send_keepalive(NMUser *user, nm_response_cb callback, gpointer data)
--{
-- NMERR_T rc = NM_OK;
--
-- if (user == NULL)
-- return NMERR_BAD_PARM;
--
-- rc = nm_send_request(user->conn, "ping", NULL, callback, data, NULL);
--
-- return rc;
--}
--
--NMERR_T
--nm_process_new_data(NMUser * user)
--{
-- NMConn *conn;
-- NMERR_T rc = NM_OK;
-- guint32 val;
--
-- if (user == NULL)
-- return NMERR_BAD_PARM;
--
-- conn = user->conn;
--
-- /* Check to see if this is an event or a response */
-- rc = nm_read_all(conn, (char *) &val, sizeof(val));
-- if (rc == NM_OK) {
-- if (strncmp((char *) &val, "HTTP", strlen("HTTP")) == 0)
-- rc = nm_process_response(user);
-- else
-- rc = nm_process_event(user, GUINT32_FROM_LE(val));
--
-- } else {
-- if (errno == EAGAIN)
-- rc = NM_OK;
-- else
-- rc = NMERR_PROTOCOL;
-- }
--
-- return rc;
--}
--
--NMConference *
--nm_find_conversation(NMUser * user, const char *who)
--{
-- NMConference *conference = NULL;
-- NMConference *tmp;
-- GSList *cnode;
--
-- if (user && user->conferences) {
-- for (cnode = user->conferences; cnode; cnode = cnode->next) {
-- tmp = cnode->data;
-- if (nm_conference_get_participant_count(tmp) == 1) {
-- NMUserRecord *ur = nm_conference_get_participant(tmp, 0);
--
-- if (ur) {
-- if (nm_utf8_str_equal(nm_user_record_get_dn(ur), who)) {
-- conference = tmp;
-- break;
-- }
-- }
-- }
-- }
-- }
--
-- return conference;
--}
--
--void
--nm_conference_list_add(NMUser * user, NMConference * conf)
--{
-- if (user == NULL || conf == NULL)
-- return;
--
-- nm_conference_add_ref(conf);
-- user->conferences = g_slist_append(user->conferences, conf);
--}
--
--void
--nm_conference_list_remove(NMUser * user, NMConference * conf)
--{
-- if (user == NULL || conf == NULL)
-- return;
--
-- if (g_slist_find(user->conferences, conf)) {
-- user->conferences = g_slist_remove(user->conferences, conf);
-- nm_release_conference(conf);
-- }
--}
--
--void
--nm_conference_list_free(NMUser * user)
--{
-- GSList *cnode;
-- NMConference *conference;
--
-- if (user == NULL)
-- return;
--
-- if (user->conferences) {
-- for (cnode = user->conferences; cnode; cnode = cnode->next) {
-- conference = cnode->data;
-- cnode->data = NULL;
-- nm_release_conference(conference);
-- }
--
-- g_slist_free(user->conferences);
-- user->conferences = NULL;
-- }
--}
--
--NMConference *
--nm_conference_list_find(NMUser * user, const char *guid)
--{
-- GSList *cnode;
-- NMConference *conference = NULL, *tmp;
--
-- if (user == NULL || guid == NULL)
-- return NULL;
--
-- if (user->conferences) {
-- for (cnode = user->conferences; cnode; cnode = cnode->next) {
-- tmp = cnode->data;
-- if (nm_are_guids_equal(nm_conference_get_guid(tmp), guid)) {
-- conference = tmp;
-- break;
-- }
-- }
-- }
--
-- return conference;
--}
--
--gboolean
--nm_are_guids_equal(const char *guid1, const char *guid2)
--{
-- if (guid1 == NULL || guid2 == NULL)
-- return FALSE;
--
-- return (strncmp(guid1, guid2, CONF_GUID_END) == 0);
--}
--
--void
--nm_user_add_contact(NMUser * user, NMContact * contact)
--{
-- if (user == NULL || contact == NULL)
-- return;
--
-- nm_contact_add_ref(contact);
--
-- g_hash_table_insert(user->contacts,
-- g_utf8_strdown(nm_contact_get_dn(contact), -1), contact);
--}
--
--void
--nm_user_add_user_record(NMUser * user, NMUserRecord * user_record)
--{
-- const char *display_id;
-- const char *dn;
--
-- if (!user || !user_record)
-- return;
--
-- display_id = nm_user_record_get_display_id(user_record);
-- dn = nm_user_record_get_dn(user_record);
--
-- if (!dn || !display_id)
-- return;
--
-- nm_user_record_add_ref(user_record);
--
-- g_hash_table_insert(user->user_records,
-- g_utf8_strdown(dn, -1),
-- user_record);
--
-- g_hash_table_insert(user->display_id_to_dn,
-- g_utf8_strdown(display_id, -1),
-- g_utf8_strdown(dn, -1));
--}
--
--nm_event_cb
--nm_user_get_event_callback(NMUser * user)
--{
-- if (user == NULL)
-- return NULL;
--
-- return user->evt_callback;
--}
--
--NMConn *
--nm_user_get_conn(NMUser * user)
--{
-- if (user == NULL)
-- return NULL;
--
-- return user->conn;
--}
--
--NMERR_T
--nm_create_contact_list(NMUser * user)
--{
-- NMERR_T rc = NM_OK;
-- NMField *locate = NULL;
--
-- if (user == NULL || user->fields == NULL) {
-- return NMERR_BAD_PARM;
-- }
--
-- /* Create the root folder */
-- user->root_folder = nm_create_folder("");
--
-- /* Find the contact list in the login fields */
-- locate = nm_locate_field(NM_A_FA_CONTACT_LIST, user->fields);
-- if (locate != NULL) {
--
-- /* Add the folders and then the contacts */
-- nm_folder_add_contacts_and_folders(user, user->root_folder,
-- (NMField *) (locate->ptr_value));
--
-- }
--
-- return rc;
--}
--
--gboolean nm_user_is_privacy_locked(NMUser *user)
--{
-- if (user) {
-- return user->privacy_locked;
-- }
--
-- return FALSE;
--}
--
--static gboolean
--_create_privacy_list(NMUser * user, NMRequest *request)
--{
-- NMField *locate = NULL;
-- GSList *need_details = NULL;
--
-- /* Are the privacy settings locked */
-- locate = nm_locate_field(NM_A_LOCKED_ATTR_LIST, user->fields);
-- if (locate && locate->ptr_value) {
-- if (locate->type == NMFIELD_TYPE_UTF8 &&
-- (purple_utf8_strcasecmp(locate->ptr_value, NM_A_BLOCKING) == 0)) {
-- user->privacy_locked = TRUE;
-- } else if (locate->type == NMFIELD_TYPE_MV ||
-- locate->type == NMFIELD_TYPE_ARRAY) {
-- NMField *tmp = (NMField *)locate->ptr_value;
-- while (tmp && tmp->tag) {
-- if (purple_utf8_strcasecmp(tmp->ptr_value, NM_A_BLOCKING) == 0) {
-- user->privacy_locked = TRUE;
-- break;
-- }
-- tmp++;
-- }
-- }
-- }
--
-- /* Set default deny flag */
-- locate = nm_locate_field(NM_A_BLOCKING, user->fields);
-- if (locate && locate->ptr_value) {
-- user->default_deny = atoi((char *)locate->ptr_value);
-- }
--
-- /* Read internal blocking allow list */
-- locate = nm_locate_field(NM_A_BLOCKING_ALLOW_LIST, user->fields);
-- if (locate && locate->ptr_value) {
--
-- if (locate->type == NMFIELD_TYPE_MV) {
-- locate = (NMField *)locate->ptr_value;
-- for (; locate->tag != NULL; locate++) {
-- if (locate->ptr_value) {
--
-- user->allow_list = g_slist_append(user->allow_list, (char *)locate->ptr_value);
--
-- if (nm_find_user_record(user, (char *)locate->ptr_value) == NULL)
-- need_details = g_slist_append(need_details, (char *)locate->ptr_value);
--
-- }
-- }
-- } else {
--
-- user->allow_list = g_slist_append(user->allow_list, (char *)locate->ptr_value);
--
-- if (nm_find_user_record(user, (char *)locate->ptr_value) == NULL)
-- need_details = g_slist_append(need_details, (char *)locate->ptr_value);
--
-- }
-- }
--
-- /* Read internal blocking deny list */
-- locate = nm_locate_field(NM_A_BLOCKING_DENY_LIST, user->fields);
-- if (locate && locate->ptr_value) {
--
-- if (locate->type == NMFIELD_TYPE_MV) {
-- locate = (NMField *)locate->ptr_value;
-- for (; locate->tag != NULL; locate++) {
-- if (locate->ptr_value) {
--
-- user->deny_list = g_slist_append(user->deny_list, (char *)locate->ptr_value);
--
-- if (nm_find_user_record(user, (char *)locate->ptr_value) == NULL)
-- need_details = g_slist_append(need_details, (char *)locate->ptr_value);
--
-- }
-- }
-- } else {
--
-- user->deny_list = g_slist_append(user->deny_list, (char *)locate->ptr_value);
--
-- if (nm_find_user_record(user, (char *)locate->ptr_value) == NULL)
-- need_details = g_slist_append(need_details, (char *)locate->ptr_value);
--
-- }
-- }
--
-- if (need_details) {
--
-- nm_request_add_ref(request);
-- nm_send_multiple_get_details(user, need_details,
-- _handle_multiple_get_details_login_cb, request);
--
-- return FALSE;
-- }
--
-- return TRUE;
--}
--
--void
--nm_destroy_contact_list(NMUser * user)
--{
-- if (user == NULL)
-- return;
--
-- if (user->root_folder) {
-- nm_release_folder(user->root_folder);
-- user->root_folder = NULL;
-- }
--}
--
--NMFolder *
--nm_get_root_folder(NMUser * user)
--{
-- if (user == NULL)
-- return NULL;
--
-- if (user->root_folder == NULL)
-- nm_create_contact_list(user);
--
-- return user->root_folder;
--}
--
--NMContact *
--nm_find_contact(NMUser * user, const char *name)
--{
-- char *str;
-- const char *dn = NULL;
-- NMContact *contact = NULL;
--
-- if (user == NULL || name == NULL)
-- return NULL;
--
-- str = g_utf8_strdown(name, -1);
-- if (strstr(str, "=")) {
-- dn = str;
-- } else {
-- /* Assume that we have a display id instead of a dn */
-- dn = (const char *) g_hash_table_lookup(user->display_id_to_dn, str);
-- }
--
-- /* Find contact object in reference table */
-- if (dn) {
-- contact = (NMContact *) g_hash_table_lookup(user->contacts, dn);
-- }
--
-- g_free(str);
-- return contact;
--}
--
--GList *
--nm_find_contacts(NMUser * user, const char *dn)
--{
-- guint32 i, cnt;
-- NMFolder *folder;
-- NMContact *contact;
-- GList *contacts = NULL;
--
-- if (user == NULL || dn == NULL)
-- return NULL;
--
-- /* Check for contact at the root */
-- contact = nm_folder_find_contact(user->root_folder, dn);
-- if (contact) {
-- contacts = g_list_append(contacts, contact);
-- contact = NULL;
-- }
--
-- /* Check for contact in each subfolder */
-- cnt = nm_folder_get_subfolder_count(user->root_folder);
-- for (i = 0; i < cnt; i++) {
-- folder = nm_folder_get_subfolder(user->root_folder, i);
-- contact = nm_folder_find_contact(folder, dn);
-- if (contact) {
-- contacts = g_list_append(contacts, contact);
-- contact = NULL;
-- }
-- }
--
-- return contacts;
--}
--
--NMUserRecord *
--nm_find_user_record(NMUser * user, const char *name)
--{
-- char *str = NULL;
-- const char *dn = NULL;
-- NMUserRecord *user_record = NULL;
--
-- if (user == NULL || name == NULL)
-- return NULL;
--
-- str = g_utf8_strdown(name, -1);
-- if (strstr(str, "=")) {
-- dn = str;
-- } else {
-- /* Assume that we have a display id instead of a dn */
-- dn = (const char *) g_hash_table_lookup(user->display_id_to_dn, str);
-- }
--
-- /* Find user record in reference table */
-- if (dn) {
-- user_record =
-- (NMUserRecord *) g_hash_table_lookup(user->user_records, dn);
-- }
--
-- g_free(str);
-- return user_record;
--}
--
--const char *
--nm_lookup_dn(NMUser * user, const char *display_id)
--{
-- const char *dn;
-- char *lower;
--
-- if (user == NULL || display_id == NULL)
-- return NULL;
--
-- lower = g_utf8_strdown(display_id, -1);
-- dn = g_hash_table_lookup(user->display_id_to_dn, lower);
-- g_free(lower);
--
-- return dn;
--}
--
--NMFolder *
--nm_find_folder(NMUser * user, const char *name)
--{
-- NMFolder *folder = NULL, *temp;
-- int i, num_folders;
-- const char *tname = NULL;
--
-- if (user == NULL || name == NULL)
-- return NULL;
--
-- if (*name == '\0')
-- return user->root_folder;
--
-- num_folders = nm_folder_get_subfolder_count(user->root_folder);
-- for (i = 0; i < num_folders; i++) {
-- temp = nm_folder_get_subfolder(user->root_folder, i);
-- tname = nm_folder_get_name(temp);
-- if (tname && (strcmp(tname, name) == 0)) {
-- folder = temp;
-- break;
-- }
-- }
--
-- return folder;
--}
--
--NMFolder *
--nm_find_folder_by_id(NMUser * user, int object_id)
--{
-- NMFolder *folder = NULL, *temp;
-- int i, num_folders;
--
-- if (user == NULL)
-- return NULL;
--
-- if (object_id == 0)
-- return user->root_folder;
--
-- num_folders = nm_folder_get_subfolder_count(user->root_folder);
-- for (i = 0; i < num_folders; i++) {
-- temp = nm_folder_get_subfolder(user->root_folder, i);
-- if (nm_folder_get_id(temp) == object_id) {
-- folder = temp;
-- break;
-- }
-- }
--
-- return folder;
--}
--
--static void
--_handle_multiple_get_details_login_cb(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- nm_response_cb cb;
-- NMRequest *request = user_data;
--
-- if (user == NULL || request == NULL)
-- return;
--
-- if ((cb = nm_request_get_callback(request))) {
-- cb(user, ret_code, nm_request_get_data(request),
-- nm_request_get_user_define(request));
-- nm_release_request(request);
-- }
--}
--
--static void
--_handle_multiple_get_details_joinconf_cb(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- NMRequest *request = user_data;
-- NMUserRecord *user_record = resp_data;
-- NMConference *conference;
-- GSList *list, *node;
--
-- if (user == NULL || resp_data == NULL || user_data == NULL)
-- return;
--
-- conference = nm_request_get_data(request);
-- list = nm_request_get_user_define(request);
--
-- if (ret_code == 0 && conference && list) {
--
-- /* Add the user to the conference */
-- nm_conference_add_participant(conference, user_record);
--
-- /* Find the user in the list and remove it */
-- for (node = list; node; node = node->next) {
-- if (nm_utf8_str_equal(nm_user_record_get_dn(user_record),
-- (const char *) node->data)) {
-- g_free(node->data);
-- list = g_slist_remove(list, node->data);
-- nm_request_set_user_define(request, list);
-- break;
-- }
-- }
--
-- /* Time to callback? */
-- if (list == NULL) {
-- nm_response_cb cb = nm_request_get_callback(request);
--
-- if (cb) {
-- cb(user, 0, conference, conference);
-- }
-- nm_release_request(request);
-- }
-- }
--}
--
--static NMERR_T
--nm_call_handler(NMUser * user, NMRequest * request, NMField * fields)
--{
-- NMERR_T rc = NM_OK, ret_code = NM_OK;
-- NMConference *conf = NULL;
-- NMUserRecord *user_record = NULL;
-- NMField *locate = NULL;
-- NMField *field = NULL;
-- const char *cmd;
-- nm_response_cb cb;
-- gboolean done = TRUE;
--
-- if (user == NULL || request == NULL || fields == NULL)
-- return NMERR_BAD_PARM;
--
-- /* Get the return code */
-- field = nm_locate_field(NM_A_SZ_RESULT_CODE, fields);
-- if (field) {
-- ret_code = atoi((char *) field->ptr_value);
-- } else {
-- ret_code = NMERR_PROTOCOL;
-- }
--
-- cmd = nm_request_get_cmd(request);
-- if (ret_code == NM_OK && cmd != NULL) {
--
-- if (strcmp("login", cmd) == 0) {
--
-- user->user_record = nm_create_user_record_from_fields(fields);
--
-- /* Save the users fields */
-- user->fields = nm_copy_field_array(fields);
--
-- nm_create_contact_list(user);
-- done = _create_privacy_list(user, request);
--
-- } else if (strcmp("setstatus", cmd) == 0) {
--
-- /* Nothing to do */
--
-- } else if (strcmp("createconf", cmd) == 0) {
--
-- conf = (NMConference *) nm_request_get_data(request);
--
-- /* get the convo guid */
-- locate = nm_locate_field(NM_A_FA_CONVERSATION, fields);
-- if (locate) {
-- field =
-- nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) fields->ptr_value);
-- if (field) {
-- nm_conference_set_guid(conf, (char *) field->ptr_value);
-- }
-- }
--
-- nm_conference_list_add(user, conf);
-- nm_release_conference(conf);
--
-- } else if (strcmp("leaveconf", cmd) == 0) {
--
-- conf = (NMConference *) nm_request_get_data(request);
-- nm_conference_list_remove(user, conf);
--
-- } else if (strcmp("joinconf", cmd) == 0) {
-- GSList *list = NULL, *node;
--
-- conf = nm_request_get_data(request);
--
-- locate = nm_locate_field(NM_A_FA_CONTACT_LIST, fields);
-- if (locate && locate->ptr_value != 0) {
--
-- field = (NMField *) locate->ptr_value;
-- while ((field = nm_locate_field(NM_A_SZ_DN, field))) {
-- if (field && field->ptr_value != 0) {
--
-- if (nm_utf8_str_equal
-- (nm_user_record_get_dn(user->user_record),
-- (const char *) field->ptr_value)) {
-- field++;
-- continue;
-- }
--
-- user_record =
-- nm_find_user_record(user,
-- (const char *) field->ptr_value);
-- if (user_record == NULL) {
-- list =
-- g_slist_append(list,
-- g_strdup((char *) field->ptr_value));
-- } else {
-- nm_conference_add_participant(conf, user_record);
-- }
-- }
-- field++;
-- }
--
-- if (list != NULL) {
--
-- done = FALSE;
-- nm_request_set_user_define(request, list);
-- nm_request_add_ref(request);
-- for (node = list; node; node = node->next) {
--
-- nm_send_get_details(user, (const char *) node->data,
-- _handle_multiple_get_details_joinconf_cb,
-- request);
-- }
-- }
-- }
--
-- } else if (strcmp("getdetails", cmd) == 0) {
--
-- locate = nm_locate_field(NM_A_FA_RESULTS, fields);
-- while (locate && locate->ptr_value != 0) {
--
-- user_record = nm_create_user_record_from_fields(locate);
-- if (user_record) {
-- NMUserRecord *tmp;
--
-- tmp =
-- nm_find_user_record(user,
-- nm_user_record_get_dn(user_record));
-- if (tmp) {
--
-- /* Update the existing user record */
-- nm_user_record_copy(tmp, user_record);
-- nm_release_user_record(user_record);
-- user_record = tmp;
--
-- } else {
-- nm_user_add_user_record(user, user_record);
-- nm_release_user_record(user_record);
-- }
--
-- /* Response data is new user record */
-- nm_request_set_data(request, (gpointer) user_record);
-- }
--
-- locate = nm_locate_field(NM_A_FA_RESULTS, locate+1);
-- }
--
-- } else if (strcmp("createfolder", cmd) == 0) {
--
-- _update_contact_list(user, fields);
--
-- } else if (strcmp("createcontact", cmd) == 0) {
--
-- _update_contact_list(user, fields);
--
-- locate =
-- nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) fields->ptr_value);
-- if (locate) {
--
-- NMContact *new_contact =
-- nm_folder_find_item_by_object_id(user->root_folder,
-- atoi((char *)locate->ptr_value));
--
-- if (new_contact) {
--
-- /* Add the contact to our cache */
-- nm_user_add_contact(user, new_contact);
--
-- /* Set the contact as the response data */
-- nm_request_set_data(request, (gpointer) new_contact);
--
-- }
--
-- }
--
-- } else if (strcmp("deletecontact", cmd) == 0) {
--
-- _update_contact_list(user, fields);
--
-- } else if (strcmp("movecontact", cmd) == 0) {
--
-- _update_contact_list(user, fields);
--
-- } else if (strcmp("getstatus", cmd) == 0) {
--
-- locate = nm_locate_field(NM_A_SZ_STATUS, fields);
-- if (locate) {
-- nm_user_record_set_status((NMUserRecord *)
-- nm_request_get_data(request),
-- atoi((char *) locate->ptr_value), NULL);
-- }
--
-- } else if (strcmp("updateitem", cmd) == 0) {
--
-- /* Nothing extra to do here */
--
-- } else if (strcmp("createblock", cmd) == 0) {
-- if ((locate = nm_locate_field(NM_A_BLOCKING_DENY_LIST, fields))) {
-- if (locate->ptr_value) {
-- user->deny_list = g_slist_append(user->deny_list, g_strdup((char *)locate->ptr_value));
-- }
-- } else if ((locate = nm_locate_field(NM_A_BLOCKING_ALLOW_LIST, fields))) {
-- if (locate->ptr_value) {
-- user->allow_list = g_slist_append(user->allow_list, g_strdup((char *)locate->ptr_value));
-- }
-- }
-- } else if (strcmp("updateblocks", cmd) == 0) {
-- /* nothing to do here */
-- } else {
--
-- /* Nothing to do, just print debug message */
-- purple_debug(PURPLE_DEBUG_INFO, "novell",
-- "nm_call_handler(): Unknown request command, %s\n", cmd);
--
-- }
-- }
--
-- if (done && (cb = nm_request_get_callback(request))) {
--
-- cb(user, ret_code, nm_request_get_data(request),
-- nm_request_get_user_define(request));
-- }
--
-- return rc;
--}
--
--static NMERR_T
--nm_process_response(NMUser * user)
--{
-- NMERR_T rc = NM_OK;
-- NMField *fields = NULL;
-- NMField *field = NULL;
-- NMConn *conn = user->conn;
-- NMRequest *req = NULL;
--
-- rc = nm_read_header(conn);
-- if (rc == NM_OK) {
-- rc = nm_read_fields(conn, -1, &fields);
-- }
--
-- if (rc == NM_OK) {
-- field = nm_locate_field(NM_A_SZ_TRANSACTION_ID, fields);
-- if (field != NULL && field->ptr_value != 0) {
-- req = nm_conn_find_request(conn, atoi((char *) field->ptr_value));
-- if (req != NULL) {
-- rc = nm_call_handler(user, req, fields);
-- nm_conn_remove_request_item(conn, req);
-- }
--
-- }
-- }
--
-- if (fields)
-- nm_free_fields(&fields);
--
-- return rc;
--}
--
--/*
-- * Some utility functions...haven't figured out where
-- * they belong yet.
-- */
--
--gboolean
--nm_utf8_str_equal(gconstpointer str1, gconstpointer str2)
--{
-- return (purple_utf8_strcasecmp(str1, str2) == 0);
--}
--
--char *
--nm_typed_to_dotted(const char *typed)
--{
-- unsigned i = 0, j = 0;
-- char *dotted;
--
-- if (typed == NULL)
-- return NULL;
--
-- dotted = g_new0(char, strlen(typed));
--
-- do {
--
-- /* replace comma with a dot */
-- if (j != 0) {
-- dotted[j] = '.';
-- j++;
-- }
--
-- /* skip the type */
-- while (typed[i] != '\0' && typed[i] != '=')
-- i++;
--
-- /* verify that we aren't running off the end */
-- if (typed[i] == '\0') {
-- dotted[j] = '\0';
-- break;
-- }
--
-- i++;
--
-- /* copy the object name to context */
-- while (typed[i] != '\0' && typed[i] != ',') {
-- dotted[j] = typed[i];
-- j++;
-- i++;
-- }
--
-- } while (typed[i] != '\0');
--
-- return dotted;
--}
--
--const char *
--nm_error_to_string(NMERR_T err)
--{
-- static char *unknown_msg = NULL;
--
-- g_free(unknown_msg);
-- unknown_msg = NULL;
--
-- switch (err) {
--
-- case NMERR_BAD_PARM:
-- return _("Required parameters not passed in");
--
-- case NMERR_TCP_WRITE:
-- return _("Unable to write to network");
--
-- case NMERR_TCP_READ:
-- return _("Unable to read from network");
--
-- case NMERR_PROTOCOL:
-- return _("Error communicating with server");
--
-- case NMERR_CONFERENCE_NOT_FOUND:
-- case NMERR_CONFERENCE_NOT_FOUND_2:
-- return _("Conference not found");
--
-- case NMERR_CONFERENCE_NOT_INSTANTIATED:
-- return _("Conference does not exist");
--
-- case NMERR_DUPLICATE_FOLDER:
-- case NMERR_FOLDER_EXISTS:
-- return _("A folder with that name already exists");
--
-- case NMERR_NOT_SUPPORTED:
-- return _("Not supported");
--
-- case NMERR_PASSWORD_EXPIRED:
-- case NMERR_PASSWORD_EXPIRED_2:
-- return _("Password has expired");
--
-- case NMERR_PASSWORD_INVALID:
-- return _("Incorrect password");
--
-- case NMERR_USER_NOT_FOUND:
-- return _("User not found");
--
-- case NMERR_USER_DISABLED:
-- return _("Account has been disabled");
--
-- case NMERR_DIRECTORY_FAILURE:
-- return _("The server could not access the directory");
--
-- case NMERR_ADMIN_LOCKED:
-- return _("Your system administrator has disabled this operation");
--
-- case NMERR_SERVER_BUSY:
-- return _("The server is unavailable; try again later");
--
-- case NMERR_DUPLICATE_CONTACT:
-- return _("Cannot add a contact to the same folder twice");
--
-- case NMERR_USER_NOT_ALLOWED:
-- return _("Cannot add yourself");
--
-- case NMERR_MASTER_ARCHIVE_MISSING:
-- return _("Master archive is misconfigured");
--
-- case NMERR_AUTHENTICATION_FAILED:
-- case NMERR_CREDENTIALS_MISSING:
-- return _("Incorrect username or password");
--
-- case NMERR_HOST_NOT_FOUND:
-- return _("Could not recognize the host of the username you entered");
--
-- case NMERR_ACCESS_DENIED:
-- return _("Your account has been disabled because too many incorrect passwords were entered");
--
-- case NMERR_DUPLICATE_PARTICIPANT:
-- return _("You cannot add the same person twice to a conversation");
--
-- case NMERR_TOO_MANY_CONTACTS:
-- case NMERR_TOO_MANY_FOLDERS:
-- return _("You have reached your limit for the number of contacts allowed");
--
-- case NMERR_OBJECT_NOT_FOUND:
-- return _("You have entered an incorrect username");
--
-- case NMERR_DIRECTORY_UPDATE:
-- return _("An error occurred while updating the directory");
--
-- case NMERR_SERVER_PROTOCOL:
-- return _("Incompatible protocol version");
--
-- case NMERR_USER_BLOCKED:
-- return _("The user has blocked you");
--
-- case NMERR_EVAL_CONNECTION_LIMIT:
-- return _("This evaluation version does not allow more than ten users to log in at one time");
--
-- case NMERR_CONVERSATION_INVITE:
-- return _("The user is either offline or you are blocked");
--
-- default:
-- unknown_msg = g_strdup_printf (_("Unknown error: 0x%X"), err);
--
-- return unknown_msg;
-- }
--}
--
--static void
--_update_contact_list(NMUser * user, NMField * fields)
--{
-- NMField *list, *cursor, *locate;
-- gint objid1;
-- NMContact *contact;
-- NMFolder *folder;
-- gpointer item;
--
-- if (user == NULL || fields == NULL)
-- return;
--
-- /* Is it wrapped in a RESULTS array? */
-- if (strcmp(fields->tag, NM_A_FA_RESULTS) == 0) {
-- list = (NMField *) fields->ptr_value;
-- } else {
-- list = fields;
-- }
--
-- /* Update the cached contact list */
-- cursor = (NMField *) list->ptr_value;
-- while (cursor->tag != NULL) {
-- if ((g_ascii_strcasecmp(cursor->tag, NM_A_FA_CONTACT) == 0) ||
-- (g_ascii_strcasecmp(cursor->tag, NM_A_FA_FOLDER) == 0)) {
--
-- locate =
-- nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) cursor->ptr_value);
-- if (locate != NULL && locate->ptr_value != 0) {
-- objid1 = atoi((char *) locate->ptr_value);
-- item =
-- nm_folder_find_item_by_object_id(user->root_folder, objid1);
-- if (item != NULL) {
-- if (cursor->method == NMFIELD_METHOD_ADD) {
-- if (g_ascii_strcasecmp(cursor->tag, NM_A_FA_CONTACT) == 0) {
-- contact = (NMContact *) item;
-- nm_contact_update_list_properties(contact, cursor);
-- } else if (g_ascii_strcasecmp(cursor->tag, NM_A_FA_FOLDER)
-- == 0) {
-- folder = (NMFolder *) item;
-- nm_folder_update_list_properties(folder, cursor);
-- }
-- } else if (cursor->method == NMFIELD_METHOD_DELETE) {
-- if (g_ascii_strcasecmp(cursor->tag, NM_A_FA_CONTACT) == 0) {
-- contact = (NMContact *) item;
-- folder =
-- nm_find_folder_by_id(user,
-- nm_contact_get_parent_id
-- (contact));
-- if (folder) {
-- nm_folder_remove_contact(folder, contact);
-- }
-- } else if (g_ascii_strcasecmp(cursor->tag, NM_A_FA_FOLDER)
-- == 0) {
-- /* TODO: write nm_folder_remove_folder */
-- /* ignoring for now, should not be a big deal */
--/* folder = (NMFolder *) item;*/
--/* nm_folder_remove_folder(user->root_folder, folder);*/
-- }
-- }
-- } else {
--
-- if (cursor->method == NMFIELD_METHOD_ADD) {
--
-- /* Not found, so we need to add it */
-- if (g_ascii_strcasecmp(cursor->tag, NM_A_FA_CONTACT) == 0) {
--
-- const char *dn = NULL;
--
-- locate =
-- nm_locate_field(NM_A_SZ_DN,
-- (NMField *) cursor->ptr_value);
-- if (locate != NULL && locate->ptr_value != 0) {
-- dn = (const char *) locate->ptr_value;
-- if (dn != NULL) {
-- contact =
-- nm_create_contact_from_fields(cursor);
-- if (contact) {
-- nm_folder_add_contact_to_list(user->
-- root_folder,
-- contact);
-- nm_release_contact(contact);
-- }
-- }
-- }
-- } else if (g_ascii_strcasecmp(cursor->tag, NM_A_FA_FOLDER)
-- == 0) {
-- folder = nm_create_folder_from_fields(cursor);
-- nm_folder_add_folder_to_list(user->root_folder,
-- folder);
-- nm_release_folder(folder);
-- }
-- }
-- }
-- }
-- }
-- cursor++;
-- }
--}
--
--static char *
--nm_rtfize_text(char *text)
--{
-- GString *gstr = NULL;
-- unsigned char *pch;
-- char *uni_str = NULL, *rtf = NULL;
-- int bytes;
-- gunichar uc;
--
-- gstr = g_string_sized_new(strlen(text)*2);
-- pch = (unsigned char *)text;
-- while (*pch) {
-- if ((*pch) <= 0x7F) {
-- switch (*pch) {
-- case '{':
-- case '}':
-- case '\\':
-- gstr = g_string_append_c(gstr, '\\');
-- gstr = g_string_append_c(gstr, *pch);
-- break;
-- case '\n':
-- gstr = g_string_append(gstr, "\\par ");
-- break;
-- default:
-- gstr = g_string_append_c(gstr, *pch);
-- break;
-- }
-- pch++;
-- } else {
-- /* convert the utf-8 character to ucs-4 for rtf encoding */
-- if(*pch <= 0xDF) {
-- uc = ((((gunichar)pch[0]) & 0x001F) << 6) |
-- (((gunichar)pch[1]) & 0x003F);
-- bytes = 2;
-- } else if(*pch <= 0xEF) {
-- uc = ((((gunichar)pch[0]) & 0x000F) << 12) |
-- ((((gunichar)pch[1]) & 0x003F) << 6) |
-- (((gunichar)pch[2]) & 0x003F);
-- bytes = 3;
-- } else if (*pch <= 0xF7) {
-- uc = ((((gunichar)pch[0]) & 0x0007) << 18) |
-- ((((gunichar)pch[1]) & 0x003F) << 12) |
-- ((((gunichar)pch[2]) & 0x003F) << 6) |
-- (((gunichar)pch[3]) & 0x003F);
-- bytes = 4;
-- } else if (*pch <= 0xFB) {
-- uc = ((((gunichar)pch[0]) & 0x0003) << 24) |
-- ((((gunichar)pch[1]) & 0x003F) << 18) |
-- ((((gunichar)pch[2]) & 0x003F) << 12) |
-- ((((gunichar)pch[3]) & 0x003F) << 6) |
-- (((gunichar)pch[4]) & 0x003F);
-- bytes = 5;
-- } else if (*pch <= 0xFD) {
-- uc = ((((gunichar)pch[0]) & 0x0001) << 30) |
-- ((((gunichar)pch[1]) & 0x003F) << 24) |
-- ((((gunichar)pch[2]) & 0x003F) << 18) |
-- ((((gunichar)pch[3]) & 0x003F) << 12) |
-- ((((gunichar)pch[4]) & 0x003F) << 6) |
-- (((gunichar)pch[5]) & 0x003F);
-- bytes = 6;
-- } else {
-- /* should never happen ... bogus utf-8! */
-- purple_debug_info("novell", "bogus utf-8 lead byte: 0x%X\n", pch[0]);
-- uc = 0x003F;
-- bytes = 1;
-- }
-- uni_str = g_strdup_printf("\\u%d?", uc);
-- purple_debug_info("novell", "unicode escaped char %s\n", uni_str);
-- gstr = g_string_append(gstr, uni_str);
-- pch += bytes;
-- g_free(uni_str);
-- }
-- }
--
-- rtf = g_strdup_printf(RTF_TEMPLATE, gstr->str);
-- g_string_free(gstr, TRUE);
-- return rtf;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmuser.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmuser.h
---- pidgin-2.10.7/libpurple/protocols/novell/nmuser.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmuser.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,680 +0,0 @@
--/*
-- * nmuser.h
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#ifndef __NM_USER_H__
--#define __NM_USER_H__
--
--#include <glib.h>
--#include <stdio.h>
--#include <stdlib.h>
--
--typedef guint32 NMERR_T;
--typedef int NMSTATUS_T;
--
--typedef struct _NMUser NMUser;
--
--typedef enum
--{
-- NMREQUEST_TYPE_LOGIN = 0,
-- NMREQUEST_TYPE_LOGOUT,
-- NMREQUEST_TYPE_SETSTATUS,
-- NMREQUEST_TYPE_GETDETAILS,
-- NMREQUEST_TYPE_CREATECONF,
-- NMREQUEST_TYPE_SENDMESSAGE,
-- NMREQUEST_TYPE_JOINCONF,
-- NMREQUEST_TYPE_LEAVECONF,
-- NMREQUEST_TYPE_REJECTCONF,
-- NMREQUEST_TYPE_SENDTYPING,
-- NMREQUEST_TYPE_CREATECONTACT,
-- NMREQUEST_TYPE_DELETECONTACT
--
--} NMRequestType;
--
--#include "debug.h"
--#include "nmmessage.h"
--#include "nmconference.h"
--#include "nmcontact.h"
--#include "nmuserrecord.h"
--#include "nmfield.h"
--#include "nmevent.h"
--
--/* Callback typedefs */
--typedef void (*nm_response_cb) (NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data);
--
--typedef void (*nm_event_cb) (NMUser * user, NMEvent * event);
--
--#include "nmrequest.h"
--#include "nmconn.h"
--
--/* This represents user that we are currently logged in as */
--struct _NMUser
--{
--
-- char *name;
--
-- NMSTATUS_T status;
--
-- /* A copy of the login response fields */
-- NMField *fields;
--
-- /* The user record for this user */
-- NMUserRecord *user_record;
--
-- /* Our connection information */
-- NMConn *conn;
--
-- /* Our public IP address */
-- char *address;
--
-- /* This is the contact list */
-- NMFolder *root_folder;
--
-- /* All contacts that we know about hashed by dn */
-- GHashTable *contacts;
--
-- /* All user records hashed by dn */
-- GHashTable *user_records;
--
-- /* DN lookup */
-- GHashTable *display_id_to_dn;
--
-- /* One on one conversations indexed by recipient's dn */
-- GSList *conferences;
--
-- guint32 conference_count;
--
-- /* Called when we receive an event */
-- nm_event_cb evt_callback;
--
-- /* Privacy settings */
-- gboolean privacy_locked;
-- gboolean default_deny;
-- GSList *allow_list;
-- GSList *deny_list;
--
-- /* Pending requests. If we need to go to the server to more info
-- * before processing a request we will queue it up and process when
-- * we get a response
-- */
-- GSList *pending_requests;
--
-- /* Pending events. Same as above except for events. */
-- GSList *pending_events;
--
-- /* Generic pointer to data needed by the client
-- * using the API
-- */
-- gpointer client_data;
--
-- /* Have the privacy lists been synched yet */
-- gboolean privacy_synched;
--
-- /* Has the contact list been synched */
-- gboolean clist_synched;
--};
--
--#define NM_STATUS_UNKNOWN 0
--#define NM_STATUS_OFFLINE 1
--#define NM_STATUS_AVAILABLE 2
--#define NM_STATUS_BUSY 3
--#define NM_STATUS_AWAY 4
--#define NM_STATUS_AWAY_IDLE 5
--#define NM_STATUS_INVALID 6
--
--#define NMERR_BASE 0x2000L
--#define NM_OK 0L
--#define NMERR_BAD_PARM (NMERR_BASE + 0x0001)
--#define NMERR_TCP_WRITE (NMERR_BASE + 0x0002)
--#define NMERR_TCP_READ (NMERR_BASE + 0x0003)
--#define NMERR_PROTOCOL (NMERR_BASE + 0x0004)
--#define NMERR_SERVER_REDIRECT (NMERR_BASE + 0x0005)
--#define NMERR_CONFERENCE_NOT_FOUND (NMERR_BASE + 0x0006)
--#define NMERR_CONFERENCE_NOT_INSTANTIATED (NMERR_BASE + 0x0007)
--#define NMERR_FOLDER_EXISTS (NMERR_BASE + 0x0008)
--
--/* Errors that are returned from the server */
--#define NMERR_SERVER_BASE 0xD100L
--#define NMERR_ACCESS_DENIED (NMERR_SERVER_BASE + 0x0006)
--#define NMERR_NOT_SUPPORTED (NMERR_SERVER_BASE + 0x000A)
--#define NMERR_PASSWORD_EXPIRED (NMERR_SERVER_BASE + 0x000B)
--#define NMERR_PASSWORD_INVALID (NMERR_SERVER_BASE + 0x000C)
--#define NMERR_USER_NOT_FOUND (NMERR_SERVER_BASE + 0x000D)
--#define NMERR_USER_DISABLED (NMERR_SERVER_BASE + 0x0010)
--#define NMERR_DIRECTORY_FAILURE (NMERR_SERVER_BASE + 0x0011)
--#define NMERR_HOST_NOT_FOUND (NMERR_SERVER_BASE + 0x0019)
--#define NMERR_ADMIN_LOCKED (NMERR_SERVER_BASE + 0x001C)
--#define NMERR_DUPLICATE_PARTICIPANT (NMERR_SERVER_BASE + 0x001F)
--#define NMERR_SERVER_BUSY (NMERR_SERVER_BASE + 0x0023)
--#define NMERR_OBJECT_NOT_FOUND (NMERR_SERVER_BASE + 0x0024)
--#define NMERR_DIRECTORY_UPDATE (NMERR_SERVER_BASE + 0x0025)
--#define NMERR_DUPLICATE_FOLDER (NMERR_SERVER_BASE + 0x0026)
--#define NMERR_DUPLICATE_CONTACT (NMERR_SERVER_BASE + 0x0027)
--#define NMERR_USER_NOT_ALLOWED (NMERR_SERVER_BASE + 0x0028)
--#define NMERR_TOO_MANY_CONTACTS (NMERR_SERVER_BASE + 0x0029)
--#define NMERR_CONFERENCE_NOT_FOUND_2 (NMERR_SERVER_BASE + 0x002B)
--#define NMERR_TOO_MANY_FOLDERS (NMERR_SERVER_BASE + 0x002C)
--#define NMERR_SERVER_PROTOCOL (NMERR_SERVER_BASE + 0x0030)
--#define NMERR_CONVERSATION_INVITE (NMERR_SERVER_BASE + 0x0035)
--#define NMERR_USER_BLOCKED (NMERR_SERVER_BASE + 0x0039)
--#define NMERR_MASTER_ARCHIVE_MISSING (NMERR_SERVER_BASE + 0x003A)
--#define NMERR_PASSWORD_EXPIRED_2 (NMERR_SERVER_BASE + 0x0042)
--#define NMERR_CREDENTIALS_MISSING (NMERR_SERVER_BASE + 0x0046)
--#define NMERR_AUTHENTICATION_FAILED (NMERR_SERVER_BASE + 0x0049)
--#define NMERR_EVAL_CONNECTION_LIMIT (NMERR_SERVER_BASE + 0x004A)
--
--/**
-- * Initialize the user that we are going to login to the system as.
-- *
-- * @param name The userid of the user
-- * @param server IP Address of server
-- * @param port Port to connect to on the server
-- * @param data Client data to associate with the user
-- * @param event_callback Function to call when we receive an event
-- *
-- * @return The initialized user object. Must be freed by calling
-- * nm_deinitialize_user
-- */
--NMUser *nm_initialize_user(const char *name, const char *server, int port,
-- gpointer data, nm_event_cb event_callback);
--
--
--/**
-- * Free up resources associated with the user object.
-- *
-- * @param user The user to deinitialize
-- */
--void nm_deinitialize_user(NMUser * user);
--
--/**
-- * Send a login request to the server.
-- *
-- * The response data sent to the callback will be NULL.
-- *
-- * @param user The User to login -- must be initialized
-- * @param pwd The password of the user
-- * @param my_addr The address of the client machine
-- * @param user_agent String describing the client (eg. "Purple/0.76 (Linux; 2.4.20)")
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data to be passed to the callback function
-- *
-- *
-- * @return NM_OK if login is sent successfully, error otherwise.
-- */
--NMERR_T nm_send_login(NMUser * user, const char *pwd, const char *my_addr,
-- const char *user_agent, nm_response_cb callback,
-- gpointer data);
--
--/**
-- * Send a set status request to the server.
-- *
-- * The response data sent to the callback will be NULL.
-- *
-- * @param user The logged in User
-- * @param dn The DN of the user (if known, or NULL if not known)
-- * @param address IP Address of server
-- * @param callback Function to call when we get the response from the server
-- *
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_set_status(NMUser * user, int status, const char *text,
-- const char *auto_resp, nm_response_cb callback,
-- gpointer data);
--
--/**
-- * Send a create conference to the server.
-- *
-- * The response data sent to the callback will be NULL.
-- *
-- * @param user The logged in User
-- * @param conference Conference to create
-- * @param add_participants Add participant list on create?
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data to be passed to the callback function
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_create_conference(NMUser * user, NMConference * conference,
-- nm_response_cb callback, gpointer data);
--
--/**
-- * Tell server we have left the conference.
-- *
-- * The response data sent to the callback will be NULL.
-- *
-- * @param user The logged in User
-- * @param conference Conference the user is leaving
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data to be passed to the callback function
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_leave_conference(NMUser * user, NMConference * conference,
-- nm_response_cb callback, gpointer data);
--
--/**
-- * Send a join conference request to the server.
-- *
-- * The response data sent to the callback will be NULL.
-- *
-- * @param user The logged in User
-- * @param conference Conference the user is joining
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data to be passed to the callback function
-- *
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_join_conference(NMUser * user, NMConference * conference,
-- nm_response_cb callback, gpointer data);
--
--/**
-- * Send a conference reject request to the server.
-- *
-- * The response data sent to the callback will be NULL.
-- *
-- * @param user The logged in User
-- * @param conference Conference the user is rejecting
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data to be passed to the callback function
-- *
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_reject_conference(NMUser * user, NMConference * conference,
-- nm_response_cb callback, gpointer data);
--
--
--/**
-- * Send a conference invitation to the server.
-- *
-- * The response data sent to the callback will be NULL.
-- *
-- * @param user The logged in User
-- * @param conference Conference the user is rejecting
-- * @param user_record The user to invite
-- * @param message The invite message if there is one, NULL otherwise
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data to be passed to the callback function
-- *
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_conference_invite(NMUser *user, NMConference *conference, NMUserRecord *user_record,
-- const char *message, nm_response_cb callback, gpointer data);
--
--/**
-- * Get details for a more than one user from the server.
-- *
-- * The response data sent to the callback will be an NMUserRecord which should be
-- * freed with nm_release_user_record
-- *
-- * @param user The logged in User
-- * @param names Link list of user id's or dn's
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data to be passed to the callback function
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_multiple_get_details(NMUser * user, GSList *names,
-- nm_response_cb callback, gpointer data);
--
--/**
-- * Get details for a user from the server.
-- *
-- * The response data sent to the callback will be an NMUserRecord which should be
-- * freed with nm_release_user_record
-- *
-- * @param user The logged in User
-- * @param name Userid or DN of the user to look up
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data to be passed to the callback function
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_get_details(NMUser * user, const char *name,
-- nm_response_cb callback, gpointer data);
--
--/**
-- * Send a message.
-- *
-- * The response data sent to the callback will be NULL.
-- *
-- * @param user The logged in User
-- * @param message The message to send.
-- * @param callback Function to call when we get the response from the server
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_message(NMUser * user, NMMessage * message,
-- nm_response_cb callback);
--
--/**
-- * Sends a typing event to the server.
-- *
-- * The response data sent to the callback will be NULL.
-- *
-- * @param user The logged in User
-- * @param conf The conference that corresponds to the typing event
-- * @param typing TRUE if the user is typing
-- * FALSE if the user has stopped typing
-- * @param callback Function to call when we get the response from the server
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_typing(NMUser * user, NMConference * conf,
-- gboolean typing, nm_response_cb callback);
--
--/**
-- * Send a create contact request to the server.
-- *
-- * The given folder should already exist on the server. If not,
-- * the call will fail.
-- *
-- * The response data sent to the callback will be a NMContact which should
-- * be released with nm_release_contact
-- *
-- * @param user The logged in User
-- * @param folder The folder that the contact should be created in
-- * @param contact The contact to add
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_create_contact(NMUser * user, NMFolder * folder,
-- NMContact * contact, nm_response_cb callback,
-- gpointer data);
--
--/**
-- * Send a remove contact request to the server.
-- *
-- * The response data sent to the callback will be NULL.
-- *
-- * @param user The logged in User
-- * @param folder The folder to remove contact from
-- * @param contact The contact to remove
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_remove_contact(NMUser * user, NMFolder * folder,
-- NMContact * contact, nm_response_cb callback,
-- gpointer data);
--
--/**
-- * Send a create folder request to the server.
-- *
-- * The response data sent to the callback will be a NMFolder which should be
-- * released with nm_release_folder
-- *
-- * @param user The logged in User
-- * @param name The name of the folder to create
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_create_folder(NMUser * user, const char *name,
-- nm_response_cb callback, gpointer data);
--
--/**
-- * Send a delete folder request to the server.
-- *
-- * The response data sent to the callback will be NULL.
-- *
-- * @param user The logged in User
-- * @param folder The name of the folder to remove
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_remove_folder(NMUser * user, NMFolder * folder,
-- nm_response_cb callback, gpointer data);
--
--/**
-- * Send a rename contact request to the server.
-- *
-- * The response data sent to the callback will be NULL.
-- *
-- * @param user The logged in User
-- * @param contact The contact to rename
-- * @param new_name The new display name for the contact
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_rename_contact(NMUser * user, NMContact * contact,
-- const char *new_name, nm_response_cb callback,
-- gpointer data);
--
--/**
-- * Send a rename folder request to the server.
-- *
-- * The response data sent to the callback will be NULL.
-- *
-- * @param user The logged in User
-- * @param folder The folder to rename
-- * @param new_name The new name of the folder
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_rename_folder(NMUser * user, NMFolder * folder,
-- const char *new_name, nm_response_cb callback,
-- gpointer data);
--
--/**
-- * Send a move contact request to the server.
-- *
-- * The response data sent to the callback will be NULL.
-- *
-- * @param user The logged in User
-- * @param contact The contact to move
-- * @param folder The folder to move the contact to
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_move_contact(NMUser * user, NMContact * contact,
-- NMFolder * folder, nm_response_cb callback,
-- gpointer data);
--
--/**
-- * Send a get status request to the server.
-- *
-- * The response data sent to the callback will be a NMUserRecord.
-- *
-- * @param user The logged in User
-- * @param contact The contact to move
-- * @param folder The folder to move the contact to
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T nm_send_get_status(NMUser * user, NMUserRecord * user_record,
-- nm_response_cb callback, gpointer data);
--
--/**
-- * Send a request to add an item to the allow or deny list.
-- *
-- * @param user The logged in User
-- * @param who The userid or DN of the user to add to list
-- * @param allow_list TRUE if adding to allow list, FALSE if adding to deny list
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T
--nm_send_create_privacy_item(NMUser *user, const char *who, gboolean is_allowed,
-- nm_response_cb callback, gpointer data);
--
--/**
-- * Send a request to remove an item from the allow or deny list.
-- *
-- * @param user The logged in User
-- * @param who The userid or DN of the user to add to list
-- * @param allow_list TRUE if removing from allow list, FALSE if removing from deny list
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T
--nm_send_remove_privacy_item(NMUser *user, const char *dn, gboolean allow_list,
-- nm_response_cb callback, gpointer data);
--
--/**
-- * Send a request to change the default privacy setting to deny all or allow all
-- *
-- * @param user The logged in User
-- * @param default_deny TRUE if default should be changed to deny all
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T
--nm_send_set_privacy_default(NMUser *user, gboolean default_deny,
-- nm_response_cb callback, gpointer data);
--
--/**
-- * Send a ping to the server
-- *
-- * @param user The logged in User
-- * @param callback Function to call when we get the response from the server
-- * @param data User defined data
-- *
-- * @return NM_OK if successfully sent, error otherwise
-- */
--NMERR_T
--nm_send_keepalive(NMUser *user, nm_response_cb callback, gpointer data);
--
--/**
-- * Reads a response/event from the server and processes it.
-- *
-- * @param user The logged in User
-- */
--NMERR_T nm_process_new_data(NMUser * user);
--
--/**
-- * Return the root folder of the contact list
-- *
-- * @param user The logged in User
-- *
-- * @return Root folder
-- */
--NMFolder *nm_get_root_folder(NMUser * user);
--
--/**
-- * Create the contact list based on the login fields
-- *
-- * @param user The logged in User
-- *
-- */
--NMERR_T nm_create_contact_list(NMUser * user);
--
--void nm_destroy_contact_list(NMUser * user);
--
--void nm_user_add_contact(NMUser * user, NMContact * contact);
--
--void nm_user_add_user_record(NMUser * user, NMUserRecord * user_record);
--
--NMContact *nm_find_contact(NMUser * user, const char *dn);
--
--GList *nm_find_contacts(NMUser * user, const char *dn);
--
--NMUserRecord *nm_find_user_record(NMUser * user, const char *dn);
--
--NMFolder *nm_find_folder(NMUser * user, const char *name);
--
--NMFolder *nm_find_folder_by_id(NMUser * user, int object_id);
--
--NMConference *nm_find_conversation(NMUser * user, const char *who);
--
--void nm_conference_list_add(NMUser * user, NMConference * conf);
--
--void nm_conference_list_remove(NMUser * user, NMConference * conf);
--
--void nm_conference_list_free(NMUser * user);
--
--NMConference *nm_conference_list_find(NMUser * user, const char *guid);
--
--const char *nm_lookup_dn(NMUser * user, const char *display_id);
--
--nm_event_cb nm_user_get_event_callback(NMUser * user);
--
--NMConn *nm_user_get_conn(NMUser * user);
--
--gboolean nm_user_is_privacy_locked(NMUser *user);
--
--/** Some utility functions **/
--
--/**
-- * Check to see if the conference GUIDs are equivalent.
-- *
-- * @param guid1 First guid to compare
-- * @param guid2 Second guid to compare
-- *
-- * @return TRUE if conference GUIDs are equivalent, FALSE otherwise.
-- *
-- */
--gboolean nm_are_guids_equal(const char *guid1, const char *guid2);
--
--/**
-- * Compare UTF8 strings for equality only (case insensitive)
-- *
-- * @param guid1 First string to compare
-- * @param guid2 Second string to compare
-- *
-- * @return TRUE if strings are equal, FALSE otherwise
-- *
-- */
--gboolean nm_utf8_str_equal(gconstpointer str1, gconstpointer str2);
--
--/**
-- * Convert a fully typed LDAP DN to dotted, untype notation
-- * e.g. cn=mike,o=novell -> mike.novell
-- *
-- * @param typed Fully typed dn
-- *
-- * @return Dotted equivalent of typed (must be freed).
-- *
-- */
--char *nm_typed_to_dotted(const char *typed);
--
--/**
-- * Return a string representation of the error code.
-- *
-- * @param error NMERR_T to convert to string
-- *
-- * @return String representation.
-- */
--const char *nm_error_to_string (NMERR_T err);
--
--#endif
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmuserrecord.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmuserrecord.c
---- pidgin-2.10.7/libpurple/protocols/novell/nmuserrecord.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmuserrecord.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,561 +0,0 @@
--/*
-- * nmuserrecord.c
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include <glib.h>
--#include <string.h>
--#include "nmuserrecord.h"
--#include "nmfield.h"
--#include "nmuser.h"
--
--struct _NMUserRecord
--{
-- NMSTATUS_T status;
-- char *status_text;
-- char *dn;
-- char *cn;
-- char *display_id;
-- char *fname;
-- char *lname;
-- char *full_name;
-- NMField *fields;
-- gboolean auth_attr;
-- gpointer data;
-- int ref_count;
--};
--
--struct _NMProperty
--{
-- char *tag;
-- char *value;
--};
--
--static int count = 0;
--
--/* API functions */
--
--NMUserRecord *
--nm_create_user_record()
--{
-- NMUserRecord *user_record = g_new0(NMUserRecord, 1);
--
-- user_record->ref_count = 1;
--
-- purple_debug(PURPLE_DEBUG_INFO, "novell", "Creating user_record, total=%d\n",
-- count++);
--
-- return user_record;
--}
--
--static char *
--_get_attribute_value(NMField *field)
--{
-- char *value = NULL;
--
-- if (field->ptr_value == NULL)
-- return NULL;
--
-- if (field->type == NMFIELD_TYPE_UTF8 || field->type == NMFIELD_TYPE_DN) {
--
-- value = (char *)field->ptr_value;
--
-- } else if (field->type == NMFIELD_TYPE_MV) {
--
-- /* Need to handle multi-valued returns, for now
-- * just pick the first value and return it
-- */
-- NMField *tmp = (NMField *)field->ptr_value;
-- if ((tmp != NULL) &&
-- ((tmp->type == NMFIELD_TYPE_UTF8) ||
-- (tmp->type == NMFIELD_TYPE_DN))) {
--
-- value = (char *)tmp->ptr_value;
--
-- } else {
-- return NULL;
-- }
--
-- } else {
-- return NULL;
-- }
--
-- return g_strdup(value);
--}
--/*
-- * This creates a user_record for the reference list the
-- * field array that is passed in should be a
-- * NM_A_FA_USER_DETAILS array.
-- */
--NMUserRecord *
--nm_create_user_record_from_fields(NMField * details)
--{
-- NMUserRecord *user_record;
-- NMField *field, *fields = details;
--
-- if (details == NULL) {
-- return NULL;
-- }
--
-- if (details->type == NMFIELD_TYPE_ARRAY) {
-- if (details->ptr_value == NULL)
-- return NULL;
-- fields = (NMField *) details->ptr_value;
-- }
--
-- user_record = nm_create_user_record();
--
-- if ((field = nm_locate_field(NM_A_SZ_AUTH_ATTRIBUTE, fields))) {
--
-- if (field->ptr_value) {
-- user_record->display_id = _get_attribute_value(field);
-- user_record->auth_attr = TRUE;
-- }
-- }
--
-- if ((field = nm_locate_field(NM_A_SZ_DN, fields))) {
--
-- if (field->ptr_value) {
-- user_record->dn = _get_attribute_value(field);
-- }
-- }
--
-- if ((field = nm_locate_field("CN", fields))) {
--
-- if (field->ptr_value) {
-- user_record->cn = _get_attribute_value(field);
-- }
-- }
--
-- if ((field = nm_locate_field("Given Name", fields))) {
--
-- if (field->ptr_value) {
-- user_record->fname = _get_attribute_value(field);
-- }
-- }
--
-- if ((field = nm_locate_field("Surname", fields))) {
--
-- if (field->ptr_value) {
-- user_record->lname = _get_attribute_value(field);
-- }
-- }
--
-- if ((field = nm_locate_field("Full Name", fields))) {
--
-- if (field->ptr_value) {
-- user_record->full_name = _get_attribute_value(field);
-- }
-- }
--
-- if ((field = nm_locate_field(NM_A_SZ_STATUS, fields))) {
--
-- if (field->ptr_value)
-- user_record->status = atoi((char *) field->ptr_value);
--
-- }
--
-- if ((field = nm_locate_field(NM_A_SZ_MESSAGE_BODY, fields))) {
--
-- if (field->ptr_value)
-- user_record->status_text = g_strdup((char *) field->ptr_value);
--
-- }
--
-- user_record->fields = nm_copy_field_array(fields);
--
-- return user_record;
--}
--
--void
--nm_user_record_copy(NMUserRecord * dest, NMUserRecord * src)
--{
-- if (dest == NULL || src == NULL)
-- return;
--
-- dest->status = src->status;
--
-- /* Copy status text */
-- if (dest->status_text) {
-- g_free(dest->status_text);
-- dest->status_text = NULL;
-- }
--
-- if (src->status_text)
-- dest->status_text = g_strdup(src->status_text);
--
-- /* Copy DN */
-- if (dest->dn) {
-- g_free(dest->dn);
-- dest->dn = NULL;
-- }
--
-- if (src->dn)
-- dest->dn = g_strdup(src->dn);
--
-- /* Copy CN */
-- if (dest->cn) {
-- g_free(dest->cn);
-- dest->cn = NULL;
-- }
--
-- if (src->cn)
-- dest->cn = g_strdup(src->cn);
--
-- /* Copy display id */
-- if (dest->display_id) {
-- g_free(dest->display_id);
-- dest->display_id = NULL;
-- }
--
-- if (src->display_id)
-- dest->display_id = g_strdup(src->display_id);
--
-- /* Copy first name */
-- if (dest->fname) {
-- g_free(dest->fname);
-- dest->fname = NULL;
-- }
--
-- if (src->fname)
-- dest->fname = g_strdup(src->fname);
--
-- /* Copy last name */
-- if (dest->lname) {
-- g_free(dest->lname);
-- dest->lname = NULL;
-- }
--
-- if (src->lname)
-- dest->lname = g_strdup(src->lname);
--
-- /* Copy full name */
-- if (dest->full_name) {
-- g_free(dest->full_name);
-- dest->full_name = NULL;
-- }
--
-- if (src->full_name)
-- dest->full_name = g_strdup(src->full_name);
--
-- /* Copy fields */
-- if (src->fields) {
--
-- if (dest->fields) {
-- nm_free_fields(&dest->fields);
-- }
--
-- dest->fields = nm_copy_field_array(src->fields);
-- }
--
-- /* Copy data */
-- dest->data = src->data;
--}
--
--void
--nm_user_record_add_ref(NMUserRecord * user_record)
--{
-- if (user_record)
-- user_record->ref_count++;
--}
--
--void
--nm_release_user_record(NMUserRecord * user_record)
--{
-- if (--(user_record->ref_count) == 0) {
--
-- purple_debug(PURPLE_DEBUG_INFO, "novell",
-- "Releasing user_record, total=%d\n", --count);
--
-- if (user_record->dn) {
-- g_free(user_record->dn);
-- }
--
-- if (user_record->cn) {
-- g_free(user_record->cn);
-- }
--
-- if (user_record->display_id) {
-- g_free(user_record->display_id);
-- }
--
-- if (user_record->fname) {
-- g_free(user_record->fname);
-- }
--
-- if (user_record->lname) {
-- g_free(user_record->lname);
-- }
--
-- if (user_record->full_name) {
-- g_free(user_record->full_name);
-- }
--
-- if (user_record->status_text) {
-- g_free(user_record->status_text);
-- }
--
-- nm_free_fields(&user_record->fields);
--
-- g_free(user_record);
-- }
--}
--
--/* UserRecord API */
--
--NMSTATUS_T
--nm_user_record_get_status(NMUserRecord * user_record)
--{
-- if (user_record == NULL)
-- return (NMSTATUS_T) - 1;
--
-- return user_record->status;
--
--}
--
--const char *
--nm_user_record_get_status_text(NMUserRecord * user_record)
--{
-- if (user_record == NULL)
-- return NULL;
--
-- return user_record->status_text;
--}
--
--void
--nm_user_record_set_dn(NMUserRecord * user_record, const char *dn)
--{
-- if (user_record != NULL && dn != NULL) {
-- if (user_record->dn)
-- g_free(user_record->dn);
--
-- user_record->dn = g_strdup(dn);
-- }
--}
--
--const char *
--nm_user_record_get_dn(NMUserRecord * user_record)
--{
-- if (user_record == NULL)
-- return NULL;
--
-- return user_record->dn;
--}
--
--void
--nm_user_record_set_userid(NMUserRecord * user_record, const char *userid)
--{
-- if (user_record != NULL && userid != NULL) {
-- if (user_record->cn)
-- g_free(user_record->cn);
--
-- user_record->cn = g_strdup(userid);
-- }
--}
--
--const char *
--nm_user_record_get_userid(NMUserRecord * user_record)
--{
-- if (user_record == NULL)
-- return NULL;
--
-- return user_record->cn;
--}
--
--void
--nm_user_record_set_display_id(NMUserRecord * user_record, const char *display_id)
--{
-- if (user_record != NULL && display_id != NULL) {
-- if (user_record->display_id)
-- g_free(user_record->display_id);
--
-- user_record->display_id = g_strdup(display_id);
-- }
--}
--
--const char *
--nm_user_record_get_display_id(NMUserRecord * user_record)
--{
-- if (user_record == NULL)
-- return NULL;
--
-- if (user_record->display_id == NULL) {
-- user_record->display_id = nm_typed_to_dotted(user_record->dn);
-- }
--
-- return user_record->display_id;
--}
--
--const char *
--nm_user_record_get_full_name(NMUserRecord * user_record)
--{
-- if (user_record == NULL)
-- return NULL;
--
-- if (user_record->full_name == NULL) {
-- if (user_record->fname && user_record->lname) {
-- user_record->full_name = g_strdup_printf("%s %s",
-- user_record->fname,
-- user_record->lname);
--
-- }
-- }
--
-- return user_record->full_name;
--}
--
--const char *
--nm_user_record_get_first_name(NMUserRecord * user_record)
--{
-- if (user_record == NULL)
-- return NULL;
--
-- return user_record->fname;
--
--}
--
--const char *
--nm_user_record_get_last_name(NMUserRecord * user_record)
--{
-- if (user_record == NULL)
-- return NULL;
--
-- return user_record->lname;
--}
--
--gpointer
--nm_user_record_get_data(NMUserRecord * user_record)
--{
-- if (user_record == NULL)
-- return NULL;
--
-- return user_record->data;
--}
--
--void
--nm_user_record_set_data(NMUserRecord * user_record, gpointer data)
--{
-- if (user_record == NULL)
-- return;
--
-- user_record->data = data;
--}
--
--void
--nm_user_record_set_status(NMUserRecord * user_record,
-- int status, const char *text)
--{
-- if (user_record == NULL)
-- return;
--
-- user_record->status = status;
--
-- if (user_record->status_text) {
-- g_free(user_record->status_text);
-- user_record->status_text = NULL;
-- }
--
-- if (text)
-- user_record->status_text = g_strdup(text);
--}
--
--gboolean
--nm_user_record_get_auth_attr(NMUserRecord *user_record)
--{
-- if (user_record == NULL)
-- return FALSE;
--
-- return user_record->auth_attr;
--}
--
--int
--nm_user_record_get_property_count(NMUserRecord * user_record)
--{
-- NMField *locate, *fields;
--
-- int count = 0;
--
-- if (user_record && user_record->fields) {
-- locate = nm_locate_field(NM_A_FA_INFO_DISPLAY_ARRAY,
-- (NMField *) user_record->fields);
-- if (locate && (fields = (NMField *) (locate->ptr_value))) {
-- count = (int) nm_count_fields(fields);
-- }
-- }
-- return count;
--}
--
--NMProperty *
--nm_user_record_get_property(NMUserRecord * user_record, int index)
--{
-- NMProperty *property = NULL;
-- NMField *field = NULL, *fields, *locate;
--
-- if (user_record && user_record->fields) {
-- locate = nm_locate_field(NM_A_FA_INFO_DISPLAY_ARRAY,
-- (NMField *) user_record->fields);
-- if (locate && (fields = (NMField *) (locate->ptr_value))) {
-- int max = nm_count_fields(fields);
--
-- if (index < max) {
-- if (user_record) {
-- field = &fields[index];
-- if (field && field->tag && field->ptr_value) {
-- property = g_new0(NMProperty, 1);
-- property->tag = g_strdup(field->tag);
-- property->value = _get_attribute_value(field);
-- }
-- }
-- }
-- }
-- }
--
-- return property;
--}
--
--void
--nm_release_property(NMProperty * property)
--{
-- if (property) {
-- if (property->tag)
-- g_free(property->tag);
--
-- if (property->value)
-- g_free(property->value);
--
-- g_free(property);
-- }
--}
--
--const char *
--nm_property_get_tag(NMProperty * property)
--{
-- if (property)
-- return property->tag;
-- else
-- return NULL;
--}
--
--const char *
--nm_property_get_value(NMProperty * property)
--{
-- if (property)
-- return property->value;
-- else
-- return NULL;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmuserrecord.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmuserrecord.h
---- pidgin-2.10.7/libpurple/protocols/novell/nmuserrecord.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmuserrecord.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,273 +0,0 @@
--/*
-- * nmuserrecord.h
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#ifndef __NM_USER_RECORD_H__
--#define __NM_USER_RECORD_H__
--
--#include <glib.h>
--
--typedef struct _NMUserRecord NMUserRecord;
--typedef struct _NMProperty NMProperty;
--
--#include "nmfield.h"
--#include "nmuser.h"
--
--/**
-- * Creates an NMUserRecord
-- *
-- * The NMUserRecord should be released by calling
-- * nm_release_user_record
-- *
-- * @return The new user record
-- *
-- */
--NMUserRecord *nm_create_user_record(void);
--
--/**
-- * Creates an NMUserRecord
-- *
-- * The NMUserRecord should be released by calling
-- * nm_release_user_record
-- *
-- * @param details Should be a NM_A_FA_USER_DETAILS
-- *
-- *
-- * @return The new user record
-- *
-- */
--NMUserRecord *nm_create_user_record_from_fields(NMField * details);
--
--/**
-- * Add a reference to an existing user_record
-- *
-- * The reference should be released by calling
-- * nm_release_user_record
-- *
-- * @param user_record The contact to addref
-- *
-- */
--void nm_user_record_add_ref(NMUserRecord * user_record);
--
--/**
-- * Release a reference to the user record
-- *
-- * @param user_record The user record
-- *
-- */
--void nm_release_user_record(NMUserRecord * user_record);
--
--/**
-- * Set the status for the user record
-- *
-- * @param user_record The user record
-- * @param status The status for the user
-- * @param text The status text for the user
-- *
-- */
--void nm_user_record_set_status(NMUserRecord * user_record, NMSTATUS_T status,
-- const char *text);
--
--/**
-- * Get the status for the user record
-- *
-- * @param user_record The user record
-- *
-- * @return The status for the user record
-- */
--NMSTATUS_T nm_user_record_get_status(NMUserRecord * user_record);
--
--/**
-- * Get the status text for the user record
-- *
-- * @param user_record The user record
-- *
-- * @return The status text if there is any, NULL otherwise
-- *
-- */
--const char *nm_user_record_get_status_text(NMUserRecord * user_record);
--
--/**
-- * Set the DN for the user record
-- *
-- * @param user_record The user record
-- * @param dn The new DN for the user record
-- *
-- */
--void nm_user_record_set_dn(NMUserRecord * user_record, const char *dn);
--
--/**
-- * Get the DN for the user record
-- *
-- * @param user_record The user record
-- *
-- * @return The DN for the user record
-- */
--const char *nm_user_record_get_dn(NMUserRecord * user_record);
--
--/**
-- * Set the user id for the
-- *
-- * @param user_record The user record
-- * @param userid The userid (CN) for the user record
-- *
-- */
--void nm_user_record_set_userid(NMUserRecord * user_record, const char *userid);
--
--/**
-- * Get the user id for the user record
-- *
-- * @param user_record The user record
-- *
-- * @return The user id for the user record
-- */
--const char *nm_user_record_get_userid(NMUserRecord * user_record);
--
--/**
-- * Set the display id for the user record
-- *
-- * @param user_record The user record
-- * @param display_id The new display id for the user
-- *
-- */
--void nm_user_record_set_display_id(NMUserRecord * user_record,
-- const char *display_id);
--
--/**
-- * Get the display id for the user record
-- *
-- * @param user_record The user record
-- *
-- * @return The display id for the user record
-- */
--const char *nm_user_record_get_display_id(NMUserRecord * user_record);
--
--/**
-- * Return whether or not the display id is an auth attribute or not.
-- *
-- * @param user_record The user record
-- *
-- * @return TRUE if display_id is an auth attribute, FALSE otherwise.
-- */
--gboolean
--nm_user_record_get_auth_attr(NMUserRecord *user_record);
--
--/**
-- * Get the full name for the user record
-- *
-- * @param user_record The user record
-- *
-- * @return The full name for the user
-- */
--const char *nm_user_record_get_full_name(NMUserRecord * user_record);
--
--/**
-- * Get the first name for the user record
-- *
-- * @param user_record The user record
-- *
-- * @return The first name for the user
-- */
--const char *nm_user_record_get_first_name(NMUserRecord * user_record);
--
--/**
-- * Get the last name for the user record
-- *
-- * @param user_record The user record
-- *
-- * @return The last name for the user
-- */
--const char *nm_user_record_get_last_name(NMUserRecord * user_record);
--
--/**
-- * Set the user defined data for the user record
-- *
-- * @param user_record The user record
-- * @param data The user defined data for the user record
-- *
-- */
--void nm_user_record_set_data(NMUserRecord * user_record, gpointer data);
--
--/**
-- * Get the user defined data for the user record
-- *
-- * @param user_record The user record
-- *
-- * @return The user defined data for the user record
-- */
--gpointer nm_user_record_get_data(NMUserRecord * user_record);
--
--/**
-- * Get the property count for the user record
-- *
-- * @param user_record The user record
-- *
-- * @return The number of information properties for the user record
-- *
-- */
--int nm_user_record_get_property_count(NMUserRecord * user_record);
--
--/**
-- * Get an info property for the user record. The property must be released
-- * by calling nm_release_property()
-- *
-- * @param user_record The user record
-- * @param index The index of the property to get (zero based)
-- *
-- * @return The property
-- */
--NMProperty *nm_user_record_get_property(NMUserRecord * user_record, int index);
--
--/**
-- * Release a property object
-- *
-- * @param property The property
-- *
-- */
--void nm_release_property(NMProperty * property);
--
--/**
-- * Get the tag for the property
-- *
-- * @param property The property
-- *
-- * @return The tag of the property (i.e. "Email Address")
-- */
--const char *nm_property_get_tag(NMProperty * property);
--
--/**
-- * Get the value for the property
-- *
-- * @param property The property
-- *
-- * @return The value of the property (i.e. "nobody@nowhere.com")
-- */
--const char *nm_property_get_value(NMProperty * property);
--
--/**
-- * Copy a user record (deep copy). The dest user record must have already been
-- * created (nm_create_user_record)
-- *
-- * @param dest The destination of the copy
-- * @param src The source of the copy
-- *
-- */
--void nm_user_record_copy(NMUserRecord * dest, NMUserRecord * src);
--
--#endif
-diff -Nur pidgin-2.10.7/libpurple/protocols/novell/novell.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/novell.c
---- pidgin-2.10.7/libpurple/protocols/novell/novell.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/novell.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,3590 +0,0 @@
--/*
-- * novell.c
-- *
-- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; version 2 of the License.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include "internal.h"
--#include "accountopt.h"
--#include "debug.h"
--#include "prpl.h"
--#include "server.h"
--#include "nmuser.h"
--#include "notify.h"
--#include "util.h"
--#include "sslconn.h"
--#include "request.h"
--#include "network.h"
--#include "privacy.h"
--#include "status.h"
--#include "version.h"
--
--#define DEFAULT_PORT 8300
--#define NOVELL_CONNECT_STEPS 4
--#define NM_ROOT_FOLDER_NAME "GroupWise Messenger"
--
--#define NOVELL_STATUS_TYPE_AVAILABLE "available"
--#define NOVELL_STATUS_TYPE_AWAY "away"
--#define NOVELL_STATUS_TYPE_BUSY "busy"
--#define NOVELL_STATUS_TYPE_OFFLINE "offline"
--#define NOVELL_STATUS_TYPE_IDLE "idle"
--#define NOVELL_STATUS_TYPE_APPEAR_OFFLINE "appearoffline"
--
--static PurplePlugin *my_protocol = NULL;
--
--static gboolean
--_is_disconnect_error(NMERR_T err);
--
--static gboolean
--_check_for_disconnect(NMUser * user, NMERR_T err);
--
--static void
--_send_message(NMUser * user, NMMessage * message);
--
--static void
--_update_buddy_status(NMUser *user, PurpleBuddy * buddy, int status, int gmt);
--
--static void
--_remove_purple_buddies(NMUser * user);
--
--static void
--_add_contacts_to_purple_blist(NMUser * user, NMFolder * folder);
--
--static void
--_add_purple_buddies(NMUser * user);
--
--static void
--_sync_contact_list(NMUser *user);
--
--static void
--_sync_privacy_lists(NMUser *user);
--
--static void
--_show_info(PurpleConnection * gc, NMUserRecord * user_record, char * name);
--
--const char *
--_get_conference_name(int id);
--
--/*******************************************************************************
-- * Response callbacks
-- *******************************************************************************/
--
--/* Handle login response */
--static void
--_login_resp_cb(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- PurpleConnection *gc;
-- const char *alias;
-- NMERR_T rc;
--
-- if (user == NULL)
-- return;
--
-- gc = purple_account_get_connection(user->client_data);
-- if (gc == NULL)
-- return;
--
-- if (ret_code == NM_OK) {
--
-- /* Set alias for user if not set (use Full Name) */
-- alias = purple_account_get_alias(user->client_data);
-- if (alias == NULL || *alias == '\0') {
-- alias = nm_user_record_get_full_name(user->user_record);
--
-- if (alias)
-- purple_account_set_alias(user->client_data, alias);
-- }
--
-- /* Tell Purple that we are connected */
-- purple_connection_set_state(gc, PURPLE_CONNECTED);
--
-- _sync_contact_list(user);
--
-- rc = nm_send_set_status(user, NM_STATUS_AVAILABLE, NULL, NULL, NULL,
-- NULL);
-- _check_for_disconnect(user, rc);
--
-- } else {
-- PurpleConnectionError reason;
-- char *err = g_strdup_printf(_("Unable to login: %s"),
-- nm_error_to_string (ret_code));
--
-- switch (ret_code) {
-- case NMERR_AUTHENTICATION_FAILED:
-- case NMERR_CREDENTIALS_MISSING:
-- case NMERR_PASSWORD_INVALID:
-- /* Don't attempt to auto-reconnect if our
-- * password was invalid.
-- */
-- if (!purple_account_get_remember_password(gc->account))
-- purple_account_set_password(gc->account, NULL);
-- reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
-- break;
-- default:
-- /* FIXME: There are other reasons login could fail */
-- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-- }
--
-- purple_connection_error_reason(gc, reason, err);
-- g_free(err);
-- }
--}
--
--/* Handle getstatus response*/
--static void
--_get_status_resp_cb(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- PurpleBuddy *buddy;
-- GSList *buddies;
-- GSList *bnode;
-- NMUserRecord *user_record = (NMUserRecord *) resp_data;
-- int status;
--
-- if (user == NULL || user_record == NULL)
-- return;
--
-- if (ret_code == NM_OK) {
--
-- /* Find all Purple buddies and update their statuses */
-- const char *name = nm_user_record_get_display_id(user_record);
--
-- if (name) {
-- buddies = purple_find_buddies((PurpleAccount *) user->client_data, name);
-- for (bnode = buddies; bnode; bnode = bnode->next) {
-- buddy = (PurpleBuddy *) bnode->data;
-- if (buddy) {
-- status = nm_user_record_get_status(user_record);
-- _update_buddy_status(user, buddy, status, time(0));
-- }
-- }
-- g_slist_free(buddies);
-- }
--
-- } else {
--
-- purple_debug(PURPLE_DEBUG_INFO, "novell",
-- "_get_status_resp_cb(): rc = 0x%X\n", ret_code);
--
-- }
--}
--
--/* Show an error if the rename failed */
--static void
--_rename_contact_resp_cb(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- if (ret_code != NM_OK) {
-- purple_debug(PURPLE_DEBUG_INFO, "novell",
-- "_rename_contact_resp_cb(): rc = 0x%X\n", ret_code);
-- }
--}
--
--/* Handle the getdetails response and send the message */
--static void
--_get_details_resp_send_msg(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- PurpleConversation *gconv;
-- PurpleConnection *gc;
-- NMUserRecord *user_record = NULL;
-- NMContact *cntct = NULL;
-- NMConference *conf;
-- NMMessage *msg = user_data;
-- const char *dn = NULL;
-- const char *name;
--
-- if (user == NULL || msg == NULL)
-- return;
--
-- if (ret_code == NM_OK) {
-- user_record = (NMUserRecord *) resp_data;
-- if (user_record) {
--
-- /* Set the title for the conversation */
-- /* XXX - Should this be PURPLE_CONV_TYPE_IM? */
-- gconv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,
-- nm_user_record_get_display_id(user_record),
-- (PurpleAccount *) user->client_data);
-- if (gconv) {
--
-- dn = nm_user_record_get_dn(user_record);
-- if (dn) {
-- cntct = nm_find_contact(user, dn);
-- }
--
-- if (cntct) {
-- purple_conversation_set_title(gconv,
-- nm_contact_get_display_name(cntct));
-- } else {
--
-- /* Not in the contact list, try to user full name */
-- name = (char *) nm_user_record_get_full_name(user_record);
-- if (name)
-- purple_conversation_set_title(gconv, name);
-- }
-- }
--
-- /* Add the user record to particpant list */
-- conf = nm_message_get_conference(msg);
-- if (conf) {
-- nm_conference_add_participant(conf, user_record);
-- _send_message(user, msg);
-- }
-- }
--
-- } else {
--
-- gc = purple_account_get_connection(user->client_data);
-- if (gc != NULL) {
-- char *err = g_strdup_printf(_("Unable to send message."
-- " Could not get details for user (%s)."),
-- nm_error_to_string (ret_code));
--
-- purple_notify_error(gc, NULL, err, NULL);
-- g_free(err);
-- }
--
-- if (msg)
-- nm_release_message(msg);
-- }
--}
--
--/* Set up the new PurpleBuddy based on the response from getdetails */
--static void
--_get_details_resp_setup_buddy(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- NMUserRecord *user_record;
-- NMContact *contact;
-- PurpleBuddy *buddy;
-- const char *alias;
-- NMERR_T rc = NM_OK;
--
-- if (user == NULL || resp_data == NULL || user_data == NULL)
-- return;
--
-- contact = user_data;
--
-- if (ret_code == NM_OK) {
-- user_record = resp_data;
--
-- buddy = nm_contact_get_data(contact);
--
-- nm_contact_set_user_record(contact, user_record);
--
-- /* Set the display id */
-- purple_blist_rename_buddy(buddy,
-- nm_user_record_get_display_id(user_record));
--
-- alias = purple_buddy_get_alias(buddy);
-- if (alias == NULL || *alias == '\0' || (strcmp(alias, purple_buddy_get_name(buddy)) == 0)) {
-- purple_blist_alias_buddy(buddy,
-- nm_user_record_get_full_name(user_record));
--
-- /* Tell the server about the new display name */
-- rc = nm_send_rename_contact(user, contact,
-- nm_user_record_get_full_name(user_record),
-- NULL, NULL);
-- _check_for_disconnect(user, rc);
--
-- }
--
--
-- /* Get initial status for the buddy */
-- rc = nm_send_get_status(user, resp_data, _get_status_resp_cb, NULL);
-- _check_for_disconnect(user, rc);
--
--/* nm_release_contact(contact);*/
--
-- }
--
-- if (contact)
-- nm_release_contact(contact);
--}
--
--/* Add the new contact into the PurpleBuddy list */
--static void
--_create_contact_resp_cb(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- NMContact *tmp_contact = (NMContact *) user_data;
-- NMContact *new_contact = NULL;
-- NMFolder *folder = NULL;
-- PurpleGroup *group;
-- PurpleBuddy *buddy;
-- const char *folder_name = NULL;
-- NMERR_T rc = NM_OK;
--
-- if (user == NULL)
-- return;
--
-- if (ret_code == NM_OK) {
--
-- new_contact = (NMContact *) resp_data;
-- if (new_contact == NULL || tmp_contact == NULL)
-- return;
--
-- /* Get the userid and folder name for the new contact */
-- folder = nm_find_folder_by_id(user,
-- nm_contact_get_parent_id(new_contact));
-- if (folder) {
-- folder_name = nm_folder_get_name(folder);
-- }
--
-- if (folder_name == NULL || *folder_name == '\0')
-- folder_name = NM_ROOT_FOLDER_NAME;
--
-- /* Re-add the buddy now that we got the okay from the server */
-- if (folder_name && (group = purple_find_group(folder_name))) {
--
-- const char *alias = nm_contact_get_display_name(tmp_contact);
-- const char *display_id = nm_contact_get_display_id(new_contact);
--
-- if (display_id == NULL)
-- display_id = nm_contact_get_dn(new_contact);
--
-- if (alias && strcmp(alias, display_id)) {
--
-- /* The user requested an alias, tell the server about it. */
-- rc = nm_send_rename_contact(user, new_contact, alias,
-- _rename_contact_resp_cb, NULL);
-- _check_for_disconnect(user, rc);
--
-- } else {
--
-- alias = "";
--
-- }
--
-- /* Add it to the purple buddy list if it is not there */
-- buddy = purple_find_buddy_in_group(user->client_data, display_id, group);
-- if (buddy == NULL) {
-- buddy = purple_buddy_new(user->client_data, display_id, alias);
-- purple_blist_add_buddy(buddy, NULL, group, NULL);
-- }
--
-- /* Save the new buddy as part of the contact object */
-- nm_contact_set_data(new_contact, (gpointer) buddy);
--
-- /* We need details for the user before we can setup the
-- * new Purple buddy. We always call this because the
-- * 'createcontact' response fields do not always contain
-- * everything that we need.
-- */
-- nm_contact_add_ref(new_contact);
--
-- rc = nm_send_get_details(user, nm_contact_get_dn(new_contact),
-- _get_details_resp_setup_buddy, new_contact);
-- _check_for_disconnect(user, rc);
--
-- }
--
-- } else {
-- PurpleConnection *gc = purple_account_get_connection(user->client_data);
-- const char *name = nm_contact_get_dn(tmp_contact);
-- char *err;
--
-- err =
-- g_strdup_printf(_("Unable to add %s to your buddy list (%s)."),
-- name, nm_error_to_string (ret_code));
-- purple_notify_error(gc, NULL, err, NULL);
-- g_free(err);
--
-- }
--
-- if (tmp_contact)
-- nm_release_contact(tmp_contact);
--}
--
--/* Show an error if we failed to send the message */
--static void
--_send_message_resp_cb(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- PurpleConnection *gc;
-- char *err = NULL;
--
-- if (user == NULL)
-- return;
--
-- if (ret_code != NM_OK) {
-- gc = purple_account_get_connection(user->client_data);
--
-- /* TODO: Improve this! message to who or for what conference? */
-- err = g_strdup_printf(_("Unable to send message (%s)."),
-- nm_error_to_string (ret_code));
-- purple_notify_error(gc, NULL, err, NULL);
-- g_free(err);
-- }
--}
--
--/* Show an error if the remove failed */
--static void
--_remove_contact_resp_cb(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- if (ret_code != NM_OK) {
-- /* TODO: Display an error? */
--
-- purple_debug(PURPLE_DEBUG_INFO, "novell",
-- "_remove_contact_resp_cb(): rc = 0x%x\n", ret_code);
-- }
--}
--
--/* Show an error if the remove failed */
--static void
--_remove_folder_resp_cb(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- if (ret_code != NM_OK) {
-- /* TODO: Display an error? */
--
-- purple_debug(PURPLE_DEBUG_INFO, "novell",
-- "_remove_folder_resp_cb(): rc = 0x%x\n", ret_code);
-- }
--}
--
--/* Show an error if the move failed */
--static void
--_move_contact_resp_cb(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- if (ret_code != NM_OK) {
-- /* TODO: Display an error? */
--
-- purple_debug(PURPLE_DEBUG_INFO, "novell",
-- "_move_contact_resp_cb(): rc = 0x%x\n", ret_code);
-- }
--}
--
--/* Show an error if the rename failed */
--static void
--_rename_folder_resp_cb(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- if (ret_code != NM_OK) {
-- /* TODO: Display an error? */
--
-- purple_debug(PURPLE_DEBUG_INFO, "novell",
-- "_rename_folder_resp_cb(): rc = 0x%x\n", ret_code);
-- }
--}
--
--static void
--_sendinvite_resp_cb(NMUser *user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- char *err;
-- PurpleConnection *gc;
--
-- if (user == NULL)
-- return;
--
-- if (ret_code != NM_OK) {
-- gc = purple_account_get_connection(user->client_data);
-- err = g_strdup_printf(_("Unable to invite user (%s)."), nm_error_to_string(ret_code));
-- purple_notify_error(gc, NULL, err, NULL);
-- g_free(err);
--
-- purple_debug(PURPLE_DEBUG_INFO, "novell",
-- "_sendinvite_resp_cb(): rc = 0x%x\n", ret_code);
-- }
--
--}
--
--/* If the createconf was successful attempt to send the message,
-- * otherwise display an error message to the user.
-- */
--static void
--_createconf_resp_send_msg(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- NMConference *conf;
-- NMMessage *msg = user_data;
--
-- if (user == NULL || msg == NULL)
-- return;
--
-- if (ret_code == NM_OK) {
-- _send_message(user, msg);
-- } else {
--
-- if ((conf = nm_message_get_conference(msg))) {
--
-- PurpleConnection *gc = purple_account_get_connection(user->client_data);
-- const char *name = NULL;
-- char *err;
-- NMUserRecord *ur;
--
-- ur = nm_conference_get_participant(conf, 0);
-- if (ur)
-- name = nm_user_record_get_userid(ur);
--
-- if (name)
-- err = g_strdup_printf(_("Unable to send message to %s."
-- " Could not create the conference (%s)."),
-- name,
-- nm_error_to_string (ret_code));
-- else
-- err = g_strdup_printf(_("Unable to send message."
-- " Could not create the conference (%s)."),
-- nm_error_to_string (ret_code));
--
-- purple_notify_error(gc, NULL, err, NULL);
-- g_free(err);
-- }
--
-- if (msg)
-- nm_release_message(msg);
-- }
--}
--
--/* Move contact to newly created folder */
--static void
--_create_folder_resp_move_contact(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- NMContact *contact = user_data;
-- NMFolder *new_folder;
-- char *folder_name = resp_data;
-- NMERR_T rc = NM_OK;
--
-- if (user == NULL || folder_name == NULL || contact == NULL) {
--
-- if (folder_name)
-- g_free(folder_name);
--
-- return;
-- }
--
-- if (ret_code == NM_OK || ret_code == NMERR_DUPLICATE_FOLDER) {
-- new_folder = nm_find_folder(user, folder_name);
-- if (new_folder) {
--
-- /* Tell the server to move the contact to the new folder */
--/* rc = nm_send_move_contact(user, contact, new_folder,
-- _move_contact_resp_cb, NULL); */
--
-- rc = nm_send_create_contact(user, new_folder, contact,
-- NULL, NULL);
--
-- _check_for_disconnect(user, rc);
--
-- }
-- } else {
-- PurpleConnection *gc = purple_account_get_connection(user->client_data);
-- char *err = g_strdup_printf(_("Unable to move user %s"
-- " to folder %s in the server side list."
-- " Error while creating folder (%s)."),
-- nm_contact_get_dn(contact),
-- folder_name,
-- nm_error_to_string (ret_code));
--
-- purple_notify_error(gc, NULL, err, NULL);
-- g_free(err);
-- }
--
-- if (folder_name)
-- g_free(folder_name);
--}
--
--/* Add contact to newly create folder */
--static void
--_create_folder_resp_add_contact(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- NMContact *contact = (NMContact *) user_data;
-- NMFolder *folder;
-- char *folder_name = (char *) resp_data;
-- NMERR_T rc = NM_OK;
--
-- if (user == NULL || folder_name == NULL || contact == NULL) {
--
-- if (contact)
-- nm_release_contact(contact);
--
-- if (folder_name)
-- g_free(folder_name);
--
-- return;
-- }
--
-- if (ret_code == NM_OK || ret_code == NMERR_DUPLICATE_FOLDER) {
-- folder = nm_find_folder(user, folder_name);
-- if (folder) {
--
-- rc = nm_send_create_contact(user, folder, contact,
-- _create_contact_resp_cb, contact);
-- _check_for_disconnect(user, rc);
-- }
-- } else {
-- PurpleConnection *gc = purple_account_get_connection(user->client_data);
-- const char *name = nm_contact_get_dn(contact);
-- char *err =
-- g_strdup_printf(_("Unable to add %s to your buddy list."
-- " Error creating folder in server side list (%s)."),
-- name, nm_error_to_string (ret_code));
--
-- purple_notify_error(gc, NULL, err, NULL);
--
-- nm_release_contact(contact);
-- g_free(err);
-- }
--
-- g_free(folder_name);
--}
--
--static void
--_join_conf_resp_cb(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- PurpleConversation *chat;
-- PurpleConnection *gc;
-- NMUserRecord *ur;
-- NMConference *conference = user_data;
-- const char *name, *conf_name;
-- int i, count;
--
-- if (user == NULL || conference == NULL)
-- return;
--
-- gc = purple_account_get_connection(user->client_data);
--
-- if (ret_code == NM_OK) {
-- conf_name = _get_conference_name(++user->conference_count);
-- chat = serv_got_joined_chat(gc, user->conference_count, conf_name);
-- if (chat) {
--
-- nm_conference_set_data(conference, (gpointer) chat);
--
-- count = nm_conference_get_participant_count(conference);
-- for (i = 0; i < count; i++) {
-- ur = nm_conference_get_participant(conference, i);
-- if (ur) {
-- name = nm_user_record_get_display_id(ur);
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(chat), name, NULL,
-- PURPLE_CBFLAGS_NONE, TRUE);
-- }
-- }
-- }
-- }
--}
--
--/* Show info returned by getdetails */
--static void
--_get_details_resp_show_info(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- PurpleConnection *gc;
-- NMUserRecord *user_record;
-- char *name;
-- char *err;
--
-- if (user == NULL)
-- return;
--
-- name = user_data;
--
-- if (ret_code == NM_OK) {
-- user_record = (NMUserRecord *) resp_data;
-- if (user_record) {
-- _show_info(purple_account_get_connection(user->client_data),
-- user_record, g_strdup(name));
-- }
-- } else {
-- gc = purple_account_get_connection(user->client_data);
-- err =
-- g_strdup_printf(_("Could not get details for user %s (%s)."),
-- name, nm_error_to_string (ret_code));
-- purple_notify_error(gc, NULL, err, NULL);
-- g_free(err);
-- }
--
-- if (name)
-- g_free(name);
--}
--
--/* Handle get details response add to privacy list */
--static void
--_get_details_resp_add_privacy_item(NMUser *user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- PurpleConnection *gc;
-- NMUserRecord *user_record = resp_data;
-- char *err;
-- gboolean allowed = GPOINTER_TO_INT(user_data);
-- const char *display_id;
--
-- if (user == NULL)
-- return;
--
-- gc = purple_account_get_connection(user->client_data);
-- display_id = nm_user_record_get_display_id(user_record);
--
-- if (ret_code == NM_OK) {
--
-- if (allowed) {
--
-- if (!g_slist_find_custom(gc->account->permit,
-- display_id, (GCompareFunc)purple_utf8_strcasecmp)) {
-- purple_privacy_permit_add(gc->account, display_id, TRUE);
-- }
--
-- } else {
--
-- if (!g_slist_find_custom(gc->account->permit,
-- display_id, (GCompareFunc)purple_utf8_strcasecmp)) {
-- purple_privacy_deny_add(gc->account, display_id, TRUE);
-- }
-- }
--
-- } else {
--
-- err = g_strdup_printf(_("Unable to add user to privacy list (%s)."),
-- nm_error_to_string(ret_code));
-- purple_notify_error(gc, NULL, err, NULL);
-- g_free(err);
--
-- }
--}
--
--/* Handle response to create privacy item request */
--static void
--_create_privacy_item_deny_resp_cb(NMUser *user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- PurpleConnection *gc;
-- NMUserRecord *user_record;
-- char *who = user_data;
-- char *err;
-- NMERR_T rc = NM_OK;
-- const char *display_id = NULL;
--
-- if (user == NULL)
-- return;
--
-- gc = purple_account_get_connection(user->client_data);
--
-- if (ret_code == NM_OK) {
--
-- user_record = nm_find_user_record(user, who);
-- if (user_record)
-- display_id = nm_user_record_get_display_id(user_record);
--
-- if (display_id) {
--
-- if (!g_slist_find_custom(gc->account->deny,
-- display_id, (GCompareFunc)purple_utf8_strcasecmp)) {
--
-- purple_privacy_deny_add(gc->account, display_id, TRUE);
-- }
--
-- } else {
-- rc = nm_send_get_details(user, who,
-- _get_details_resp_add_privacy_item,
-- (gpointer)FALSE);
-- _check_for_disconnect(user, rc);
-- }
-- } else {
--
-- err = g_strdup_printf(_("Unable to add %s to deny list (%s)."),
-- who, nm_error_to_string(ret_code));
-- purple_notify_error(gc, NULL, err, NULL);
-- g_free(err);
--
-- }
--
-- if (who)
-- g_free(who);
--
--}
--
--/* Handle response to create privacy item request */
--static void
--_create_privacy_item_permit_resp_cb(NMUser *user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- PurpleConnection *gc;
-- NMUserRecord *user_record;
-- char *who = user_data;
-- char *err;
-- NMERR_T rc = NM_OK;
-- const char *display_id = NULL;
--
-- if (user == NULL)
-- return;
--
-- gc = purple_account_get_connection(user->client_data);
--
-- if (ret_code == NM_OK) {
--
-- user_record = nm_find_user_record(user, who);
-- if (user_record)
-- display_id = nm_user_record_get_display_id(user_record);
--
-- if (display_id) {
--
-- if (!g_slist_find_custom(gc->account->permit,
-- display_id,
-- (GCompareFunc)purple_utf8_strcasecmp)) {
--
-- purple_privacy_permit_add(gc->account, display_id, TRUE);
-- }
--
-- } else {
-- rc = nm_send_get_details(user, who,
-- _get_details_resp_add_privacy_item,
-- (gpointer)TRUE);
-- _check_for_disconnect(user, rc);
-- }
--
-- } else {
--
-- err = g_strdup_printf(_("Unable to add %s to permit list (%s)."), who,
-- nm_error_to_string(ret_code));
-- purple_notify_error(gc, NULL, err, NULL);
-- g_free(err);
--
-- }
--
-- if (who)
-- g_free(who);
--}
--
--static void
--_get_details_send_privacy_create(NMUser *user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- NMERR_T rc = NM_OK;
-- PurpleConnection *gc;
-- NMUserRecord *user_record = resp_data;
-- char *err;
-- gboolean allowed = GPOINTER_TO_INT(user_data);
-- const char *dn, *display_id;
--
-- if (user == NULL)
-- return;
--
-- gc = purple_account_get_connection(user->client_data);
-- dn = nm_user_record_get_dn(user_record);
-- display_id = nm_user_record_get_display_id(user_record);
--
-- if (ret_code == NM_OK) {
--
-- if (allowed) {
-- rc = nm_send_create_privacy_item(user, dn, TRUE,
-- _create_privacy_item_permit_resp_cb,
-- g_strdup(display_id));
-- _check_for_disconnect(user, rc);
--
-- } else {
-- rc = nm_send_create_privacy_item(user, dn, FALSE,
-- _create_privacy_item_deny_resp_cb,
-- g_strdup(display_id));
-- _check_for_disconnect(user, rc);
-- }
--
-- } else {
--
-- err = g_strdup_printf(_("Unable to add user to privacy list (%s)."),
-- nm_error_to_string(ret_code));
-- purple_notify_error(gc, NULL, err, NULL);
-- g_free(err);
--
-- }
--}
--
--static void
--_remove_privacy_item_resp_cb(NMUser *user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- PurpleConnection *gc;
-- char *who = user_data;
-- char *err;
--
-- if (user == NULL)
-- return;
--
-- if (ret_code != NM_OK) {
--
-- gc = purple_account_get_connection(user->client_data);
-- err = g_strdup_printf(_("Unable to remove %s from privacy list (%s)."), who,
-- nm_error_to_string(ret_code));
-- purple_notify_error(gc, NULL, err, NULL);
-- g_free(err);
-- }
--
-- if (who)
-- g_free(who);
--}
--
--static void
--_set_privacy_default_resp_cb(NMUser *user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- PurpleConnection *gc;
-- char *err;
--
-- if (user == NULL)
-- return;
--
-- if (ret_code != NM_OK) {
--
-- gc = purple_account_get_connection(user->client_data);
-- err = g_strdup_printf(_("Unable to change server side privacy settings (%s)."),
-- nm_error_to_string(ret_code));
-- purple_notify_error(gc, NULL, err, NULL);
-- g_free(err);
--
-- }
--}
--
--/* Handle get details response add to privacy list */
--static void
--_get_details_resp_send_invite(NMUser *user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- NMERR_T rc = NM_OK;
-- PurpleConnection *gc;
-- NMUserRecord *user_record = resp_data;
-- char *err;
-- GSList *cnode;
-- NMConference *conference;
-- gpointer chat;
-- long id = (long) user_data;
--
-- if (user == NULL)
-- return;
--
-- gc = purple_account_get_connection(user->client_data);
--
-- if (ret_code == NM_OK) {
--
-- for (cnode = user->conferences; cnode != NULL; cnode = cnode->next) {
-- conference = cnode->data;
-- if (conference && (chat = nm_conference_get_data(conference))) {
-- if (purple_conv_chat_get_id(PURPLE_CONV_CHAT(chat)) == id) {
-- rc = nm_send_conference_invite(user, conference, user_record,
-- NULL, _sendinvite_resp_cb, NULL);
-- _check_for_disconnect(user, rc);
-- break;
-- }
-- }
-- }
--
-- } else {
--
-- err = g_strdup_printf(_("Unable to invite user (%s)."), nm_error_to_string(ret_code));
-- purple_notify_error(gc, NULL, err, NULL);
-- g_free(err);
--
-- }
--}
--
--static void
--_createconf_resp_send_invite(NMUser * user, NMERR_T ret_code,
-- gpointer resp_data, gpointer user_data)
--{
-- NMERR_T rc = NM_OK;
-- NMConference *conference = resp_data;
-- NMUserRecord *user_record = user_data;
-- PurpleConnection *gc;
-- char *err;
--
-- if (user == NULL)
-- return;
--
--
--
-- if (ret_code == NM_OK) {
-- rc = nm_send_conference_invite(user, conference, user_record,
-- NULL, _sendinvite_resp_cb, NULL);
-- _check_for_disconnect(user, rc);
-- } else {
-- err = g_strdup_printf(_("Unable to create conference (%s)."), nm_error_to_string(ret_code));
-- gc = purple_account_get_connection(user->client_data);
-- purple_notify_error(gc, NULL, err, NULL);
-- g_free(err);
-- }
--}
--
--/*******************************************************************************
-- * Helper functions
-- ******************************************************************************/
--
--static char *
--_user_agent_string(void)
--{
--
--#if !defined(_WIN32)
--
-- const char *sysname = "";
-- const char *release = "";
-- struct utsname u;
--
-- if (uname(&u) == 0) {
-- sysname = u.sysname;
-- release = u.release;
-- } else {
-- sysname = "Linux";
-- release = "Unknown";
-- }
--
-- return g_strdup_printf("Purple/%s (%s; %s)", VERSION, sysname, release);
--
--#else
--
-- const char *sysname = "";
-- OSVERSIONINFO os_info;
-- SYSTEM_INFO sys_info;
--
-- os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-- GetVersionEx(&os_info);
-- GetSystemInfo(&sys_info);
--
-- if (os_info.dwPlatformId == VER_PLATFORM_WIN32_NT) {
-- switch (os_info.dwMajorVersion) {
-- case 3:
-- case 4:
-- sysname = "Windows NT";
-- break;
-- case 5:
-- switch (os_info.dwMinorVersion) {
-- case 0:
-- sysname = "Windows 2000";
-- break;
-- case 1:
-- sysname = "Windows XP";
-- break;
-- case 2:
-- sysname = "Windows Server 2003";
-- break;
-- default:
-- sysname = "Windows";
-- break;
-- }
-- break;
-- default:
-- sysname = "Windows";
-- break;
-- }
--
-- } else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
-- switch (os_info.dwMinorVersion) {
-- case 0:
-- sysname = "Windows 95";
-- break;
-- case 10:
-- sysname = "Windows 98";
-- break;
-- case 90:
-- sysname = "Windows ME";
-- break;
-- default:
-- sysname = "Windows";
-- break;
-- }
-- } else {
-- sysname = "Windows";
-- }
--
-- return g_strdup_printf("Purple/%s (%s; %ld.%ld)", VERSION, sysname,
-- os_info.dwMajorVersion, os_info.dwMinorVersion);
--
--#endif
--
--
--}
--
--static gboolean
--_is_disconnect_error(NMERR_T err)
--{
-- return (err == NMERR_TCP_WRITE ||
-- err == NMERR_TCP_READ || err == NMERR_PROTOCOL);
--}
--
--static gboolean
--_check_for_disconnect(NMUser * user, NMERR_T err)
--{
-- PurpleConnection *gc = purple_account_get_connection(user->client_data);
--
-- if (_is_disconnect_error(err)) {
--
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Error communicating with server. Closing connection."));
-- return TRUE;
--
-- }
--
-- return FALSE;
--}
--
--/* Check to see if the conference is instantiated, if so send the message.
-- * If not send the create conference -- the response handler for the createconf
-- * will call this function again.
-- */
--static void
--_send_message(NMUser * user, NMMessage * message)
--{
-- NMConference *conf;
-- NMERR_T rc = NM_OK;
--
-- conf = nm_message_get_conference(message);
-- if (conf) {
-- /* We have a conference make sure that the
-- server knows about it already. */
-- if (nm_conference_is_instantiated(conf)) {
--
-- /* We have everything that we need...finally! */
-- rc = nm_send_message(user, message, _send_message_resp_cb);
-- _check_for_disconnect(user, rc);
--
-- nm_release_message(message);
--
-- } else {
-- rc = nm_send_create_conference(user, conf, _createconf_resp_send_msg, message);
-- _check_for_disconnect(user, rc);
-- }
-- }
--}
--
--/*
-- * Update the status of the given buddy in the Purple buddy list
-- */
--static void
--_update_buddy_status(NMUser *user, PurpleBuddy * buddy, int novellstatus, int gmt)
--{
-- PurpleAccount *account;
-- const char *status_id;
-- const char *text = NULL;
-- const char *dn;
-- const char *name;
-- int idle = 0;
-- gboolean loggedin = TRUE;
--
-- account = purple_buddy_get_account(buddy);
-- name = purple_buddy_get_name(buddy);
--
-- switch (novellstatus) {
-- case NM_STATUS_AVAILABLE:
-- status_id = NOVELL_STATUS_TYPE_AVAILABLE;
-- break;
-- case NM_STATUS_AWAY:
-- status_id = NOVELL_STATUS_TYPE_AWAY;
-- break;
-- case NM_STATUS_BUSY:
-- status_id = NOVELL_STATUS_TYPE_BUSY;
-- break;
-- case NM_STATUS_OFFLINE:
-- status_id = NOVELL_STATUS_TYPE_OFFLINE;
-- loggedin = FALSE;
-- break;
-- case NM_STATUS_AWAY_IDLE:
-- status_id = NOVELL_STATUS_TYPE_AWAY;
-- idle = gmt;
-- break;
-- default:
-- status_id = NOVELL_STATUS_TYPE_OFFLINE;
-- loggedin = FALSE;
-- break;
-- }
--
-- /* Get status text for the user */
-- dn = nm_lookup_dn(user, name);
-- if (dn) {
-- NMUserRecord *user_record = nm_find_user_record(user, dn);
-- if (user_record) {
-- text = nm_user_record_get_status_text(user_record);
-- }
-- }
--
-- purple_prpl_got_user_status(account, name, status_id,
-- "message", text, NULL);
-- purple_prpl_got_user_idle(account, name,
-- (novellstatus == NM_STATUS_AWAY_IDLE), idle);
--}
--
--/* Iterate through the cached Purple buddy list and remove buddies
-- * that are not in the server side list.
-- */
--static void
--_remove_purple_buddies(NMUser *user)
--{
-- PurpleBlistNode *gnode;
-- PurpleBlistNode *cnode;
-- PurpleBlistNode *bnode;
-- PurpleGroup *group;
-- PurpleBuddy *buddy;
-- GSList *rem_list = NULL;
-- GSList *l;
-- NMFolder *folder = NULL;
-- const char *gname = NULL;
--
-- for (gnode = purple_blist_get_root(); gnode;
-- gnode = purple_blist_node_get_sibling_next(gnode)) {
-- if (!PURPLE_BLIST_NODE_IS_GROUP(gnode))
-- continue;
-- group = (PurpleGroup *) gnode;
-- gname = purple_group_get_name(group);
-- for (cnode = purple_blist_node_get_first_child(gnode);
-- cnode;
-- cnode = purple_blist_node_get_sibling_next(cnode)) {
-- if (!PURPLE_BLIST_NODE_IS_CONTACT(cnode))
-- continue;
-- for (bnode = purple_blist_node_get_first_child(cnode);
-- bnode;
-- bnode = purple_blist_node_get_sibling_next(bnode)) {
-- if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode))
-- continue;
-- buddy = (PurpleBuddy *) bnode;
-- if (purple_buddy_get_account(buddy) == user->client_data) {
-- if (strcmp(gname, NM_ROOT_FOLDER_NAME) == 0)
-- gname = "";
-- folder = nm_find_folder(user, gname);
-- if (folder == NULL ||
-- !nm_folder_find_contact_by_display_id(folder, purple_buddy_get_name(buddy))) {
-- rem_list = g_slist_append(rem_list, buddy);
-- }
-- }
-- }
-- }
-- }
--
-- if (rem_list) {
-- for (l = rem_list; l; l = l->next) {
-- purple_blist_remove_buddy(l->data);
-- }
-- g_slist_free(rem_list);
-- }
--}
--
--/* Add all of the contacts in the given folder to the Purple buddy list */
--static void
--_add_contacts_to_purple_blist(NMUser * user, NMFolder * folder)
--{
-- NMUserRecord *user_record = NULL;
-- NMContact *contact = NULL;
-- PurpleBuddy *buddy = NULL;
-- PurpleGroup *group;
-- NMERR_T cnt = 0, i;
-- const char *text = NULL;
-- const char *name = NULL;
-- const char *fname = NULL;
-- int status = 0;
--
-- /* If this is the root folder give it a name. Purple does not have the concept of
-- * a root folder.
-- */
-- fname = nm_folder_get_name(folder);
-- if (fname == NULL || *fname == '\0') {
-- fname = NM_ROOT_FOLDER_NAME;
-- }
--
-- /* Does the Purple group exist already? */
-- group = purple_find_group(fname);
-- if (group == NULL) {
-- group = purple_group_new(fname);
-- purple_blist_add_group(group, NULL);
-- }
--
-- /* Get each contact for this folder */
-- cnt = nm_folder_get_contact_count(folder);
-- for (i = 0; i < cnt; i++) {
-- contact = nm_folder_get_contact(folder, i);
-- if (contact) {
--
-- name = nm_contact_get_display_id(contact);
-- if (name) {
--
-- buddy = purple_find_buddy_in_group(user->client_data, name, group);
-- if (buddy == NULL) {
-- /* Add it to the purple buddy list */
-- buddy = purple_buddy_new(user->client_data,
-- name,
-- nm_contact_get_display_name(contact));
--
-- purple_blist_add_buddy(buddy, NULL, group, NULL);
-- }
--
-- /* Set the initial status for the buddy */
-- user_record = nm_contact_get_user_record(contact);
-- if (user_record) {
-- status = nm_user_record_get_status(user_record);
-- text = nm_user_record_get_status_text(user_record);
-- }
-- _update_buddy_status(user, buddy, status, time(0));
--
-- /* Save the new buddy as part of the contact object */
-- nm_contact_set_data(contact, (gpointer) buddy);
-- }
--
-- } else {
-- /* NULL contact. This should not happen, but
-- * let's break out of the loop.
-- */
-- break;
-- }
-- }
--}
--
--/* Add all of the server side contacts to the Purple buddy list. */
--static void
--_add_purple_buddies(NMUser * user)
--{
-- int cnt = 0, i;
-- NMFolder *root_folder = NULL;
-- NMFolder *folder = NULL;
--
-- root_folder = nm_get_root_folder(user);
-- if (root_folder) {
--
-- /* Add sub-folders and contacts to sub-folders...
-- * iterate throught the sub-folders in reverse order
-- * because Purple adds the folders to the front -- so we
-- * want to add the first folder last
-- */
-- cnt = nm_folder_get_subfolder_count(root_folder);
-- for (i = cnt-1; i >= 0; i--) {
-- folder = nm_folder_get_subfolder(root_folder, i);
-- if (folder) {
-- _add_contacts_to_purple_blist(user, folder);
-- }
-- }
--
-- /* Add contacts for the root folder */
-- _add_contacts_to_purple_blist(user, root_folder);
-- }
--}
--
--static void
--_sync_contact_list(NMUser *user)
--{
-- /* Remove all buddies from the local list that are
-- * not in the server side list and add all buddies
-- * from the server side list that are not in
-- * the local list
-- */
-- _remove_purple_buddies(user);
-- _add_purple_buddies(user);
-- user->clist_synched = TRUE;
--}
--
--static void
--_sync_privacy_lists(NMUser *user)
--{
-- GSList *node = NULL, *rem_list = NULL;
-- PurpleConnection *gc;
-- const char *name, *dn;
-- NMUserRecord *user_record;
--
-- if (user == NULL)
-- return;
--
-- gc = purple_account_get_connection(user->client_data);
-- if (gc == NULL)
-- return;
--
-- /* Set the Purple privacy setting */
-- if (user->default_deny) {
-- if (user->allow_list == NULL) {
-- gc->account->perm_deny = PURPLE_PRIVACY_DENY_ALL;
-- } else {
-- gc->account->perm_deny = PURPLE_PRIVACY_ALLOW_USERS;
-- }
-- } else {
-- if (user->deny_list == NULL) {
-- gc->account->perm_deny = PURPLE_PRIVACY_ALLOW_ALL;
-- } else {
-- gc->account->perm_deny = PURPLE_PRIVACY_DENY_USERS;
-- }
-- }
--
-- /* Add stuff */
-- for (node = user->allow_list; node; node = node->next) {
-- user_record = nm_find_user_record(user, (char *)node->data);
-- if (user_record)
-- name = nm_user_record_get_display_id(user_record);
-- else
-- name =(char *)node->data;
--
-- if (!g_slist_find_custom(gc->account->permit,
-- name, (GCompareFunc)purple_utf8_strcasecmp)) {
-- purple_privacy_permit_add(gc->account, name , TRUE);
-- }
-- }
--
-- for (node = user->deny_list; node; node = node->next) {
-- user_record = nm_find_user_record(user, (char *)node->data);
-- if (user_record)
-- name = nm_user_record_get_display_id(user_record);
-- else
-- name =(char *)node->data;
--
-- if (!g_slist_find_custom(gc->account->deny,
-- name, (GCompareFunc)purple_utf8_strcasecmp)) {
-- purple_privacy_deny_add(gc->account, name, TRUE);
-- }
-- }
--
--
-- /* Remove stuff */
-- for (node = gc->account->permit; node; node = node->next) {
-- dn = nm_lookup_dn(user, (char *)node->data);
-- if (dn != NULL &&
-- !g_slist_find_custom(user->allow_list,
-- dn, (GCompareFunc)purple_utf8_strcasecmp)) {
-- rem_list = g_slist_append(rem_list, node->data);
-- }
-- }
--
-- if (rem_list) {
-- for (node = rem_list; node; node = node->next) {
-- purple_privacy_permit_remove(gc->account, (char *)node->data, TRUE);
-- }
-- g_slist_free(rem_list);
-- rem_list = NULL;
-- }
--
-- for (node = gc->account->deny; node; node = node->next) {
-- dn = nm_lookup_dn(user, (char *)node->data);
-- if (dn != NULL &&
-- !g_slist_find_custom(user->deny_list,
-- dn, (GCompareFunc)purple_utf8_strcasecmp)) {
-- rem_list = g_slist_append(rem_list, node->data);
-- }
-- }
--
-- if (rem_list) {
-- for (node = rem_list; node; node = node->next) {
-- purple_privacy_deny_remove(gc->account, (char *)node->data, TRUE);
-- }
-- g_slist_free(rem_list);
-- }
--}
--
-- /* Map known property tags to user-friendly strings */
--static const char *
--_map_property_tag(const char *tag)
--{
-- if (tag == NULL) return NULL;
--
-- if (strcmp(tag, "telephoneNumber") == 0)
-- return _("Telephone Number");
-- else if (strcmp(tag, "L") == 0)
-- return _("Location");
-- else if (strcmp(tag, "OU") == 0)
-- return _("Department");
-- else if (strcmp(tag, "personalTitle") == 0)
-- return _("Personal Title");
-- else if (strcmp(tag, "Title") == 0)
-- return _("Job Title");
-- else if (strcmp(tag, "mailstop") == 0)
-- return _("Mailstop");
-- else if (strcmp(tag, "Internet EMail Address") == 0)
-- return _("Email Address");
-- else
-- return tag;
--}
--
--/* Display a dialog box showing the properties for the given user record */
--static void
--_show_info(PurpleConnection * gc, NMUserRecord * user_record, char * name)
--{
-- PurpleNotifyUserInfo *user_info = purple_notify_user_info_new();
-- int count, i;
-- NMProperty *property;
-- const char *tag, *value;
--
-- tag = _("User ID");
-- value = nm_user_record_get_userid(user_record);
-- if (value) {
-- purple_notify_user_info_add_pair(user_info, tag, value);
-- }
--
--/* tag = _("DN");
-- value = nm_user_record_get_dn(user_record);
-- if (value) {
-- purple_notify_user_info_add_pair(user_info, tag, value);
-- }
--*/
--
-- tag = _("Full name");
-- value = nm_user_record_get_full_name(user_record);
-- if (value) {
-- purple_notify_user_info_add_pair(user_info, tag, value);
-- }
--
-- count = nm_user_record_get_property_count(user_record);
-- for (i = 0; i < count; i++) {
-- property = nm_user_record_get_property(user_record, i);
-- if (property) {
-- tag = _map_property_tag(nm_property_get_tag(property));
-- value = nm_property_get_value(property);
-- if (tag && value) {
-- purple_notify_user_info_add_pair(user_info, tag, value);
-- }
-- nm_release_property(property);
-- }
-- }
--
-- purple_notify_userinfo(gc, name, user_info, NULL, NULL);
-- purple_notify_user_info_destroy(user_info);
--
-- g_free(name);
--}
--
--/* Send a join conference, the first item in the parms list is the
-- * NMUser object and the second item is the conference to join.
-- * This callback is passed to purple_request_action when we ask the
-- * user if they want to join the conference.
-- */
--static void
--_join_conference_cb(GSList * parms)
--{
-- NMUser *user;
-- NMConference *conference;
-- NMERR_T rc = NM_OK;
--
-- if (parms == NULL || g_slist_length(parms) != 2)
-- return;
--
-- user = g_slist_nth_data(parms, 0);
-- conference = g_slist_nth_data(parms, 1);
--
-- if (user && conference) {
-- rc = nm_send_join_conference(user, conference,
-- _join_conf_resp_cb, conference);
-- _check_for_disconnect(user, rc);
-- }
--
-- g_slist_free(parms);
--}
--
--/* Send a reject conference, the first item in the parms list is the
-- * NMUser object and the second item is the conference to reject.
-- * This callback is passed to purple_request_action when we ask the
-- * user if they want to joing the conference.
-- */
--static void
--_reject_conference_cb(GSList * parms)
--{
-- NMUser *user;
-- NMConference *conference;
-- NMERR_T rc = NM_OK;
--
-- if (parms == NULL || g_slist_length(parms) != 2)
-- return;
--
-- user = g_slist_nth_data(parms, 0);
-- conference = g_slist_nth_data(parms, 1);
--
-- if (user && conference) {
-- rc = nm_send_reject_conference(user, conference, NULL, NULL);
-- _check_for_disconnect(user, rc);
-- }
--
-- g_slist_free(parms);
--}
--
--static void
--_initiate_conference_cb(PurpleBlistNode *node, gpointer ignored)
--{
-- PurpleBuddy *buddy;
-- PurpleConnection *gc;
--
-- NMUser *user;
-- const char *conf_name;
-- PurpleConversation *chat = NULL;
-- NMUserRecord *user_record;
-- NMConference *conference;
--
-- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
--
-- buddy = (PurpleBuddy *) node;
-- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
--
-- user = gc->proto_data;
-- if (user == NULL)
-- return;
--
-- /* We should already have a userrecord for the buddy */
-- user_record = nm_find_user_record(user, purple_buddy_get_name(buddy));
-- if (user_record == NULL)
-- return;
--
-- conf_name = _get_conference_name(++user->conference_count);
-- chat = serv_got_joined_chat(gc, user->conference_count, conf_name);
-- if (chat) {
--
-- conference = nm_create_conference(NULL);
-- nm_conference_set_data(conference, (gpointer) chat);
-- nm_send_create_conference(user, conference, _createconf_resp_send_invite, user_record);
-- nm_release_conference(conference);
-- }
--}
--
--const char *
--_get_conference_name(int id)
--{
-- static char *name = NULL;
--
-- if (name)
-- g_free(name);
--
-- name = g_strdup_printf(_("GroupWise Conference %d"), id);
--
-- return name;
--}
--
--static void
--_show_privacy_locked_error(PurpleConnection *gc, NMUser *user)
--{
-- char *err;
--
-- err = g_strdup_printf(_("Unable to change server side privacy settings (%s)."),
-- nm_error_to_string(NMERR_ADMIN_LOCKED));
-- purple_notify_error(gc, NULL, err, NULL);
-- g_free(err);
--}
--
--/*******************************************************************************
-- * Connect and recv callbacks
-- ******************************************************************************/
--
--static void
--novell_ssl_connect_error(PurpleSslConnection * gsc,
-- PurpleSslErrorType error, gpointer data)
--{
-- PurpleConnection *gc;
-- NMUser *user;
--
-- gc = data;
-- user = gc->proto_data;
-- user->conn->ssl_conn->data = NULL;
--
-- purple_connection_ssl_error (gc, error);
--}
--
--static void
--novell_ssl_recv_cb(gpointer data, PurpleSslConnection * gsc,
-- PurpleInputCondition condition)
--{
-- PurpleConnection *gc = data;
-- NMUser *user;
-- NMERR_T rc;
--
-- if (gc == NULL)
-- return;
--
-- user = gc->proto_data;
-- if (user == NULL)
-- return;
--
-- rc = nm_process_new_data(user);
-- if (rc != NM_OK) {
--
-- if (_is_disconnect_error(rc)) {
--
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Error communicating with server. Closing connection."));
-- } else {
-- purple_debug(PURPLE_DEBUG_INFO, "novell",
-- "Error processing event or response (%d).\n", rc);
-- }
-- }
--}
--
--static void
--novell_ssl_connected_cb(gpointer data, PurpleSslConnection * gsc,
-- PurpleInputCondition cond)
--{
-- PurpleConnection *gc = data;
-- NMUser *user;
-- NMConn *conn;
-- NMERR_T rc = 0;
-- const char *pwd = NULL;
-- const char *my_addr = NULL;
-- char *ua = NULL;
--
-- if (gc == NULL || gsc == NULL)
-- return;
--
-- user = gc->proto_data;
-- if ((user == NULL) || (conn = user->conn) == NULL)
-- return;
--
-- purple_connection_update_progress(gc, _("Authenticating..."),
-- 2, NOVELL_CONNECT_STEPS);
--
-- my_addr = purple_network_get_my_ip(gsc->fd);
-- pwd = purple_connection_get_password(gc);
-- ua = _user_agent_string();
--
-- rc = nm_send_login(user, pwd, my_addr, ua, _login_resp_cb, NULL);
-- if (rc == NM_OK) {
-- conn->connected = TRUE;
-- purple_ssl_input_add(gsc, novell_ssl_recv_cb, gc);
-- } else {
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Unable to connect"));
-- }
--
-- purple_connection_update_progress(gc, _("Waiting for response..."),
-- 3, NOVELL_CONNECT_STEPS);
--
-- g_free(ua);
--}
--
--/*******************************************************************************
-- * Event callback and event handlers
-- ******************************************************************************/
--
--static void
--_evt_receive_message(NMUser * user, NMEvent * event)
--{
-- NMUserRecord *user_record = NULL;
-- NMContact *contact = NULL;
-- PurpleConversation *gconv;
-- NMConference *conference;
-- PurpleMessageFlags flags;
-- char *text = NULL;
--
-- text = g_markup_escape_text(nm_event_get_text(event), -1);
--
-- conference = nm_event_get_conference(event);
-- if (conference) {
--
-- PurpleConversation *chat = nm_conference_get_data(conference);
--
-- /* Is this a single person 'conversation' or a conference? */
-- if (chat == NULL && nm_conference_get_participant_count(conference) == 1) {
--
-- user_record = nm_find_user_record(user, nm_event_get_source(event));
-- if (user_record) {
--
-- flags = 0;
-- if (nm_event_get_type(event) == NMEVT_RECEIVE_AUTOREPLY)
-- flags |= PURPLE_MESSAGE_AUTO_RESP;
--
-- serv_got_im(purple_account_get_connection(user->client_data),
-- nm_user_record_get_display_id(user_record),
-- text, flags,
-- nm_event_get_gmt(event));
--
-- gconv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-- nm_user_record_get_display_id(user_record),
-- (PurpleAccount *) user->client_data);
-- if (gconv) {
--
-- contact = nm_find_contact(user, nm_event_get_source(event));
-- if (contact) {
--
-- purple_conversation_set_title(
-- gconv, nm_contact_get_display_name(contact));
--
--
-- } else {
--
-- const char *name =
-- nm_user_record_get_full_name(user_record);
--
-- if (name == NULL)
-- name = nm_user_record_get_userid(user_record);
--
-- purple_conversation_set_title(gconv, name);
-- }
--
-- }
--
-- } else {
-- /* this should not happen, see the event code.
-- * the event code will get the contact details from
-- * the server if it does not have them before calling
-- * the event callback.
-- */
-- }
--
-- } else if (chat) {
--
-- /* get the contact for send if we have one */
-- NMContact *contact = nm_find_contact(user,
-- nm_event_get_source(event));
--
-- /* get the user record for the sender */
-- user_record = nm_find_user_record(user, nm_event_get_source(event));
-- if (user_record) {
-- const char *name = nm_contact_get_display_name(contact);
--
-- if (name == NULL) {
-- name = nm_user_record_get_full_name(user_record);
-- if (name == NULL)
-- name = nm_user_record_get_display_id(user_record);
-- }
--
-- serv_got_chat_in(purple_account_get_connection(user->client_data),
-- purple_conv_chat_get_id(PURPLE_CONV_CHAT(chat)),
-- name, 0, text, nm_event_get_gmt(event));
-- }
-- }
-- }
--
-- g_free(text);
--}
--
--static void
--_evt_conference_left(NMUser * user, NMEvent * event)
--{
-- PurpleConversation *chat;
-- NMConference *conference;
--
-- conference = nm_event_get_conference(event);
-- if (conference) {
-- chat = nm_conference_get_data(conference);
-- if (chat) {
-- NMUserRecord *ur = nm_find_user_record(user,
-- nm_event_get_source(event));
--
-- if (ur)
-- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(chat),
-- nm_user_record_get_display_id(ur),
-- NULL);
-- }
-- }
--}
--
--static void
--_evt_conference_invite_notify(NMUser * user, NMEvent * event)
--{
-- PurpleConversation *gconv;
-- NMConference *conference;
-- NMUserRecord *user_record = NULL;
-- char *str = NULL;
--
-- user_record = nm_find_user_record(user, nm_event_get_source(event));
-- conference = nm_event_get_conference(event);
-- if (user_record && conference) {
-- gconv = nm_conference_get_data(conference);
-- str = g_strdup_printf(_("%s has been invited to this conversation."),
-- nm_user_record_get_display_id(user_record));
-- purple_conversation_write(gconv, NULL, str,
-- PURPLE_MESSAGE_SYSTEM, time(NULL));
-- g_free(str);
-- }
--}
--
--static void
--_evt_conference_invite(NMUser * user, NMEvent * event)
--{
-- NMUserRecord *ur;
-- PurpleConnection *gc;
-- GSList *parms = NULL;
-- const char *title = NULL;
-- const char *secondary = NULL;
-- const char *name = NULL;
-- char *primary = NULL;
-- time_t gmt;
--
-- ur = nm_find_user_record(user, nm_event_get_source(event));
-- if (ur)
-- name = nm_user_record_get_full_name(ur);
--
-- if (name == NULL)
-- name = nm_event_get_source(event);
--
-- gmt = nm_event_get_gmt(event);
-- title = _("Invitation to Conversation");
-- primary = g_strdup_printf(_("Invitation from: %s\n\nSent: %s"),
-- name, purple_date_format_full(localtime(&gmt)));
-- secondary = _("Would you like to join the conversation?");
--
-- /* Set up parms list for the callbacks
-- * We need to send the NMUser object and
-- * the NMConference object to the callbacks
-- */
-- parms = NULL;
-- parms = g_slist_append(parms, user);
-- parms = g_slist_append(parms, nm_event_get_conference(event));
--
-- /* Prompt the user */
-- /* TODO: Would it be better to use serv_got_chat_invite() here? */
-- gc = purple_account_get_connection(user->client_data);
-- purple_request_action(gc, title, primary, secondary,
-- PURPLE_DEFAULT_ACTION_NONE,
-- purple_connection_get_account(gc), name, NULL,
-- parms, 2,
-- _("Yes"), G_CALLBACK(_join_conference_cb),
-- _("No"), G_CALLBACK(_reject_conference_cb));
--
-- g_free(primary);
--}
--
--
--static void
--_evt_conference_joined(NMUser * user, NMEvent * event)
--{
-- PurpleConversation *chat = NULL;
-- PurpleConnection *gc;
-- NMConference *conference = NULL;
-- NMUserRecord *ur = NULL;
-- const char *name;
-- const char *conf_name;
--
-- gc = purple_account_get_connection(user->client_data);
-- if (gc == NULL)
-- return;
--
-- conference = nm_event_get_conference(event);
-- if (conference) {
-- chat = nm_conference_get_data(conference);
-- if (nm_conference_get_participant_count(conference) == 2 && chat == NULL) {
-- ur = nm_conference_get_participant(conference, 0);
-- if (ur) {
-- conf_name = _get_conference_name(++user->conference_count);
-- chat =
-- serv_got_joined_chat(gc, user->conference_count, conf_name);
-- if (chat) {
--
-- nm_conference_set_data(conference, (gpointer) chat);
--
-- name = nm_user_record_get_display_id(ur);
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(chat), name, NULL,
-- PURPLE_CBFLAGS_NONE, TRUE);
--
-- }
-- }
-- }
--
-- if (chat != NULL) {
-- ur = nm_find_user_record(user, nm_event_get_source(event));
-- if (ur) {
-- name = nm_user_record_get_display_id(ur);
-- if (!purple_conv_chat_find_user(PURPLE_CONV_CHAT(chat), name)) {
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(chat), name, NULL,
-- PURPLE_CBFLAGS_NONE, TRUE);
-- }
-- }
-- }
-- }
--}
--
--static void
--_evt_status_change(NMUser * user, NMEvent * event)
--{
-- PurpleBuddy *buddy = NULL;
-- GSList *buddies;
-- GSList *bnode;
-- NMUserRecord *user_record;
-- const char *display_id;
-- int status;
--
-- user_record = nm_event_get_user_record(event);
-- if (user_record) {
--
-- /* Retrieve new status */
-- status = nm_user_record_get_status(user_record);
--
-- /* Update status for buddy in all folders */
-- display_id = nm_user_record_get_display_id(user_record);
-- buddies = purple_find_buddies(user->client_data, display_id);
-- for (bnode = buddies; bnode; bnode = bnode->next) {
-- buddy = (PurpleBuddy *) bnode->data;
-- if (buddy) {
-- _update_buddy_status(user, buddy, status, nm_event_get_gmt(event));
-- }
-- }
--
-- g_slist_free(buddies);
--
-- }
--}
--
--static void
--_evt_user_disconnect(NMUser * user, NMEvent * event)
--{
-- PurpleConnection *gc;
-- PurpleAccount *account = user->client_data;
--
-- gc = purple_account_get_connection(account);
-- if (gc)
-- {
-- if (!purple_account_get_remember_password(account))
-- purple_account_set_password(account, NULL);
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NAME_IN_USE,
-- _("You have signed on from another location"));
-- }
--}
--
--static void
--_evt_user_typing(NMUser * user, NMEvent * event)
--{
-- PurpleConnection *gc;
-- NMUserRecord *user_record = NULL;
--
-- gc = purple_account_get_connection((PurpleAccount *) user->client_data);
-- if (gc) {
-- user_record = nm_find_user_record(user, nm_event_get_source(event));
-- if (user_record) {
-- serv_got_typing(gc, nm_user_record_get_display_id(user_record),
-- 30, PURPLE_TYPING);
-- }
-- }
--}
--
--static void
--_evt_user_not_typing(NMUser * user, NMEvent * event)
--{
-- PurpleConnection *gc;
-- NMUserRecord *user_record;
--
-- gc = purple_account_get_connection((PurpleAccount *) user->client_data);
-- if (gc) {
-- user_record = nm_find_user_record(user, nm_event_get_source(event));
-- if (user_record) {
-- serv_got_typing_stopped(gc,
-- nm_user_record_get_display_id(user_record));
-- }
-- }
--}
--
--static void
--_evt_undeliverable_status(NMUser * user, NMEvent * event)
--{
-- NMUserRecord *ur;
-- PurpleConversation *gconv;
-- char *str;
--
-- ur = nm_find_user_record(user, nm_event_get_source(event));
-- if (ur) {
-- /* XXX - Should this be PURPLE_CONV_TYPE_IM? */
-- gconv =
-- purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,
-- nm_user_record_get_display_id(ur),
-- user->client_data);
-- if (gconv) {
-- const char *name = nm_user_record_get_full_name(ur);
--
-- if (name == NULL) {
-- name = nm_user_record_get_display_id(ur);
-- }
-- str = g_strdup_printf(_("%s appears to be offline and did not receive"
-- " the message that you just sent."), name);
-- purple_conversation_write(gconv, NULL, str,
-- PURPLE_MESSAGE_SYSTEM, time(NULL));
-- g_free(str);
-- }
-- }
--}
--
--static void
--_event_callback(NMUser * user, NMEvent * event)
--{
-- if (user == NULL || event == NULL)
-- return;
--
-- switch (nm_event_get_type(event)) {
-- case NMEVT_STATUS_CHANGE:
-- _evt_status_change(user, event);
-- break;
-- case NMEVT_RECEIVE_AUTOREPLY:
-- case NMEVT_RECEIVE_MESSAGE:
-- _evt_receive_message(user, event);
-- break;
-- case NMEVT_USER_DISCONNECT:
-- _evt_user_disconnect(user, event);
-- break;
-- case NMEVT_USER_TYPING:
-- _evt_user_typing(user, event);
-- break;
-- case NMEVT_USER_NOT_TYPING:
-- _evt_user_not_typing(user, event);
-- break;
-- case NMEVT_SERVER_DISCONNECT:
-- /* Nothing to do? */
-- break;
-- case NMEVT_INVALID_RECIPIENT:
-- break;
-- case NMEVT_UNDELIVERABLE_STATUS:
-- _evt_undeliverable_status(user, event);
-- break;
-- case NMEVT_CONFERENCE_INVITE_NOTIFY:
-- /* Someone else has been invited to join a
-- * conference that we are currently a part of
-- */
-- _evt_conference_invite_notify(user, event);
-- break;
-- case NMEVT_CONFERENCE_INVITE:
-- /* We have been invited to join a conference */
-- _evt_conference_invite(user, event);
-- break;
-- case NMEVT_CONFERENCE_JOINED:
-- /* Some one has joined a conference that we
-- * are a part of
-- */
-- _evt_conference_joined(user, event);
-- break;
-- case NMEVT_CONFERENCE_LEFT:
-- /* Someone else has left a conference that we
-- * are currently a part of
-- */
-- _evt_conference_left(user, event);
-- break;
-- default:
-- purple_debug(PURPLE_DEBUG_INFO, "novell",
-- "_event_callback(): unhandled event, %d\n",
-- nm_event_get_type(event));
-- break;
-- }
--}
--
--/*******************************************************************************
-- * Prpl Ops
-- ******************************************************************************/
--
--static void
--novell_login(PurpleAccount * account)
--{
-- PurpleConnection *gc;
-- NMUser *user = NULL;
-- const char *server;
-- const char *name;
-- int port;
--
-- if (account == NULL)
-- return;
--
-- gc = purple_account_get_connection(account);
-- if (gc == NULL)
-- return;
--
-- server = purple_account_get_string(account, "server", NULL);
-- if (server == NULL || *server == '\0') {
--
-- /* TODO: Would be nice to prompt if not set!
-- * purple_request_fields(gc, _("Server Address"),...);
-- */
--
-- /* ...but for now just error out with a nice message. */
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
-- _("Unable to connect to server. Please enter the "
-- "address of the server to which you wish to connect."));
-- return;
-- }
--
-- port = purple_account_get_int(account, "port", DEFAULT_PORT);
-- name = purple_account_get_username(account);
--
-- user = nm_initialize_user(name, server, port, account, _event_callback);
-- if (user && user->conn) {
-- /* save user */
-- gc->proto_data = user;
--
-- /* connect to the server */
-- purple_connection_update_progress(gc, _("Connecting"),
-- 1, NOVELL_CONNECT_STEPS);
--
-- user->conn->use_ssl = TRUE;
--
-- user->conn->ssl_conn = g_new0(NMSSLConn, 1);
-- user->conn->ssl_conn->read = (nm_ssl_read_cb) purple_ssl_read;
-- user->conn->ssl_conn->write = (nm_ssl_write_cb) purple_ssl_write;
--
-- user->conn->ssl_conn->data = purple_ssl_connect(user->client_data,
-- user->conn->addr, user->conn->port,
-- novell_ssl_connected_cb, novell_ssl_connect_error, gc);
-- if (user->conn->ssl_conn->data == NULL) {
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
-- _("SSL support unavailable"));
-- }
-- }
--}
--
--static void
--novell_close(PurpleConnection * gc)
--{
-- NMUser *user;
-- NMConn *conn;
--
-- if (gc == NULL)
-- return;
--
-- user = gc->proto_data;
-- if (user) {
-- conn = user->conn;
-- if (conn && conn->ssl_conn) {
-- purple_ssl_close(user->conn->ssl_conn->data);
-- }
-- nm_deinitialize_user(user);
-- }
-- gc->proto_data = NULL;
--}
--
--static int
--novell_send_im(PurpleConnection * gc, const char *name,
-- const char *message_body, PurpleMessageFlags flags)
--{
-- NMUserRecord *user_record = NULL;
-- NMConference *conf = NULL;
-- NMMessage *message;
-- NMUser *user;
-- const char *dn = NULL;
-- char *plain;
-- gboolean done = TRUE, created_conf = FALSE;
-- NMERR_T rc = NM_OK;
--
-- if (gc == NULL || name == NULL ||
-- message_body == NULL || *message_body == '\0')
-- return 0;
--
-- user = gc->proto_data;
-- if (user == NULL)
-- return 0;
--
-- /* Create a new message */
-- plain = purple_unescape_html(message_body);
-- message = nm_create_message(plain);
-- g_free(plain);
--
-- /* Need to get the DN for the buddy so we can look up the convo */
-- dn = nm_lookup_dn(user, name);
--
-- /* Do we already know about the sender? */
-- user_record = nm_find_user_record(user, dn);
-- if (user_record) {
--
-- /* Do we already have an instantiated conference? */
-- conf = nm_find_conversation(user, dn);
-- if (conf == NULL) {
--
-- /* If not, create a blank conference */
-- conf = nm_create_conference(NULL);
-- created_conf = TRUE;
--
-- nm_conference_add_participant(conf, user_record);
-- }
--
-- nm_message_set_conference(message, conf);
--
-- /* Make sure conference is instantiated */
-- if (!nm_conference_is_instantiated(conf)) {
--
-- /* It is not, so send the createconf. We will
-- * have to finish sending the message when we
-- * get the response with the new conference guid.
-- */
-- rc = nm_send_create_conference(user, conf, _createconf_resp_send_msg, message);
-- _check_for_disconnect(user, rc);
--
-- done = FALSE;
-- }
--
-- } else {
--
-- /* If we don't have details for the user, then we don't have
-- * a conference yet. So create one and send the getdetails
-- * to the server. We will have to finish sending the message
-- * when we get the response from the server.
-- */
-- conf = nm_create_conference(NULL);
-- created_conf = TRUE;
--
-- nm_message_set_conference(message, conf);
--
-- rc = nm_send_get_details(user, name, _get_details_resp_send_msg, message);
-- _check_for_disconnect(user, rc);
--
-- done = FALSE;
-- }
--
-- if (done) {
--
-- /* Did we find everything we needed? */
-- rc = nm_send_message(user, message, _send_message_resp_cb);
-- _check_for_disconnect(user, rc);
--
-- nm_release_message(message);
-- }
--
-- if (created_conf && conf)
-- nm_release_conference(conf);
--
-- return 1;
--}
--
--static unsigned int
--novell_send_typing(PurpleConnection * gc, const char *name, PurpleTypingState state)
--{
-- NMConference *conf = NULL;
-- NMUser *user;
-- const char *dn = NULL;
-- NMERR_T rc = NM_OK;
--
-- if (gc == NULL || name == NULL)
-- return 0;
--
-- user = gc->proto_data;
-- if (user == NULL)
-- return 0;
--
-- /* Need to get the DN for the buddy so we can look up the convo */
-- dn = nm_lookup_dn(user, name);
-- if (dn) {
--
-- /* Now find the conference in our list */
-- conf = nm_find_conversation(user, dn);
-- if (conf) {
--
-- rc = nm_send_typing(user, conf,
-- ((state == PURPLE_TYPING) ? TRUE : FALSE), NULL);
-- _check_for_disconnect(user, rc);
--
-- }
--
-- }
--
-- return 0;
--}
--
--static void
--novell_convo_closed(PurpleConnection * gc, const char *who)
--{
-- NMUser *user;
-- NMConference *conf;
-- const char *dn;
-- NMERR_T rc = NM_OK;
--
-- if (gc == NULL || who == NULL)
-- return;
--
-- user = gc->proto_data;
-- if (user && (dn = nm_lookup_dn(user, who))) {
-- conf = nm_find_conversation(user, dn);
-- if (conf) {
-- rc = nm_send_leave_conference(user, conf, NULL, NULL);
-- _check_for_disconnect(user, rc);
-- }
-- }
--}
--
--static void
--novell_chat_leave(PurpleConnection * gc, int id)
--{
-- NMConference *conference;
-- NMUser *user;
-- PurpleConversation *chat;
-- GSList *cnode;
-- NMERR_T rc = NM_OK;
--
-- if (gc == NULL)
-- return;
--
-- user = gc->proto_data;
-- if (user == NULL)
-- return;
--
-- for (cnode = user->conferences; cnode != NULL; cnode = cnode->next) {
-- conference = cnode->data;
-- if (conference && (chat = nm_conference_get_data(conference))) {
-- if (purple_conv_chat_get_id(PURPLE_CONV_CHAT(chat)) == id) {
-- rc = nm_send_leave_conference(user, conference, NULL, NULL);
-- _check_for_disconnect(user, rc);
-- break;
-- }
-- }
-- }
--
-- serv_got_chat_left(gc, id);
--}
--
--static void
--novell_chat_invite(PurpleConnection *gc, int id,
-- const char *message, const char *who)
--{
-- NMConference *conference;
-- NMUser *user;
-- PurpleConversation *chat;
-- GSList *cnode;
-- NMERR_T rc = NM_OK;
-- NMUserRecord *user_record = NULL;
--
-- if (gc == NULL)
-- return;
--
-- user = gc->proto_data;
-- if (user == NULL)
-- return;
--
-- user_record = nm_find_user_record(user, who);
-- if (user_record == NULL) {
-- rc = nm_send_get_details(user, who, _get_details_resp_send_invite, GINT_TO_POINTER(id));
-- _check_for_disconnect(user, rc);
-- return;
-- }
--
-- for (cnode = user->conferences; cnode != NULL; cnode = cnode->next) {
-- conference = cnode->data;
-- if (conference && (chat = nm_conference_get_data(conference))) {
-- if (purple_conv_chat_get_id(PURPLE_CONV_CHAT(chat)) == id) {
-- rc = nm_send_conference_invite(user, conference, user_record,
-- message, _sendinvite_resp_cb, NULL);
-- _check_for_disconnect(user, rc);
-- break;
-- }
-- }
-- }
--}
--
--static int
--novell_chat_send(PurpleConnection * gc, int id, const char *text, PurpleMessageFlags flags)
--{
-- NMConference *conference;
-- PurpleConversation *chat;
-- GSList *cnode;
-- NMMessage *message;
-- NMUser *user;
-- NMERR_T rc = NM_OK;
-- const char *name;
-- char *str, *plain;
--
-- if (gc == NULL || text == NULL)
-- return -1;
--
-- user = gc->proto_data;
-- if (user == NULL)
-- return -1;
--
-- plain = purple_unescape_html(text);
-- message = nm_create_message(plain);
-- g_free(plain);
--
-- for (cnode = user->conferences; cnode != NULL; cnode = cnode->next) {
-- conference = cnode->data;
-- if (conference && (chat = nm_conference_get_data(conference))) {
-- if (purple_conv_chat_get_id(PURPLE_CONV_CHAT(chat)) == id) {
--
-- nm_message_set_conference(message, conference);
--
-- /* check to see if the conference is instatiated yet */
-- if (!nm_conference_is_instantiated(conference)) {
-- nm_message_add_ref(message);
-- nm_send_create_conference(user, conference, _createconf_resp_send_msg, message);
-- } else {
-- rc = nm_send_message(user, message, _send_message_resp_cb);
-- }
--
-- nm_release_message(message);
--
-- if (!_check_for_disconnect(user, rc)) {
--
-- /* Use the account alias if it is set */
-- name = purple_account_get_alias(user->client_data);
-- if (name == NULL || *name == '\0') {
--
-- /* If there is no account alias, try full name */
-- name = nm_user_record_get_full_name(user->user_record);
-- if (name == NULL || *name == '\0') {
--
-- /* Fall back to the username that we are signed in with */
-- name = purple_account_get_username(user->client_data);
-- }
-- }
--
-- serv_got_chat_in(gc, id, name, flags, text, time(NULL));
-- return 0;
-- } else
-- return -1;
--
-- }
-- }
-- }
--
--
-- /* The conference was not found, must be closed */
-- chat = purple_find_chat(gc, id);
-- if (chat) {
-- str = g_strdup(_("This conference has been closed."
-- " No more messages can be sent."));
-- purple_conversation_write(chat, NULL, str, PURPLE_MESSAGE_SYSTEM, time(NULL));
-- g_free(str);
-- }
--
-- if (message)
-- nm_release_message(message);
--
-- return -1;
--}
--
--static void
--novell_add_buddy(PurpleConnection * gc, PurpleBuddy *buddy, PurpleGroup * group)
--{
-- NMFolder *folder = NULL;
-- NMContact *contact;
-- NMUser *user;
-- NMERR_T rc = NM_OK;
-- const char *alias, *gname, *bname;
--
-- if (gc == NULL || buddy == NULL || group == NULL)
-- return;
--
-- user = (NMUser *) purple_connection_get_protocol_data(gc);
-- if (user == NULL)
-- return;
--
-- /* If we haven't synched the contact list yet, ignore
-- * the add_buddy calls. Server side list is the master.
-- */
-- if (!user->clist_synched)
-- return;
--
-- /* Don't re-add a buddy that is already on our contact list */
-- if (nm_find_user_record(user, purple_buddy_get_name(buddy)) != NULL)
-- return;
--
-- contact = nm_create_contact();
-- nm_contact_set_dn(contact, purple_buddy_get_name(buddy));
--
-- /* Remove the PurpleBuddy (we will add it back after adding it
-- * to the server side list). Save the alias if there is one.
-- */
-- alias = purple_buddy_get_alias(buddy);
-- bname = purple_buddy_get_name(buddy);
-- if (alias && strcmp(alias, bname))
-- nm_contact_set_display_name(contact, alias);
--
-- purple_blist_remove_buddy(buddy);
-- buddy = NULL;
--
-- gname = purple_group_get_name(group);
-- if (strcmp(gname, NM_ROOT_FOLDER_NAME) == 0) {
-- gname = "";
-- }
--
-- folder = nm_find_folder(user, gname);
-- if (folder) {
--
-- /* We have everything that we need, so send the createcontact */
-- rc = nm_send_create_contact(user, folder, contact,
-- _create_contact_resp_cb, contact);
--
-- } else {
--
-- /* Need to create the folder before we can add the contact */
-- rc = nm_send_create_folder(user, gname,
-- _create_folder_resp_add_contact, contact);
-- }
--
-- _check_for_disconnect(user, rc);
--
--}
--
--static void
--novell_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
--{
-- NMContact *contact;
-- NMFolder *folder;
-- NMUser *user;
-- const char *dn, *gname;
-- NMERR_T rc = NM_OK;
--
-- if (gc == NULL || buddy == NULL || group == NULL)
-- return;
--
-- user = (NMUser *) gc->proto_data;
-- if (user && (dn = nm_lookup_dn(user, purple_buddy_get_name(buddy)))) {
-- gname = purple_group_get_name(group);
-- if (strcmp(gname, NM_ROOT_FOLDER_NAME) == 0) {
-- gname = "";
-- }
-- folder = nm_find_folder(user, gname);
-- if (folder) {
-- contact = nm_folder_find_contact(folder, dn);
-- if (contact) {
--
-- /* Remove the buddy from the contact */
-- nm_contact_set_data(contact, NULL);
--
-- /* Tell the server to remove the contact */
-- rc = nm_send_remove_contact(user, folder, contact,
-- _remove_contact_resp_cb, NULL);
-- _check_for_disconnect(user, rc);
-- }
-- }
-- }
--}
--
--static void
--novell_remove_group(PurpleConnection * gc, PurpleGroup *group)
--{
-- NMUser *user;
-- NMERR_T rc = NM_OK;
--
-- if (gc == NULL || group == NULL)
-- return;
--
-- user = (NMUser *) gc->proto_data;
-- if (user) {
-- NMFolder *folder = nm_find_folder(user, purple_group_get_name(group));
--
-- if (folder) {
-- rc = nm_send_remove_folder(user, folder,
-- _remove_folder_resp_cb, NULL);
-- _check_for_disconnect(user, rc);
-- }
-- }
--}
--
--static void
--novell_alias_buddy(PurpleConnection * gc, const char *name, const char *alias)
--{
-- NMContact *contact;
-- NMUser *user;
-- GList *contacts = NULL;
-- GList *cnode = NULL;
-- const char *dn = NULL, *fname = NULL;
-- NMERR_T rc = NM_OK;
--
-- if (gc == NULL || name == NULL || alias == NULL)
-- return;
--
-- user = (NMUser *) gc->proto_data;
-- if (user && (dn = nm_lookup_dn(user, name))) {
--
-- /* Alias all of instances of the contact */
-- contacts = nm_find_contacts(user, dn);
-- for (cnode = contacts; cnode != NULL; cnode = cnode->next) {
-- contact = (NMContact *) cnode->data;
-- if (contact) {
-- PurpleGroup *group = NULL;
-- PurpleBuddy *buddy;
-- NMFolder *folder;
--
-- /* Alias the Purple buddy? */
-- folder = nm_find_folder_by_id(user,
-- nm_contact_get_parent_id(contact));
-- if (folder) {
-- fname = nm_folder_get_name(folder);
-- if (*fname == '\0') {
-- fname = NM_ROOT_FOLDER_NAME;
-- }
-- group = purple_find_group(fname);
-- }
--
-- if (group) {
-- const char *balias;
-- buddy = purple_find_buddy_in_group(user->client_data,
-- name, group);
-- balias = buddy ? purple_buddy_get_local_buddy_alias(buddy) : NULL;
-- if (balias && strcmp(balias, alias))
-- purple_blist_alias_buddy(buddy, alias);
-- }
--
-- /* Tell the server to alias the contact */
-- rc = nm_send_rename_contact(user, contact, alias,
-- _rename_contact_resp_cb, NULL);
-- _check_for_disconnect(user, rc);
-- }
-- }
-- if (contacts)
-- g_list_free(contacts);
-- }
--}
--
--static void
--novell_group_buddy(PurpleConnection * gc,
-- const char *name, const char *old_group_name,
-- const char *new_group_name)
--{
-- NMFolder *old_folder;
-- NMFolder *new_folder;
-- NMContact *contact;
-- NMUser *user;
-- const char *dn;
-- NMERR_T rc = NM_OK;
--
-- if (gc == NULL || name == NULL ||
-- old_group_name == NULL || new_group_name == NULL)
-- return;
--
-- user = (NMUser *) gc->proto_data;
-- if (user && (dn = nm_lookup_dn(user, name))) {
--
-- /* Find the old folder */
-- if (strcmp(old_group_name, NM_ROOT_FOLDER_NAME) == 0) {
-- old_folder = nm_get_root_folder(user);
-- if (nm_folder_find_contact(old_folder, dn) == NULL)
-- old_folder = nm_find_folder(user, old_group_name);
-- } else {
-- old_folder = nm_find_folder(user, old_group_name);
-- }
--
-- if (old_folder && (contact = nm_folder_find_contact(old_folder, dn))) {
--
-- /* Find the new folder */
-- new_folder = nm_find_folder(user, new_group_name);
-- if (new_folder == NULL) {
-- if (strcmp(new_group_name, NM_ROOT_FOLDER_NAME) == 0)
-- new_folder = nm_get_root_folder(user);
-- }
--
-- if (new_folder) {
--
-- /* Tell the server to move the contact to the new folder */
-- rc = nm_send_move_contact(user, contact, new_folder,
-- _move_contact_resp_cb, NULL);
--
-- } else {
--
-- nm_contact_add_ref(contact);
--
-- /* Remove the old contact first */
-- nm_send_remove_contact(user, old_folder, contact,
-- _remove_contact_resp_cb, NULL);
--
-- /* New folder does not exist yet, so create it */
-- rc = nm_send_create_folder(user, new_group_name,
-- _create_folder_resp_move_contact,
-- contact);
-- }
--
-- _check_for_disconnect(user, rc);
-- }
-- }
--}
--
--static void
--novell_rename_group(PurpleConnection * gc, const char *old_name,
-- PurpleGroup *group, GList *moved_buddies)
--{
-- NMERR_T rc = NM_OK;
-- NMFolder *folder;
-- NMUser *user;
--
-- if (gc == NULL || old_name == NULL || group == NULL || moved_buddies == NULL) {
-- return;
-- }
--
-- user = gc->proto_data;
-- if (user) {
-- const char *gname = purple_group_get_name(group);
-- /* Does new folder exist already? */
-- if (nm_find_folder(user, gname)) {
-- /* purple_blist_rename_group() adds the buddies
-- * to the new group and removes the old group...
-- * so there is nothing more to do here.
-- */
-- return;
-- }
--
-- if (strcmp(old_name, NM_ROOT_FOLDER_NAME) == 0) {
-- /* Can't rename the root folder ... need to revisit this */
-- return;
-- }
--
-- folder = nm_find_folder(user, old_name);
-- if (folder) {
-- rc = nm_send_rename_folder(user, folder, gname,
-- _rename_folder_resp_cb, NULL);
-- _check_for_disconnect(user, rc);
-- }
-- }
--}
--
--static const char *
--novell_list_icon(PurpleAccount * account, PurpleBuddy * buddy)
--{
-- return "novell";
--}
--
--static void
--novell_tooltip_text(PurpleBuddy * buddy, PurpleNotifyUserInfo * user_info, gboolean full)
--{
-- NMUserRecord *user_record = NULL;
-- PurpleConnection *gc;
-- NMUser *user;
-- int status = 0;
-- const char *status_str = NULL;
-- const char *text = NULL;
--
-- if (buddy == NULL)
-- return;
--
-- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-- if (gc == NULL || (user = gc->proto_data) == NULL)
-- return;
--
-- if (PURPLE_BUDDY_IS_ONLINE(buddy)) {
-- user_record = nm_find_user_record(user, purple_buddy_get_name(buddy));
-- if (user_record) {
-- status = nm_user_record_get_status(user_record);
-- text = nm_user_record_get_status_text(user_record);
-- /* No custom text, so default it ... */
-- switch (status) {
-- case NM_STATUS_AVAILABLE:
-- status_str = _("Available");
-- break;
-- case NM_STATUS_AWAY:
-- status_str = _("Away");
-- break;
-- case NM_STATUS_BUSY:
-- status_str = _("Busy");
-- break;
-- case NM_STATUS_AWAY_IDLE:
-- status_str = _("Idle");
-- break;
-- case NM_STATUS_OFFLINE:
-- status_str = _("Offline");
-- break;
-- default:
-- status_str = _("Unknown");
-- break;
-- }
--
-- purple_notify_user_info_add_pair(user_info, _("Status"), status_str);
--
-- if (text)
-- purple_notify_user_info_add_pair(user_info, _("Message"), text);
-- }
-- }
--}
--
--static void
--novell_set_idle(PurpleConnection * gc, int time)
--{
-- NMUser *user;
-- NMERR_T rc = NM_OK;
-- const char *id = NULL;
-- PurpleStatus *status = NULL;
--
-- if (gc == NULL)
-- return;
--
-- user = gc->proto_data;
-- if (user == NULL)
-- return;
--
-- status = purple_account_get_active_status(purple_connection_get_account(gc));
-- id = purple_status_get_id(status);
--
-- /* Only go idle if active status is available */
-- if (!strcmp(id, NOVELL_STATUS_TYPE_AVAILABLE)) {
-- if (time > 0) {
-- rc = nm_send_set_status(user, NM_STATUS_AWAY_IDLE, NULL, NULL, NULL, NULL);
-- } else {
-- rc = nm_send_set_status(user, NM_STATUS_AVAILABLE, NULL, NULL, NULL, NULL);
-- }
-- }
--
-- _check_for_disconnect(user, rc);
--}
--
--static void
--novell_get_info(PurpleConnection * gc, const char *name)
--{
-- NMUserRecord *user_record;
-- NMUser *user;
-- NMERR_T rc;
--
-- if (gc == NULL || name == NULL)
-- return;
--
-- user = (NMUser *) gc->proto_data;
-- if (user) {
--
-- user_record = nm_find_user_record(user, name);
-- if (user_record) {
-- _show_info(gc, user_record, g_strdup(name));
--
-- } else {
-- rc = nm_send_get_details(user, name,
-- _get_details_resp_show_info, g_strdup(name));
--
-- _check_for_disconnect(user, rc);
--
-- }
--
-- }
--}
--
--static char *
--novell_status_text(PurpleBuddy * buddy)
--{
-- const char *text = NULL;
-- const char *dn = NULL;
-- PurpleAccount *account;
--
-- account = buddy ? purple_buddy_get_account(buddy) : NULL;
-- if (buddy && account) {
-- PurpleConnection *gc = purple_account_get_connection(account);
--
-- if (gc && gc->proto_data) {
-- NMUser *user = gc->proto_data;
--
-- dn = nm_lookup_dn(user, purple_buddy_get_name(buddy));
-- if (dn) {
-- NMUserRecord *user_record = nm_find_user_record(user, dn);
--
-- if (user_record) {
-- text = nm_user_record_get_status_text(user_record);
-- if (text)
-- return g_strdup(text);
-- }
-- }
-- }
-- }
--
-- return NULL;
--}
--
--static GList *
--novell_status_types(PurpleAccount *account)
--{
-- GList *status_types = NULL;
-- PurpleStatusType *type;
--
-- g_return_val_if_fail(account != NULL, NULL);
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, NOVELL_STATUS_TYPE_AVAILABLE,
-- NULL, TRUE, TRUE, FALSE,
-- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- status_types = g_list_append(status_types, type);
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY, NOVELL_STATUS_TYPE_AWAY,
-- NULL, TRUE, TRUE, FALSE,
-- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- status_types = g_list_append(status_types, type);
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE, NOVELL_STATUS_TYPE_BUSY,
-- _("Busy"), TRUE, TRUE, FALSE,
-- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- status_types = g_list_append(status_types, type);
--
-- type = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE, NOVELL_STATUS_TYPE_APPEAR_OFFLINE,
-- NULL, TRUE, TRUE, FALSE);
-- status_types = g_list_append(status_types, type);
--
-- type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, NULL, NULL, TRUE, TRUE, FALSE);
-- status_types = g_list_append(status_types, type);
--
-- return status_types;
--}
--
--static void
--novell_set_status(PurpleAccount *account, PurpleStatus *status)
--{
-- PurpleConnection *gc;
-- gboolean connected;
-- PurplePresence *presence;
-- PurpleStatusType *type;
-- PurpleStatusPrimitive primitive;
-- NMUser *user;
-- NMSTATUS_T novellstatus = NM_STATUS_AVAILABLE;
-- NMERR_T rc = NM_OK;
-- const char *msg = NULL;
-- char *text = NULL;
--
-- connected = purple_account_is_connected(account);
-- presence = purple_status_get_presence(status);
-- type = purple_status_get_type(status);
-- primitive = purple_status_type_get_primitive(type);
--
-- /*
-- * We don't have any independent statuses, so we don't need to
-- * do anything when a status is deactivated (because another
-- * status is about to be activated).
-- */
-- if (!purple_status_is_active(status))
-- return;
--
-- if (!connected)
-- return;
--
-- gc = purple_account_get_connection(account);
-- user = gc->proto_data;
-- if (user == NULL)
-- return;
--
-- if (primitive == PURPLE_STATUS_AVAILABLE) {
-- novellstatus = NM_STATUS_AVAILABLE;
-- } else if (primitive == PURPLE_STATUS_AWAY) {
-- novellstatus = NM_STATUS_AWAY;
-- } else if (primitive == PURPLE_STATUS_UNAVAILABLE) {
-- novellstatus = NM_STATUS_BUSY;
-- } else if (primitive == PURPLE_STATUS_INVISIBLE) {
-- novellstatus = NM_STATUS_OFFLINE;
-- } else if (purple_presence_is_idle(presence)) {
-- novellstatus = NM_STATUS_AWAY_IDLE;
-- } else {
-- novellstatus = NM_STATUS_AVAILABLE;
-- }
--
-- if (primitive == PURPLE_STATUS_AWAY || primitive == PURPLE_STATUS_AVAILABLE ||
-- primitive == PURPLE_STATUS_UNAVAILABLE) {
-- msg = purple_status_get_attr_string(status, "message");
-- text = g_strdup(msg);
--
-- if (primitive == PURPLE_STATUS_AVAILABLE)
-- msg = NULL; /* no auto replies for online status */
--
-- /* Don't want newlines in status text */
-- purple_util_chrreplace(text, '\n', ' ');
-- }
--
-- rc = nm_send_set_status(user, novellstatus, text, msg, NULL, NULL);
-- _check_for_disconnect(user, rc);
--
-- if (text)
-- g_free(text);
--}
--
--static void
--novell_add_permit(PurpleConnection *gc, const char *who)
--{
-- NMUser *user;
-- NMERR_T rc = NM_OK;
-- const char *name = who;
--
-- if (gc == NULL || who == NULL)
-- return;
--
-- user = gc->proto_data;
-- if (user == NULL)
-- return;
--
-- /* Remove first -- we will add it back in when we get
-- * the okay from the server
-- */
-- purple_privacy_permit_remove(gc->account, who, TRUE);
--
-- if (nm_user_is_privacy_locked(user)) {
-- _show_privacy_locked_error(gc, user);
-- _sync_privacy_lists(user);
-- return;
-- }
--
-- /* Work around for problem with un-typed, dotted contexts */
-- if (strchr(who, '.')) {
-- const char *dn = nm_lookup_dn(user, who);
-- if (dn == NULL) {
-- rc = nm_send_get_details(user, who, _get_details_send_privacy_create,
-- (gpointer)TRUE);
-- _check_for_disconnect(user, rc);
-- return;
-- } else {
-- name = dn;
-- }
-- }
--
-- rc = nm_send_create_privacy_item(user, name, TRUE,
-- _create_privacy_item_permit_resp_cb,
-- g_strdup(who));
-- _check_for_disconnect(user, rc);
--}
--
--static void
--novell_add_deny(PurpleConnection *gc, const char *who)
--{
-- NMUser *user;
-- NMERR_T rc = NM_OK;
-- const char *name = who;
--
-- if (gc == NULL || who == NULL)
-- return;
--
-- user = gc->proto_data;
-- if (user == NULL)
-- return;
--
-- /* Remove first -- we will add it back in when we get
-- * the okay from the server
-- */
-- purple_privacy_deny_remove(gc->account, who, TRUE);
--
-- if (nm_user_is_privacy_locked(user)) {
-- _show_privacy_locked_error(gc, user);
-- _sync_privacy_lists(user);
-- return;
-- }
--
-- /* Work around for problem with un-typed, dotted contexts */
-- if (strchr(who, '.')) {
-- const char *dn = nm_lookup_dn(user, who);
-- if (dn == NULL) {
-- rc = nm_send_get_details(user, who, _get_details_send_privacy_create,
-- (gpointer)FALSE);
-- _check_for_disconnect(user, rc);
-- return;
-- } else {
-- name = dn;
-- }
-- }
--
-- rc = nm_send_create_privacy_item(user, name, FALSE,
-- _create_privacy_item_deny_resp_cb,
-- g_strdup(who));
-- _check_for_disconnect(user, rc);
--}
--
--static void
--novell_rem_permit(PurpleConnection *gc, const char *who)
--{
-- NMUser *user;
-- NMERR_T rc = NM_OK;
-- const char *dn = NULL;
--
-- if (gc == NULL || who == NULL)
-- return;
--
-- user = gc->proto_data;
-- if (user == NULL)
-- return;
--
-- if (nm_user_is_privacy_locked(user)) {
-- _show_privacy_locked_error(gc, user);
-- _sync_privacy_lists(user);
-- return;
-- }
--
-- dn = nm_lookup_dn(user, who);
-- if (dn == NULL)
-- dn = who;
--
-- rc = nm_send_remove_privacy_item(user, dn, TRUE,
-- _remove_privacy_item_resp_cb,
-- g_strdup(who));
-- _check_for_disconnect(user, rc);
--}
--
--static void
--novell_rem_deny(PurpleConnection *gc, const char *who)
--{
-- NMUser *user;
-- NMERR_T rc = NM_OK;
-- const char *dn = NULL;
--
-- if (gc == NULL || who == NULL)
-- return;
--
-- user = gc->proto_data;
-- if (user == NULL)
-- return;
--
-- if (nm_user_is_privacy_locked(user)) {
-- _show_privacy_locked_error(gc, user);
-- _sync_privacy_lists(user);
-- return;
-- }
--
-- dn = nm_lookup_dn(user, who);
-- if (dn == NULL)
-- dn = who;
--
-- rc = nm_send_remove_privacy_item(user, dn, FALSE,
-- _remove_privacy_item_resp_cb,
-- g_strdup(who));
-- _check_for_disconnect(user, rc);
--}
--
--static void
--novell_set_permit_deny(PurpleConnection *gc)
--{
-- NMERR_T rc = NM_OK;
-- const char *dn, *name = NULL;
-- NMUserRecord *user_record = NULL;
-- GSList *node = NULL, *copy = NULL;
-- NMUser *user;
-- int i, j, num_contacts, num_folders;
-- NMContact *contact;
-- NMFolder *folder = NULL;
--
-- if (gc == NULL)
-- return;
--
-- user = gc->proto_data;
-- if (user == NULL)
-- return;
--
-- if (user->privacy_synched == FALSE) {
-- _sync_privacy_lists(user);
-- user->privacy_synched = TRUE;
-- return;
-- }
--
-- if (nm_user_is_privacy_locked(user)) {
-- _show_privacy_locked_error(gc, user);
-- _sync_privacy_lists(user);
-- return;
-- }
--
-- switch (gc->account->perm_deny) {
--
-- case PURPLE_PRIVACY_ALLOW_ALL:
-- rc = nm_send_set_privacy_default(user, FALSE,
-- _set_privacy_default_resp_cb, NULL);
-- _check_for_disconnect(user, rc);
--
-- /* clear server side deny list */
-- if (rc == NM_OK) {
-- copy = g_slist_copy(user->deny_list);
-- for (node = copy; node && node->data; node = node->next) {
-- rc = nm_send_remove_privacy_item(user, (const char *)node->data,
-- FALSE, NULL, NULL);
-- if (_check_for_disconnect(user, rc))
-- break;
-- }
-- g_slist_free(copy);
-- g_slist_free(user->deny_list);
-- user->deny_list = NULL;
-- }
-- break;
--
-- case PURPLE_PRIVACY_DENY_ALL:
-- rc = nm_send_set_privacy_default(user, TRUE,
-- _set_privacy_default_resp_cb, NULL);
-- _check_for_disconnect(user, rc);
--
-- /* clear server side allow list */
-- if (rc == NM_OK) {
-- copy = g_slist_copy(user->allow_list);
-- for (node = copy; node && node->data; node = node->next) {
-- rc = nm_send_remove_privacy_item(user, (const char *)node->data,
-- TRUE, NULL, NULL);
-- if (_check_for_disconnect(user, rc))
-- break;
-- }
-- g_slist_free(copy);
-- g_slist_free(user->allow_list);
-- user->allow_list = NULL;
-- }
-- break;
--
-- case PURPLE_PRIVACY_ALLOW_USERS:
--
-- rc = nm_send_set_privacy_default(user, TRUE,
-- _set_privacy_default_resp_cb, NULL);
-- _check_for_disconnect(user, rc);
--
-- /* sync allow lists */
-- if (rc == NM_OK) {
--
-- for (node = user->allow_list; node; node = node->next) {
-- user_record = nm_find_user_record(user, (char *)node->data);
-- if (user_record) {
-- name = nm_user_record_get_display_id(user_record);
--
-- if (!g_slist_find_custom(gc->account->permit,
-- name, (GCompareFunc)purple_utf8_strcasecmp)) {
-- purple_privacy_permit_add(gc->account, name , TRUE);
-- }
-- }
-- }
--
-- for (node = gc->account->permit; node; node = node->next) {
-- name = NULL;
-- dn = nm_lookup_dn(user, (char *)node->data);
-- if (dn) {
-- user_record = nm_find_user_record(user, dn);
-- name = nm_user_record_get_display_id(user_record);
--
-- if (!g_slist_find_custom(user->allow_list,
-- dn, (GCompareFunc)purple_utf8_strcasecmp)) {
-- rc = nm_send_create_privacy_item(user, dn, TRUE,
-- _create_privacy_item_deny_resp_cb,
-- g_strdup(dn));
-- }
-- } else {
-- purple_privacy_permit_remove(gc->account, (char *)node->data, TRUE);
-- }
-- }
-- }
-- break;
--
-- case PURPLE_PRIVACY_DENY_USERS:
--
-- /* set to default allow */
-- rc = nm_send_set_privacy_default(user, FALSE,
-- _set_privacy_default_resp_cb, NULL);
-- _check_for_disconnect(user, rc);
--
-- /* sync deny lists */
-- if (rc == NM_OK) {
--
-- for (node = user->deny_list; node; node = node->next) {
-- user_record = nm_find_user_record(user, (char *)node->data);
-- if (user_record) {
-- name = nm_user_record_get_display_id(user_record);
--
-- if (!g_slist_find_custom(gc->account->deny,
-- name, (GCompareFunc)purple_utf8_strcasecmp)) {
-- purple_privacy_deny_add(gc->account, name , TRUE);
-- }
-- }
-- }
--
-- for (node = gc->account->deny; node; node = node->next) {
--
-- name = NULL;
-- dn = nm_lookup_dn(user, (char *)node->data);
-- if (dn) {
-- user_record = nm_find_user_record(user, dn);
-- name = nm_user_record_get_display_id(user_record);
--
-- if (!g_slist_find_custom(user->deny_list,
-- dn, (GCompareFunc)purple_utf8_strcasecmp)) {
-- rc = nm_send_create_privacy_item(user, dn, FALSE,
-- _create_privacy_item_deny_resp_cb,
-- g_strdup(name));
-- }
-- } else {
-- purple_privacy_deny_remove(gc->account, (char *)node->data, TRUE);
-- }
-- }
--
-- }
-- break;
--
-- case PURPLE_PRIVACY_ALLOW_BUDDYLIST:
--
-- /* remove users from allow list that are not in buddy list */
-- copy = g_slist_copy(user->allow_list);
-- for (node = copy; node && node->data; node = node->next) {
-- if (!nm_find_contacts(user, node->data)) {
-- rc = nm_send_remove_privacy_item(user, (const char *)node->data,
-- TRUE, NULL, NULL);
-- if (_check_for_disconnect(user, rc))
-- return;
-- }
-- }
-- g_slist_free(copy);
--
-- /* add all buddies to allow list */
-- num_contacts = nm_folder_get_contact_count(user->root_folder);
-- for (i = 0; i < num_contacts; i++) {
-- contact = nm_folder_get_contact(user->root_folder, i);
-- dn = nm_contact_get_dn(contact);
-- if (dn && !g_slist_find_custom(user->allow_list,
-- dn, (GCompareFunc)purple_utf8_strcasecmp))
-- {
-- rc = nm_send_create_privacy_item(user, dn, TRUE,
-- _create_privacy_item_deny_resp_cb,
-- g_strdup(dn));
-- if (_check_for_disconnect(user, rc))
-- return;
-- }
--
-- }
--
-- num_folders = nm_folder_get_subfolder_count(user->root_folder);
-- for (i = 0; i < num_folders; i++) {
-- folder = nm_folder_get_subfolder(user->root_folder, i);
-- num_contacts = nm_folder_get_contact_count(folder);
-- for (j = 0; j < num_contacts; j++) {
-- contact = nm_folder_get_contact(folder, j);
-- dn = nm_contact_get_dn(contact);
-- if (dn && !g_slist_find_custom(user->allow_list,
-- dn, (GCompareFunc)purple_utf8_strcasecmp))
-- {
-- rc = nm_send_create_privacy_item(user, dn, TRUE,
-- _create_privacy_item_deny_resp_cb,
-- g_strdup(dn));
-- if (_check_for_disconnect(user, rc))
-- return;
-- }
-- }
-- }
--
-- /* set to default deny */
-- rc = nm_send_set_privacy_default(user, TRUE,
-- _set_privacy_default_resp_cb, NULL);
-- if (_check_for_disconnect(user, rc))
-- break;
--
-- break;
-- }
--}
--
--static GList *
--novell_blist_node_menu(PurpleBlistNode *node)
--{
-- GList *list = NULL;
-- PurpleMenuAction *act;
--
-- if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
-- act = purple_menu_action_new(_("Initiate _Chat"),
-- PURPLE_CALLBACK(_initiate_conference_cb),
-- NULL, NULL);
-- list = g_list_append(list, act);
-- }
--
-- return list;
--}
--
--static void
--novell_keepalive(PurpleConnection *gc)
--{
-- NMUser *user;
-- NMERR_T rc = NM_OK;
--
-- if (gc == NULL)
-- return;
--
-- user = gc->proto_data;
-- if (user == NULL)
-- return;
--
-- rc = nm_send_keepalive(user, NULL, NULL);
-- _check_for_disconnect(user, rc);
--}
--
--static PurplePluginProtocolInfo prpl_info = {
-- 0,
-- NULL, /* user_splits */
-- NULL, /* protocol_options */
-- NO_BUDDY_ICONS, /* icon_spec */
-- novell_list_icon, /* list_icon */
-- NULL, /* list_emblems */
-- novell_status_text, /* status_text */
-- novell_tooltip_text, /* tooltip_text */
-- novell_status_types, /* status_types */
-- novell_blist_node_menu, /* blist_node_menu */
-- NULL, /* chat_info */
-- NULL, /* chat_info_defaults */
-- novell_login, /* login */
-- novell_close, /* close */
-- novell_send_im, /* send_im */
-- NULL, /* set_info */
-- novell_send_typing, /* send_typing */
-- novell_get_info, /* get_info */
-- novell_set_status, /* set_status */
-- novell_set_idle, /* set_idle */
-- NULL, /* change_passwd */
-- novell_add_buddy, /* add_buddy */
-- NULL, /* add_buddies */
-- novell_remove_buddy, /* remove_buddy */
-- NULL, /* remove_buddies */
-- novell_add_permit, /* add_permit */
-- novell_add_deny, /* add_deny */
-- novell_rem_permit, /* rem_permit */
-- novell_rem_deny, /* rem_deny */
-- novell_set_permit_deny, /* set_permit_deny */
-- NULL, /* join_chat */
-- NULL, /* reject_chat */
-- NULL, /* get_chat_name */
-- novell_chat_invite, /* chat_invite */
-- novell_chat_leave, /* chat_leave */
-- NULL, /* chat_whisper */
-- novell_chat_send, /* chat_send */
-- novell_keepalive, /* keepalive */
-- NULL, /* register_user */
-- NULL, /* get_cb_info */
-- NULL, /* get_cb_away */
-- novell_alias_buddy, /* alias_buddy */
-- novell_group_buddy, /* group_buddy */
-- novell_rename_group, /* rename_group */
-- NULL, /* buddy_free */
-- novell_convo_closed, /* convo_closed */
-- purple_normalize_nocase, /* normalize */
-- NULL, /* set_buddy_icon */
-- novell_remove_group, /* remove_group */
-- NULL, /* get_cb_real_name */
-- NULL, /* set_chat_topic */
-- NULL, /* find_blist_chat */
-- NULL, /* roomlist_get_list */
-- NULL, /* roomlist_cancel */
-- NULL, /* roomlist_expand_category */
-- NULL, /* can_receive_file */
-- NULL, /* send_file */
-- NULL, /* new_xfer */
-- NULL, /* offline_message */
-- NULL, /* 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-novell", /**< id */
-- "GroupWise", /**< name */
-- DISPLAY_VERSION, /**< version */
-- /** summary */
-- N_("Novell GroupWise Messenger Protocol Plugin"),
-- /** description */
-- N_("Novell GroupWise Messenger Protocol Plugin"),
-- NULL, /**< author */
-- PURPLE_WEBSITE, /**< homepage */
--
-- NULL, /**< load */
-- NULL, /**< unload */
-- NULL, /**< destroy */
--
-- NULL, /**< ui_info */
-- &prpl_info, /**< extra_info */
-- NULL,
-- NULL,
--
-- /* padding */
-- NULL,
-- NULL,
-- NULL,
-- NULL
--};
--
--static void
--init_plugin(PurplePlugin * plugin)
--{
-- PurpleAccountOption *option;
--
-- option = purple_account_option_string_new(_("Server address"), "server", NULL);
-- prpl_info.protocol_options =
-- g_list_append(prpl_info.protocol_options, option);
--
-- option = purple_account_option_int_new(_("Server port"), "port", DEFAULT_PORT);
-- prpl_info.protocol_options =
-- g_list_append(prpl_info.protocol_options, option);
--
-- my_protocol = plugin;
--}
--
--PURPLE_INIT_PLUGIN(novell, init_plugin, info);
-diff -Nur pidgin-2.10.7/libpurple/protocols/null/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/null/Makefile.in
---- pidgin-2.10.7/libpurple/protocols/null/Makefile.in 2013-02-11 07:17:21.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/null/Makefile.in 2013-08-16 23:51:32.453142958 -0300
-@@ -184,8 +184,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -247,8 +245,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/libpurple/protocols/null/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/null/Makefile.mingw
---- pidgin-2.10.7/libpurple/protocols/null/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/null/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,79 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of libnull
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = libnull
--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)
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = nullprpl.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lintl \
-- -lws2_32 \
-- -lpurple
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install install_real clean
--
--all: $(TARGET).dll
--
--install_real: all $(DLL_INSTALL_DIR) $(PURPLE_INSTALL_DIR)
-- cp $(TARGET).dll $(DLL_INSTALL_DIR)
--
--install: all
--
--$(OBJECTS): $(PURPLE_CONFIG_H)
--
--$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -f $(OBJECTS)
-- rm -f $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/authorization.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/authorization.c
---- pidgin-2.10.7/libpurple/protocols/oscar/authorization.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/authorization.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,131 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Everything related to OSCAR authorization requests.
-- */
--
--#include "oscar.h"
--#include "request.h"
--
--/* When you ask other people for authorization */
--void
--oscar_auth_sendrequest(PurpleConnection *gc, const char *bname, const char *msg)
--{
-- OscarData *od;
-- PurpleAccount *account;
-- PurpleBuddy *buddy;
-- PurpleGroup *group;
-- const char *gname;
--
-- od = purple_connection_get_protocol_data(gc);
-- account = purple_connection_get_account(gc);
-- buddy = purple_find_buddy(account, bname);
-- if (buddy != NULL)
-- group = purple_buddy_get_group(buddy);
-- else
-- group = NULL;
--
-- if (group != NULL)
-- {
-- gname = purple_group_get_name(group);
-- purple_debug_info("oscar", "ssi: adding buddy %s to group %s\n",
-- bname, gname);
-- aim_ssi_sendauthrequest(od, bname, msg ? msg : _("Please authorize me so I can add you to my buddy list."));
-- if (!aim_ssi_itemlist_finditem(od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY))
-- {
-- aim_ssi_addbuddy(od, bname, gname, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, TRUE);
--
-- /* Mobile users should always be online */
-- if (bname[0] == '+') {
-- purple_prpl_got_user_status(account,
-- purple_buddy_get_name(buddy),
-- OSCAR_STATUS_ID_AVAILABLE, NULL);
-- purple_prpl_got_user_status(account,
-- purple_buddy_get_name(buddy),
-- OSCAR_STATUS_ID_MOBILE, NULL);
-- }
-- }
-- }
--}
--
--static void
--oscar_auth_grant(gpointer cbdata)
--{
-- struct name_data *data = cbdata;
-- PurpleConnection *gc = data->gc;
-- OscarData *od = purple_connection_get_protocol_data(gc);
--
-- aim_ssi_sendauthreply(od, data->name, 0x01, NULL);
--
-- oscar_free_name_data(data);
--}
--
--static void
--oscar_auth_dontgrant(struct name_data *data, char *msg)
--{
-- PurpleConnection *gc = data->gc;
-- OscarData *od = purple_connection_get_protocol_data(gc);
--
-- aim_ssi_sendauthreply(od, data->name, 0x00, msg ? msg : _("No reason given."));
--
-- oscar_free_name_data(data);
--}
--
--static void
--oscar_auth_dontgrant_msgprompt(gpointer cbdata)
--{
-- struct name_data *data = cbdata;
-- purple_request_input(data->gc, NULL, _("Authorization Denied Message:"),
-- NULL, _("No reason given."), TRUE, FALSE, NULL,
-- _("_OK"), G_CALLBACK(oscar_auth_dontgrant),
-- _("_Cancel"), G_CALLBACK(oscar_free_name_data),
-- purple_connection_get_account(data->gc), data->name, NULL,
-- data);
--}
--
--void
--oscar_auth_sendrequest_menu(PurpleBlistNode *node, gpointer ignored)
--{
-- PurpleBuddy *buddy;
-- PurpleConnection *gc;
--
-- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
--
-- buddy = (PurpleBuddy *) node;
-- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-- oscar_auth_sendrequest(gc, purple_buddy_get_name(buddy), NULL);
--}
--
--/* When other people ask you for authorization */
--void
--oscar_auth_recvrequest(PurpleConnection *gc, gchar *name, gchar *nick, gchar *reason)
--{
-- PurpleAccount* account = purple_connection_get_account(gc);
-- struct name_data *data = g_new(struct name_data, 1);
--
-- data->gc = gc;
-- data->name = name;
-- data->nick = nick;
--
-- purple_account_request_authorization(account, data->name, NULL, data->nick,
-- reason, purple_find_buddy(account, data->name) != NULL,
-- oscar_auth_grant, oscar_auth_dontgrant_msgprompt, data);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/AUTHORS pidgin-2.10.7-nonprism/libpurple/protocols/oscar/AUTHORS
---- pidgin-2.10.7/libpurple/protocols/oscar/AUTHORS 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/AUTHORS 1969-12-31 21:00:00.000000000 -0300
-@@ -1,49 +0,0 @@
--
--N: ComBOTS Product GmbH (htfv)
--T: 2007
--E: foss@combots.com
--
--N: Jonathan Clark
--T: 2005-2006
--E: ardentlygnarley a.t users d.o.t sourceforge d.o.t net
--
--N: Mark Doliner
--T: 2001-2006
--H: markdoliner
--E: thekingant a.t users d.o.t sourceforge d.o.t net
--W: http://kingant.net/
--
--N: Adam Fritzler
--T: 1998-2001
--H: mid
--E: mid a.t auk d.o.t cx
--W: http://www.auk.cx/~mid,http://www.auk.cx/faim
--D: Wrote most of the wap of crap that you see before you.
--
--N: Josh Myer
--T: 1998-2001
--E: josh a.t joshisanerd d.o.t com
--D: OFT/ODC (not quite finished yet..), random little things, Munger-At-Large, compile-time warnings.
--
--N: Daniel M. Pomerantz
--H: dmprantz
--D: Made initial versions cross platform
--
--N: Daniel Reed
--T: 1998-2001
--H: n, linuxkitty
--E: n a.t ml d.o.t org
--W: http://users.n.ml.org/n/
--D: Fixed aim_snac.c
--
--N: Eric Warmenhoven
--T: 1998-2001
--E: warmenhoven a.t linux d.o.t com
--D: Some OFT info, initial author of the libpurple-side of the oscar protocol plugin
--
--N: Brock Wilcox
--T: 1998-2001
--H: awwaiid
--E: awwaiid a.t auk d.o.t cx
--D: Figured out original password roasting
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/bstream.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/bstream.c
---- pidgin-2.10.7/libpurple/protocols/oscar/bstream.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/bstream.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,288 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * This file contains all functions needed to use bstreams.
-- */
--
--#include "oscar.h"
--
--int byte_stream_new(ByteStream *bs, size_t len)
--{
-- if (bs == NULL)
-- return -1;
--
-- return byte_stream_init(bs, g_malloc(len), len);
--}
--
--int byte_stream_init(ByteStream *bs, guint8 *data, size_t len)
--{
-- if (bs == NULL)
-- return -1;
--
-- bs->data = data;
-- bs->len = len;
-- bs->offset = 0;
--
-- return 0;
--}
--
--void byte_stream_destroy(ByteStream *bs)
--{
-- g_free(bs->data);
--}
--
--int byte_stream_bytes_left(ByteStream *bs)
--{
-- return bs->len - bs->offset;
--}
--
--int byte_stream_curpos(ByteStream *bs)
--{
-- return bs->offset;
--}
--
--int byte_stream_setpos(ByteStream *bs, size_t off)
--{
-- g_return_val_if_fail(off <= bs->len, -1);
--
-- bs->offset = off;
-- return off;
--}
--
--void byte_stream_rewind(ByteStream *bs)
--{
-- byte_stream_setpos(bs, 0);
--}
--
--/*
-- * N can be negative, which can be used for going backwards
-- * in a bstream.
-- */
--int byte_stream_advance(ByteStream *bs, int n)
--{
-- g_return_val_if_fail(byte_stream_curpos(bs) + n >= 0, 0);
-- g_return_val_if_fail(n <= byte_stream_bytes_left(bs), 0);
--
-- bs->offset += n;
-- return n;
--}
--
--guint8 byte_stream_get8(ByteStream *bs)
--{
-- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 1, 0);
--
-- bs->offset++;
-- return aimutil_get8(bs->data + bs->offset - 1);
--}
--
--guint16 byte_stream_get16(ByteStream *bs)
--{
-- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 2, 0);
--
-- bs->offset += 2;
-- return aimutil_get16(bs->data + bs->offset - 2);
--}
--
--guint32 byte_stream_get32(ByteStream *bs)
--{
-- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 4, 0);
--
-- bs->offset += 4;
-- return aimutil_get32(bs->data + bs->offset - 4);
--}
--
--guint8 byte_stream_getle8(ByteStream *bs)
--{
-- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 1, 0);
--
-- bs->offset++;
-- return aimutil_getle8(bs->data + bs->offset - 1);
--}
--
--guint16 byte_stream_getle16(ByteStream *bs)
--{
-- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 2, 0);
--
-- bs->offset += 2;
-- return aimutil_getle16(bs->data + bs->offset - 2);
--}
--
--guint32 byte_stream_getle32(ByteStream *bs)
--{
-- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 4, 0);
--
-- bs->offset += 4;
-- return aimutil_getle32(bs->data + bs->offset - 4);
--}
--
--static void byte_stream_getrawbuf_nocheck(ByteStream *bs, guint8 *buf, size_t len)
--{
-- memcpy(buf, bs->data + bs->offset, len);
-- bs->offset += len;
--}
--
--int byte_stream_getrawbuf(ByteStream *bs, guint8 *buf, size_t len)
--{
-- g_return_val_if_fail(byte_stream_bytes_left(bs) >= len, 0);
--
-- byte_stream_getrawbuf_nocheck(bs, buf, len);
-- return len;
--}
--
--guint8 *byte_stream_getraw(ByteStream *bs, size_t len)
--{
-- guint8 *ob;
--
-- g_return_val_if_fail(byte_stream_bytes_left(bs) >= len, NULL);
--
-- ob = g_malloc(len);
-- byte_stream_getrawbuf_nocheck(bs, ob, len);
-- return ob;
--}
--
--char *byte_stream_getstr(ByteStream *bs, size_t len)
--{
-- char *ob;
--
-- g_return_val_if_fail(byte_stream_bytes_left(bs) >= len, NULL);
--
-- ob = g_malloc(len + 1);
-- byte_stream_getrawbuf_nocheck(bs, (guint8 *)ob, len);
-- ob[len] = '\0';
-- return ob;
--}
--
--int byte_stream_put8(ByteStream *bs, guint8 v)
--{
-- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 1, 0);
--
-- bs->offset += aimutil_put8(bs->data + bs->offset, v);
-- return 1;
--}
--
--int byte_stream_put16(ByteStream *bs, guint16 v)
--{
-- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 2, 0);
--
-- bs->offset += aimutil_put16(bs->data + bs->offset, v);
-- return 2;
--}
--
--int byte_stream_put32(ByteStream *bs, guint32 v)
--{
-- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 4, 0);
--
-- bs->offset += aimutil_put32(bs->data + bs->offset, v);
-- return 1;
--}
--
--int byte_stream_putle8(ByteStream *bs, guint8 v)
--{
-- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 1, 0);
--
-- bs->offset += aimutil_putle8(bs->data + bs->offset, v);
-- return 1;
--}
--
--int byte_stream_putle16(ByteStream *bs, guint16 v)
--{
-- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 2, 0);
--
-- bs->offset += aimutil_putle16(bs->data + bs->offset, v);
-- return 2;
--}
--
--int byte_stream_putle32(ByteStream *bs, guint32 v)
--{
-- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 4, 0);
--
-- bs->offset += aimutil_putle32(bs->data + bs->offset, v);
-- return 1;
--}
--
--
--int byte_stream_putraw(ByteStream *bs, const guint8 *v, size_t len)
--{
-- g_return_val_if_fail(byte_stream_bytes_left(bs) >= len, 0);
--
-- memcpy(bs->data + bs->offset, v, len);
-- bs->offset += len;
-- return len;
--}
--
--int byte_stream_putstr(ByteStream *bs, const char *str)
--{
-- return byte_stream_putraw(bs, (guint8 *)str, strlen(str));
--}
--
--int byte_stream_putbs(ByteStream *bs, ByteStream *srcbs, size_t len)
--{
-- g_return_val_if_fail(byte_stream_bytes_left(srcbs) >= len, 0);
-- g_return_val_if_fail(byte_stream_bytes_left(bs) >= len, 0);
--
-- memcpy(bs->data + bs->offset, srcbs->data + srcbs->offset, len);
-- bs->offset += len;
-- srcbs->offset += len;
-- return len;
--}
--
--int byte_stream_putuid(ByteStream *bs, OscarData *od)
--{
-- PurpleAccount *account;
--
-- account = purple_connection_get_account(od->gc);
--
-- return byte_stream_putle32(bs, atoi(purple_account_get_username(account)));
--}
--
--void byte_stream_put_bart_asset(ByteStream *bs, guint16 type, ByteStream *data)
--{
-- byte_stream_put16(bs, type);
--
-- if (data != NULL && data->len > 0) {
-- /* Flags. 0x04 means "this asset has data attached to it" */
-- byte_stream_put8(bs, 0x04); /* Flags */
-- byte_stream_put8(bs, data->len); /* Length */
-- byte_stream_rewind(data);
-- byte_stream_putbs(bs, data, data->len); /* Data */
-- } else {
-- byte_stream_put8(bs, 0x00); /* No flags */
-- byte_stream_put8(bs, 0x00); /* Length */
-- /* No data */
-- }
--}
--
--void byte_stream_put_bart_asset_str(ByteStream *bs, guint16 type, const char *datastr)
--{
-- ByteStream data;
-- size_t len = datastr != NULL ? strlen(datastr) : 0;
--
-- if (len > 0) {
-- byte_stream_new(&data, 2 + len + 2);
-- byte_stream_put16(&data, len); /* Length */
-- byte_stream_putstr(&data, datastr); /* String */
-- byte_stream_put16(&data, 0x0000); /* Unknown */
-- byte_stream_put_bart_asset(bs, type, &data);
-- byte_stream_destroy(&data);
-- } else {
-- byte_stream_put_bart_asset(bs, type, NULL);
-- }
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/clientlogin.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/clientlogin.c
---- pidgin-2.10.7/libpurple/protocols/oscar/clientlogin.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/clientlogin.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,654 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/**
-- * This file implements AIM's clientLogin procedure for authenticating
-- * users. This replaces the older MD5-based and XOR-based
-- * authentication methods that use SNAC family 0x0017.
-- *
-- * This doesn't use SNACs or FLAPs at all. It makes http and https
-- * POSTs to AOL to validate the user based on the password they
-- * provided to us. Upon successful authentication we request a
-- * connection to the BOS server by calling startOSCARsession. The
-- * AOL server gives us the hostname and port number to use, as well
-- * as the cookie to use to authenticate to the BOS server. And then
-- * everything else is the same as with BUCP.
-- *
-- * For details, see:
-- * http://dev.aol.com/aim/oscar/#AUTH
-- * http://dev.aol.com/authentication_for_clients
-- */
--
--#include "oscar.h"
--#include "oscarcommon.h"
--
--#include "cipher.h"
--#include "core.h"
--
--#define AIM_LOGIN_HOST "api.screenname.aol.com"
--#define ICQ_LOGIN_HOST "api.login.icq.net"
--
--#define AIM_API_HOST "api.oscar.aol.com"
--#define ICQ_API_HOST "api.icq.net"
--
--#define CLIENT_LOGIN_PAGE "/auth/clientLogin"
--#define START_OSCAR_SESSION_PAGE "/aim/startOSCARSession"
--
--#define HTTPS_FORMAT_URL(host, page) "https://" host page
--
--static const gchar *client_login_urls[] = {
-- HTTPS_FORMAT_URL(AIM_LOGIN_HOST, CLIENT_LOGIN_PAGE),
-- HTTPS_FORMAT_URL(ICQ_LOGIN_HOST, CLIENT_LOGIN_PAGE),
--};
--
--static const gchar *start_oscar_session_urls[] = {
-- HTTPS_FORMAT_URL(AIM_API_HOST, START_OSCAR_SESSION_PAGE),
-- HTTPS_FORMAT_URL(ICQ_API_HOST, START_OSCAR_SESSION_PAGE),
--};
--
--static const gchar *get_client_login_url(OscarData *od)
--{
-- return client_login_urls[od->icq ? 1 : 0];
--}
--
--static const gchar *get_start_oscar_session_url(OscarData *od)
--{
-- return start_oscar_session_urls[od->icq ? 1 : 0];
--}
--
--/*
-- * Using clientLogin requires a developer ID. This key is for libpurple.
-- * It is the default key for all libpurple-based clients. AOL encourages
-- * UIs (especially ones with lots of users) to override this with their
-- * own key. This key is owned by the AIM account "markdoliner"
-- *
-- * Keys can be managed at http://developer.aim.com/manageKeys.jsp
-- */
--#define DEFAULT_CLIENT_KEY "ma15d7JTxbmVG-RP"
--
--static const char *get_client_key(OscarData *od)
--{
-- return oscar_get_ui_info_string(
-- od->icq ? "prpl-icq-clientkey" : "prpl-aim-clientkey",
-- DEFAULT_CLIENT_KEY);
--}
--
--static gchar *generate_error_message(xmlnode *resp, const char *url)
--{
-- xmlnode *text;
-- xmlnode *status_code_node;
-- gchar *status_code;
-- gboolean have_error_code = TRUE;
-- gchar *err = NULL;
-- gchar *details = NULL;
--
-- status_code_node = xmlnode_get_child(resp, "statusCode");
-- if (status_code_node) {
-- /* We can get 200 OK here if the server omitted something we think it shouldn't have (see #12783).
-- * No point in showing the "Ok" string to the user.
-- */
-- if ((status_code = xmlnode_get_data_unescaped(status_code_node)) && strcmp(status_code, "200") == 0) {
-- have_error_code = FALSE;
-- }
-- }
-- if (have_error_code && resp && (text = xmlnode_get_child(resp, "statusText"))) {
-- details = xmlnode_get_data(text);
-- }
--
-- if (details && *details) {
-- err = g_strdup_printf(_("Received unexpected response from %s: %s"), url, details);
-- } else {
-- err = g_strdup_printf(_("Received unexpected response from %s"), url);
-- }
--
-- g_free(details);
-- return err;
--}
--
--/**
-- * @return A null-terminated base64 encoded version of the HMAC
-- * calculated using the given key and data.
-- */
--static gchar *hmac_sha256(const char *key, const char *message)
--{
-- PurpleCipherContext *context;
-- guchar digest[32];
--
-- context = purple_cipher_context_new_by_name("hmac", NULL);
-- purple_cipher_context_set_option(context, "hash", "sha256");
-- purple_cipher_context_set_key(context, (guchar *)key);
-- purple_cipher_context_append(context, (guchar *)message, strlen(message));
-- purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
-- purple_cipher_context_destroy(context);
--
-- return purple_base64_encode(digest, sizeof(digest));
--}
--
--/**
-- * @return A base-64 encoded HMAC-SHA256 signature created using the
-- * technique documented at
-- * http://dev.aol.com/authentication_for_clients#signing
-- */
--static gchar *generate_signature(const char *method, const char *url, const char *parameters, const char *session_key)
--{
-- char *encoded_url, *signature_base_string, *signature;
-- const char *encoded_parameters;
--
-- encoded_url = g_strdup(purple_url_encode(url));
-- encoded_parameters = purple_url_encode(parameters);
-- signature_base_string = g_strdup_printf("%s&%s&%s",
-- method, encoded_url, encoded_parameters);
-- g_free(encoded_url);
--
-- signature = hmac_sha256(session_key, signature_base_string);
-- g_free(signature_base_string);
--
-- return signature;
--}
--
--static gboolean parse_start_oscar_session_response(PurpleConnection *gc, const gchar *response, gsize response_len, char **host, unsigned short *port, char **cookie, char **tls_certname)
--{
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- xmlnode *response_node, *tmp_node, *data_node;
-- xmlnode *host_node = NULL, *port_node = NULL, *cookie_node = NULL, *tls_node = NULL;
-- char *tmp;
-- guint code;
-- const gchar *encryption_type = purple_account_get_string(purple_connection_get_account(gc), "encryption", OSCAR_DEFAULT_ENCRYPTION);
--
-- /* Parse the response as XML */
-- response_node = xmlnode_from_str(response, response_len);
-- if (response_node == NULL)
-- {
-- char *msg;
-- purple_debug_error("oscar", "startOSCARSession could not parse "
-- "response as XML: %s\n", response);
-- /* Note to translators: %s in this string is a URL */
-- msg = generate_error_message(response_node,
-- get_start_oscar_session_url(od));
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
-- g_free(msg);
-- return FALSE;
-- }
--
-- /* Grab the necessary XML nodes */
-- tmp_node = xmlnode_get_child(response_node, "statusCode");
-- data_node = xmlnode_get_child(response_node, "data");
-- if (data_node != NULL) {
-- host_node = xmlnode_get_child(data_node, "host");
-- port_node = xmlnode_get_child(data_node, "port");
-- cookie_node = xmlnode_get_child(data_node, "cookie");
-- }
--
-- /* Make sure we have a status code */
-- if (tmp_node == NULL || (tmp = xmlnode_get_data_unescaped(tmp_node)) == NULL) {
-- char *msg;
-- purple_debug_error("oscar", "startOSCARSession response was "
-- "missing statusCode: %s\n", response);
-- msg = generate_error_message(response_node,
-- get_start_oscar_session_url(od));
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
-- g_free(msg);
-- xmlnode_free(response_node);
-- return FALSE;
-- }
--
-- /* Make sure the status code was 200 */
-- code = atoi(tmp);
-- if (code != 200)
-- {
-- xmlnode *status_detail_node;
-- guint status_detail = 0;
--
-- status_detail_node = xmlnode_get_child(response_node,
-- "statusDetailCode");
-- if (status_detail_node) {
-- gchar *data = xmlnode_get_data(status_detail_node);
-- if (data) {
-- status_detail = atoi(data);
-- g_free(data);
-- }
-- }
--
-- purple_debug_error("oscar", "startOSCARSession response statusCode "
-- "was %s: %s\n", tmp, response);
--
-- if ((code == 401 && status_detail != 1014) || code == 607)
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-- _("You have been connecting and disconnecting too "
-- "frequently. Wait ten minutes and try again. If "
-- "you continue to try, you will need to wait even "
-- "longer."));
-- else {
-- char *msg;
-- msg = generate_error_message(response_node,
-- get_start_oscar_session_url(od));
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg);
-- g_free(msg);
-- }
--
-- g_free(tmp);
-- xmlnode_free(response_node);
-- return FALSE;
-- }
-- g_free(tmp);
--
-- /* Make sure we have everything else */
-- if (data_node == NULL || host_node == NULL || port_node == NULL || cookie_node == NULL)
-- {
-- char *msg;
-- purple_debug_error("oscar", "startOSCARSession response was missing "
-- "something: %s\n", response);
-- msg = generate_error_message(response_node,
-- get_start_oscar_session_url(od));
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
-- g_free(msg);
-- xmlnode_free(response_node);
-- return FALSE;
-- }
--
-- if (strcmp(encryption_type, OSCAR_NO_ENCRYPTION) != 0) {
-- tls_node = xmlnode_get_child(data_node, "tlsCertName");
-- if (tls_node != NULL) {
-- *tls_certname = xmlnode_get_data_unescaped(tls_node);
-- } else {
-- if (strcmp(encryption_type, OSCAR_OPPORTUNISTIC_ENCRYPTION) == 0) {
-- purple_debug_warning("oscar", "We haven't received a tlsCertName to use. We will not do SSL to BOS.\n");
-- } else {
-- purple_debug_error("oscar", "startOSCARSession was missing tlsCertName: %s\n", response);
-- purple_connection_error_reason(
-- gc,
-- PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
-- _("You required encryption in your account settings, but one of the servers doesn't support it."));
-- xmlnode_free(response_node);
-- return FALSE;
-- }
-- }
-- }
--
-- /* Extract data from the XML */
-- *host = xmlnode_get_data_unescaped(host_node);
-- tmp = xmlnode_get_data_unescaped(port_node);
-- *cookie = xmlnode_get_data_unescaped(cookie_node);
--
-- if (*host == NULL || **host == '\0' || tmp == NULL || *tmp == '\0' || *cookie == NULL || **cookie == '\0')
-- {
-- char *msg;
-- purple_debug_error("oscar", "startOSCARSession response was missing "
-- "something: %s\n", response);
-- msg = generate_error_message(response_node,
-- get_start_oscar_session_url(od));
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
-- g_free(msg);
-- g_free(*host);
-- g_free(tmp);
-- g_free(*cookie);
-- xmlnode_free(response_node);
-- return FALSE;
-- }
--
-- *port = atoi(tmp);
-- g_free(tmp);
--
-- return TRUE;
--}
--
--static void start_oscar_session_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message)
--{
-- OscarData *od;
-- PurpleConnection *gc;
-- char *host, *cookie;
-- char *tls_certname = NULL;
-- unsigned short port;
-- guint8 *cookiedata;
-- gsize cookiedata_len = 0;
--
-- od = user_data;
-- gc = od->gc;
--
-- od->url_data = NULL;
--
-- if (error_message != NULL || len == 0) {
-- gchar *tmp;
-- /* Note to translators: The first %s is a URL, the second is an
-- error message. */
-- tmp = g_strdup_printf(_("Error requesting %s: %s"),
-- get_start_oscar_session_url(od), error_message ?
-- error_message : _("The server returned an empty response"));
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-- g_free(tmp);
-- return;
-- }
--
-- if (!parse_start_oscar_session_response(gc, url_text, len, &host, &port, &cookie, &tls_certname))
-- return;
--
-- cookiedata = purple_base64_decode(cookie, &cookiedata_len);
-- oscar_connect_to_bos(gc, od, host, port, cookiedata, cookiedata_len, tls_certname);
-- g_free(cookiedata);
--
-- g_free(host);
-- g_free(cookie);
-- g_free(tls_certname);
--}
--
--static void send_start_oscar_session(OscarData *od, const char *token, const char *session_key, time_t hosttime)
--{
-- char *query_string, *signature, *url;
-- PurpleAccount *account = purple_connection_get_account(od->gc);
-- const gchar *encryption_type = purple_account_get_string(account, "encryption", OSCAR_DEFAULT_ENCRYPTION);
--
-- /*
-- * Construct the GET parameters. 0x00000611 is the distid given to
-- * us by AOL for use as the default libpurple distid.
-- */
-- query_string = g_strdup_printf("a=%s"
-- "&distId=%d"
-- "&f=xml"
-- "&k=%s"
-- "&ts=%" PURPLE_TIME_T_MODIFIER
-- "&useTLS=%d",
-- purple_url_encode(token),
-- oscar_get_ui_info_int(od->icq ? "prpl-icq-distid" : "prpl-aim-distid", 0x00000611),
-- get_client_key(od),
-- hosttime,
-- strcmp(encryption_type, OSCAR_NO_ENCRYPTION) != 0 ? 1 : 0);
-- signature = generate_signature("GET", get_start_oscar_session_url(od),
-- query_string, session_key);
-- url = g_strdup_printf("%s?%s&sig_sha256=%s", get_start_oscar_session_url(od),
-- query_string, signature);
-- g_free(query_string);
-- g_free(signature);
--
-- /* Make the request */
-- od->url_data = purple_util_fetch_url_request_len_with_account(account,
-- url, TRUE, NULL, FALSE, NULL, FALSE, -1,
-- start_oscar_session_cb, od);
-- g_free(url);
--}
--
--/**
-- * This function parses the given response from a clientLogin request
-- * and extracts the useful information.
-- *
-- * @param gc The PurpleConnection. If the response data does
-- * not indicate then purple_connection_error_reason()
-- * will be called to close this connection.
-- * @param response The response data from the clientLogin request.
-- * @param response_len The length of the above response, or -1 if
-- * @response is NUL terminated.
-- * @param token If parsing was successful then this will be set to
-- * a newly allocated string containing the token. The
-- * caller should g_free this string when it is finished
-- * with it. On failure this value will be untouched.
-- * @param secret If parsing was successful then this will be set to
-- * a newly allocated string containing the secret. The
-- * caller should g_free this string when it is finished
-- * with it. On failure this value will be untouched.
-- * @param hosttime If parsing was successful then this will be set to
-- * the time on the OpenAuth Server in seconds since the
-- * Unix epoch. On failure this value will be untouched.
-- *
-- * @return TRUE if the request was successful and we were able to
-- * extract all info we need. Otherwise FALSE.
-- */
--static gboolean parse_client_login_response(PurpleConnection *gc, const gchar *response, gsize response_len, char **token, char **secret, time_t *hosttime)
--{
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- xmlnode *response_node, *tmp_node, *data_node;
-- xmlnode *secret_node = NULL, *hosttime_node = NULL, *token_node = NULL, *tokena_node = NULL;
-- char *tmp;
--
-- /* Parse the response as XML */
-- response_node = xmlnode_from_str(response, response_len);
-- if (response_node == NULL)
-- {
-- char *msg;
-- purple_debug_error("oscar", "clientLogin could not parse "
-- "response as XML: %s\n", response);
-- msg = generate_error_message(response_node,
-- get_client_login_url(od));
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
-- g_free(msg);
-- return FALSE;
-- }
--
-- /* Grab the necessary XML nodes */
-- tmp_node = xmlnode_get_child(response_node, "statusCode");
-- data_node = xmlnode_get_child(response_node, "data");
-- if (data_node != NULL) {
-- secret_node = xmlnode_get_child(data_node, "sessionSecret");
-- hosttime_node = xmlnode_get_child(data_node, "hostTime");
-- token_node = xmlnode_get_child(data_node, "token");
-- if (token_node != NULL)
-- tokena_node = xmlnode_get_child(token_node, "a");
-- }
--
-- /* Make sure we have a status code */
-- if (tmp_node == NULL || (tmp = xmlnode_get_data_unescaped(tmp_node)) == NULL) {
-- char *msg;
-- purple_debug_error("oscar", "clientLogin response was "
-- "missing statusCode: %s\n", response);
-- msg = generate_error_message(response_node,
-- get_client_login_url(od));
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
-- g_free(msg);
-- xmlnode_free(response_node);
-- return FALSE;
-- }
--
-- /* Make sure the status code was 200 */
-- if (strcmp(tmp, "200") != 0)
-- {
-- int status_code, status_detail_code = 0;
--
-- status_code = atoi(tmp);
-- g_free(tmp);
-- tmp_node = xmlnode_get_child(response_node, "statusDetailCode");
-- if (tmp_node != NULL && (tmp = xmlnode_get_data_unescaped(tmp_node)) != NULL) {
-- status_detail_code = atoi(tmp);
-- g_free(tmp);
-- }
--
-- purple_debug_error("oscar", "clientLogin response statusCode "
-- "was %d (%d): %s\n", status_code, status_detail_code, response);
--
-- if (status_code == 330 && status_detail_code == 3011) {
-- PurpleAccount *account = purple_connection_get_account(gc);
-- if (!purple_account_get_remember_password(account))
-- purple_account_set_password(account, NULL);
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
-- _("Incorrect password"));
-- } else if (status_code == 330 && status_detail_code == 3015) {
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
-- _("Server requested that you fill out a CAPTCHA in order to "
-- "sign in, but this client does not currently support CAPTCHAs."));
-- } else if (status_code == 401 && status_detail_code == 3019) {
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-- _("AOL does not allow your screen name to authenticate here"));
-- } else {
-- char *msg;
-- msg = generate_error_message(response_node,
-- get_client_login_url(od));
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg);
-- g_free(msg);
-- }
--
-- xmlnode_free(response_node);
-- return FALSE;
-- }
-- g_free(tmp);
--
-- /* Make sure we have everything else */
-- if (data_node == NULL || secret_node == NULL ||
-- token_node == NULL || tokena_node == NULL)
-- {
-- char *msg;
-- purple_debug_error("oscar", "clientLogin response was missing "
-- "something: %s\n", response);
-- msg = generate_error_message(response_node,
-- get_client_login_url(od));
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
-- g_free(msg);
-- xmlnode_free(response_node);
-- return FALSE;
-- }
--
-- /* Extract data from the XML */
-- *token = xmlnode_get_data_unescaped(tokena_node);
-- *secret = xmlnode_get_data_unescaped(secret_node);
-- tmp = xmlnode_get_data_unescaped(hosttime_node);
-- if (*token == NULL || **token == '\0' || *secret == NULL || **secret == '\0' || tmp == NULL || *tmp == '\0')
-- {
-- char *msg;
-- purple_debug_error("oscar", "clientLogin response was missing "
-- "something: %s\n", response);
-- msg = generate_error_message(response_node,
-- get_client_login_url(od));
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
-- g_free(msg);
-- g_free(*token);
-- g_free(*secret);
-- g_free(tmp);
-- xmlnode_free(response_node);
-- return FALSE;
-- }
--
-- *hosttime = strtol(tmp, NULL, 10);
-- g_free(tmp);
--
-- xmlnode_free(response_node);
--
-- return TRUE;
--}
--
--static void client_login_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message)
--{
-- OscarData *od;
-- PurpleConnection *gc;
-- char *token, *secret, *session_key;
-- time_t hosttime;
-- int password_len;
-- char *password;
--
-- od = user_data;
-- gc = od->gc;
--
-- od->url_data = NULL;
--
-- if (error_message != NULL || len == 0) {
-- gchar *tmp;
-- tmp = g_strdup_printf(_("Error requesting %s: %s"),
-- get_client_login_url(od), error_message ?
-- error_message : _("The server returned an empty response"));
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-- g_free(tmp);
-- return;
-- }
--
-- if (!parse_client_login_response(gc, url_text, len, &token, &secret, &hosttime))
-- return;
--
-- password_len = strlen(purple_connection_get_password(gc));
-- password = g_strdup_printf("%.*s",
-- od->icq ? MIN(password_len, MAXICQPASSLEN) : password_len,
-- purple_connection_get_password(gc));
-- session_key = hmac_sha256(password, secret);
-- g_free(password);
-- g_free(secret);
--
-- send_start_oscar_session(od, token, session_key, hosttime);
--
-- g_free(token);
-- g_free(session_key);
--}
--
--/**
-- * This function sends a request to
-- * https://api.screenname.aol.com/auth/clientLogin with the user's
-- * username and password and receives the user's session key, which is
-- * used to request a connection to the BOSS server.
-- */
--void send_client_login(OscarData *od, const char *username)
--{
-- PurpleConnection *gc;
-- GString *request, *body;
-- const char *tmp;
-- char *password;
-- int password_len;
--
-- gc = od->gc;
--
-- /*
-- * We truncate ICQ passwords to 8 characters. There is probably a
-- * limit for AIM passwords, too, but we really only need to do
-- * this for ICQ because older ICQ clients let you enter a password
-- * as long as you wanted and then they truncated it silently.
-- *
-- * And we can truncate based on the number of bytes and not the
-- * number of characters because passwords for AIM and ICQ are
-- * supposed to be plain ASCII (I don't know if this has always been
-- * the case, though).
-- */
-- tmp = purple_connection_get_password(gc);
-- password_len = strlen(tmp);
-- password = g_strndup(tmp, od->icq ? MIN(password_len, MAXICQPASSLEN) : password_len);
--
-- /* Construct the body of the HTTP POST request */
-- body = g_string_new("");
-- g_string_append_printf(body, "devId=%s", get_client_key(od));
-- g_string_append_printf(body, "&f=xml");
-- g_string_append_printf(body, "&pwd=%s", purple_url_encode(password));
-- g_string_append_printf(body, "&s=%s", purple_url_encode(username));
-- g_free(password);
--
-- /* Construct an HTTP POST request */
-- request = g_string_new("POST /auth/clientLogin HTTP/1.0\r\n"
-- "Connection: close\r\n"
-- "Accept: */*\r\n");
--
-- /* Tack on the body */
-- g_string_append_printf(request, "Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n");
-- g_string_append_printf(request, "Content-Length: %" G_GSIZE_FORMAT "\r\n\r\n", body->len);
-- g_string_append_len(request, body->str, body->len);
-- g_string_free(body, TRUE);
--
-- /* Send the POST request */
-- od->url_data = purple_util_fetch_url_request_len_with_account(
-- purple_connection_get_account(gc), get_client_login_url(od),
-- TRUE, NULL, FALSE, request->str, FALSE, -1,
-- client_login_cb, od);
-- g_string_free(request, TRUE);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/COPYING pidgin-2.10.7-nonprism/libpurple/protocols/oscar/COPYING
---- pidgin-2.10.7/libpurple/protocols/oscar/COPYING 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/COPYING 1969-12-31 21:00:00.000000000 -0300
-@@ -1,504 +0,0 @@
-- GNU LESSER GENERAL PUBLIC LICENSE
-- Version 2.1, February 1999
--
-- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
-- 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- Everyone is permitted to copy and distribute verbatim copies
-- of this license document, but changing it is not allowed.
--
--[This is the first released version of the Lesser GPL. It also counts
-- as the successor of the GNU Library Public License, version 2, hence
-- the version number 2.1.]
--
-- Preamble
--
-- The licenses for most software are designed to take away your
--freedom to share and change it. By contrast, the GNU General Public
--Licenses are intended to guarantee your freedom to share and change
--free software--to make sure the software is free for all its users.
--
-- This license, the Lesser General Public License, applies to some
--specially designated software packages--typically libraries--of the
--Free Software Foundation and other authors who decide to use it. You
--can use it too, but we suggest you first think carefully about whether
--this license or the ordinary General Public License is the better
--strategy to use in any particular case, based on the explanations below.
--
-- When we speak of free software, we are referring to freedom of use,
--not price. Our General Public Licenses are designed to make sure that
--you have the freedom to distribute copies of free software (and charge
--for this service if you wish); that you receive source code or can get
--it if you want it; that you can change the software and use pieces of
--it in new free programs; and that you are informed that you can do
--these things.
--
-- To protect your rights, we need to make restrictions that forbid
--distributors to deny you these rights or to ask you to surrender these
--rights. These restrictions translate to certain responsibilities for
--you if you distribute copies of the library or if you modify it.
--
-- For example, if you distribute copies of the library, whether gratis
--or for a fee, you must give the recipients all the rights that we gave
--you. You must make sure that they, too, receive or can get the source
--code. If you link other code with the library, you must provide
--complete object files to the recipients, so that they can relink them
--with the library after making changes to the library and recompiling
--it. And you must show them these terms so they know their rights.
--
-- We protect your rights with a two-step method: (1) we copyright the
--library, and (2) we offer you this license, which gives you legal
--permission to copy, distribute and/or modify the library.
--
-- To protect each distributor, we want to make it very clear that
--there is no warranty for the free library. Also, if the library is
--modified by someone else and passed on, the recipients should know
--that what they have is not the original version, so that the original
--author's reputation will not be affected by problems that might be
--introduced by others.
--
-- Finally, software patents pose a constant threat to the existence of
--any free program. We wish to make sure that a company cannot
--effectively restrict the users of a free program by obtaining a
--restrictive license from a patent holder. Therefore, we insist that
--any patent license obtained for a version of the library must be
--consistent with the full freedom of use specified in this license.
--
-- Most GNU software, including some libraries, is covered by the
--ordinary GNU General Public License. This license, the GNU Lesser
--General Public License, applies to certain designated libraries, and
--is quite different from the ordinary General Public License. We use
--this license for certain libraries in order to permit linking those
--libraries into non-free programs.
--
-- When a program is linked with a library, whether statically or using
--a shared library, the combination of the two is legally speaking a
--combined work, a derivative of the original library. The ordinary
--General Public License therefore permits such linking only if the
--entire combination fits its criteria of freedom. The Lesser General
--Public License permits more lax criteria for linking other code with
--the library.
--
-- We call this license the "Lesser" General Public License because it
--does Less to protect the user's freedom than the ordinary General
--Public License. It also provides other free software developers Less
--of an advantage over competing non-free programs. These disadvantages
--are the reason we use the ordinary General Public License for many
--libraries. However, the Lesser license provides advantages in certain
--special circumstances.
--
-- For example, on rare occasions, there may be a special need to
--encourage the widest possible use of a certain library, so that it becomes
--a de-facto standard. To achieve this, non-free programs must be
--allowed to use the library. A more frequent case is that a free
--library does the same job as widely used non-free libraries. In this
--case, there is little to gain by limiting the free library to free
--software only, so we use the Lesser General Public License.
--
-- In other cases, permission to use a particular library in non-free
--programs enables a greater number of people to use a large body of
--free software. For example, permission to use the GNU C Library in
--non-free programs enables many more people to use the whole GNU
--operating system, as well as its variant, the GNU/Linux operating
--system.
--
-- Although the Lesser General Public License is Less protective of the
--users' freedom, it does ensure that the user of a program that is
--linked with the Library has the freedom and the wherewithal to run
--that program using a modified version of the Library.
--
-- The precise terms and conditions for copying, distribution and
--modification follow. Pay close attention to the difference between a
--"work based on the library" and a "work that uses the library". The
--former contains code derived from the library, whereas the latter must
--be combined with the library in order to run.
--
-- GNU LESSER GENERAL PUBLIC LICENSE
-- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
--
-- 0. This License Agreement applies to any software library or other
--program which contains a notice placed by the copyright holder or
--other authorized party saying it may be distributed under the terms of
--this Lesser General Public License (also called "this License").
--Each licensee is addressed as "you".
--
-- A "library" means a collection of software functions and/or data
--prepared so as to be conveniently linked with application programs
--(which use some of those functions and data) to form executables.
--
-- The "Library", below, refers to any such software library or work
--which has been distributed under these terms. A "work based on the
--Library" means either the Library or any derivative work under
--copyright law: that is to say, a work containing the Library or a
--portion of it, either verbatim or with modifications and/or translated
--straightforwardly into another language. (Hereinafter, translation is
--included without limitation in the term "modification".)
--
-- "Source code" for a work means the preferred form of the work for
--making modifications to it. For a library, complete source code means
--all the source code for all modules it contains, plus any associated
--interface definition files, plus the scripts used to control compilation
--and installation of the library.
--
-- Activities other than copying, distribution and modification are not
--covered by this License; they are outside its scope. The act of
--running a program using the Library is not restricted, and output from
--such a program is covered only if its contents constitute a work based
--on the Library (independent of the use of the Library in a tool for
--writing it). Whether that is true depends on what the Library does
--and what the program that uses the Library does.
--
-- 1. You may copy and distribute verbatim copies of the Library's
--complete source code as you receive it, in any medium, provided that
--you conspicuously and appropriately publish on each copy an
--appropriate copyright notice and disclaimer of warranty; keep intact
--all the notices that refer to this License and to the absence of any
--warranty; and distribute a copy of this License along with the
--Library.
--
-- You may charge a fee for the physical act of transferring a copy,
--and you may at your option offer warranty protection in exchange for a
--fee.
--
-- 2. You may modify your copy or copies of the Library or any portion
--of it, thus forming a work based on the Library, and copy and
--distribute such modifications or work under the terms of Section 1
--above, provided that you also meet all of these conditions:
--
-- a) The modified work must itself be a software library.
--
-- b) You must cause the files modified to carry prominent notices
-- stating that you changed the files and the date of any change.
--
-- c) You must cause the whole of the work to be licensed at no
-- charge to all third parties under the terms of this License.
--
-- d) If a facility in the modified Library refers to a function or a
-- table of data to be supplied by an application program that uses
-- the facility, other than as an argument passed when the facility
-- is invoked, then you must make a good faith effort to ensure that,
-- in the event an application does not supply such function or
-- table, the facility still operates, and performs whatever part of
-- its purpose remains meaningful.
--
-- (For example, a function in a library to compute square roots has
-- a purpose that is entirely well-defined independent of the
-- application. Therefore, Subsection 2d requires that any
-- application-supplied function or table used by this function must
-- be optional: if the application does not supply it, the square
-- root function must still compute square roots.)
--
--These requirements apply to the modified work as a whole. If
--identifiable sections of that work are not derived from the Library,
--and can be reasonably considered independent and separate works in
--themselves, then this License, and its terms, do not apply to those
--sections when you distribute them as separate works. But when you
--distribute the same sections as part of a whole which is a work based
--on the Library, the distribution of the whole must be on the terms of
--this License, whose permissions for other licensees extend to the
--entire whole, and thus to each and every part regardless of who wrote
--it.
--
--Thus, it is not the intent of this section to claim rights or contest
--your rights to work written entirely by you; rather, the intent is to
--exercise the right to control the distribution of derivative or
--collective works based on the Library.
--
--In addition, mere aggregation of another work not based on the Library
--with the Library (or with a work based on the Library) on a volume of
--a storage or distribution medium does not bring the other work under
--the scope of this License.
--
-- 3. You may opt to apply the terms of the ordinary GNU General Public
--License instead of this License to a given copy of the Library. To do
--this, you must alter all the notices that refer to this License, so
--that they refer to the ordinary GNU General Public License, version 2,
--instead of to this License. (If a newer version than version 2 of the
--ordinary GNU General Public License has appeared, then you can specify
--that version instead if you wish.) Do not make any other change in
--these notices.
--
-- Once this change is made in a given copy, it is irreversible for
--that copy, so the ordinary GNU General Public License applies to all
--subsequent copies and derivative works made from that copy.
--
-- This option is useful when you wish to copy part of the code of
--the Library into a program that is not a library.
--
-- 4. You may copy and distribute the Library (or a portion or
--derivative of it, under Section 2) in object code or executable form
--under the terms of Sections 1 and 2 above provided that you accompany
--it with the complete corresponding machine-readable source code, which
--must be distributed under the terms of Sections 1 and 2 above on a
--medium customarily used for software interchange.
--
-- If distribution of object code is made by offering access to copy
--from a designated place, then offering equivalent access to copy the
--source code from the same place satisfies the requirement to
--distribute the source code, even though third parties are not
--compelled to copy the source along with the object code.
--
-- 5. A program that contains no derivative of any portion of the
--Library, but is designed to work with the Library by being compiled or
--linked with it, is called a "work that uses the Library". Such a
--work, in isolation, is not a derivative work of the Library, and
--therefore falls outside the scope of this License.
--
-- However, linking a "work that uses the Library" with the Library
--creates an executable that is a derivative of the Library (because it
--contains portions of the Library), rather than a "work that uses the
--library". The executable is therefore covered by this License.
--Section 6 states terms for distribution of such executables.
--
-- When a "work that uses the Library" uses material from a header file
--that is part of the Library, the object code for the work may be a
--derivative work of the Library even though the source code is not.
--Whether this is true is especially significant if the work can be
--linked without the Library, or if the work is itself a library. The
--threshold for this to be true is not precisely defined by law.
--
-- If such an object file uses only numerical parameters, data
--structure layouts and accessors, and small macros and small inline
--functions (ten lines or less in length), then the use of the object
--file is unrestricted, regardless of whether it is legally a derivative
--work. (Executables containing this object code plus portions of the
--Library will still fall under Section 6.)
--
-- Otherwise, if the work is a derivative of the Library, you may
--distribute the object code for the work under the terms of Section 6.
--Any executables containing that work also fall under Section 6,
--whether or not they are linked directly with the Library itself.
--
-- 6. As an exception to the Sections above, you may also combine or
--link a "work that uses the Library" with the Library to produce a
--work containing portions of the Library, and distribute that work
--under terms of your choice, provided that the terms permit
--modification of the work for the customer's own use and reverse
--engineering for debugging such modifications.
--
-- You must give prominent notice with each copy of the work that the
--Library is used in it and that the Library and its use are covered by
--this License. You must supply a copy of this License. If the work
--during execution displays copyright notices, you must include the
--copyright notice for the Library among them, as well as a reference
--directing the user to the copy of this License. Also, you must do one
--of these things:
--
-- a) Accompany the work with the complete corresponding
-- machine-readable source code for the Library including whatever
-- changes were used in the work (which must be distributed under
-- Sections 1 and 2 above); and, if the work is an executable linked
-- with the Library, with the complete machine-readable "work that
-- uses the Library", as object code and/or source code, so that the
-- user can modify the Library and then relink to produce a modified
-- executable containing the modified Library. (It is understood
-- that the user who changes the contents of definitions files in the
-- Library will not necessarily be able to recompile the application
-- to use the modified definitions.)
--
-- b) Use a suitable shared library mechanism for linking with the
-- Library. A suitable mechanism is one that (1) uses at run time a
-- copy of the library already present on the user's computer system,
-- rather than copying library functions into the executable, and (2)
-- will operate properly with a modified version of the library, if
-- the user installs one, as long as the modified version is
-- interface-compatible with the version that the work was made with.
--
-- c) Accompany the work with a written offer, valid for at
-- least three years, to give the same user the materials
-- specified in Subsection 6a, above, for a charge no more
-- than the cost of performing this distribution.
--
-- d) If distribution of the work is made by offering access to copy
-- from a designated place, offer equivalent access to copy the above
-- specified materials from the same place.
--
-- e) Verify that the user has already received a copy of these
-- materials or that you have already sent this user a copy.
--
-- For an executable, the required form of the "work that uses the
--Library" must include any data and utility programs needed for
--reproducing the executable from it. However, as a special exception,
--the materials to be distributed need not include anything that is
--normally distributed (in either source or binary form) with the major
--components (compiler, kernel, and so on) of the operating system on
--which the executable runs, unless that component itself accompanies
--the executable.
--
-- It may happen that this requirement contradicts the license
--restrictions of other proprietary libraries that do not normally
--accompany the operating system. Such a contradiction means you cannot
--use both them and the Library together in an executable that you
--distribute.
--
-- 7. You may place library facilities that are a work based on the
--Library side-by-side in a single library together with other library
--facilities not covered by this License, and distribute such a combined
--library, provided that the separate distribution of the work based on
--the Library and of the other library facilities is otherwise
--permitted, and provided that you do these two things:
--
-- a) Accompany the combined library with a copy of the same work
-- based on the Library, uncombined with any other library
-- facilities. This must be distributed under the terms of the
-- Sections above.
--
-- b) Give prominent notice with the combined library of the fact
-- that part of it is a work based on the Library, and explaining
-- where to find the accompanying uncombined form of the same work.
--
-- 8. You may not copy, modify, sublicense, link with, or distribute
--the Library except as expressly provided under this License. Any
--attempt otherwise to copy, modify, sublicense, link with, or
--distribute the Library is void, and will automatically terminate your
--rights under this License. However, parties who have received copies,
--or rights, from you under this License will not have their licenses
--terminated so long as such parties remain in full compliance.
--
-- 9. You are not required to accept this License, since you have not
--signed it. However, nothing else grants you permission to modify or
--distribute the Library or its derivative works. These actions are
--prohibited by law if you do not accept this License. Therefore, by
--modifying or distributing the Library (or any work based on the
--Library), you indicate your acceptance of this License to do so, and
--all its terms and conditions for copying, distributing or modifying
--the Library or works based on it.
--
-- 10. Each time you redistribute the Library (or any work based on the
--Library), the recipient automatically receives a license from the
--original licensor to copy, distribute, link with or modify the Library
--subject to these terms and conditions. You may not impose any further
--restrictions on the recipients' exercise of the rights granted herein.
--You are not responsible for enforcing compliance by third parties with
--this License.
--
-- 11. If, as a consequence of a court judgment or allegation of patent
--infringement or for any other reason (not limited to patent issues),
--conditions are imposed on you (whether by court order, agreement or
--otherwise) that contradict the conditions of this License, they do not
--excuse you from the conditions of this License. If you cannot
--distribute so as to satisfy simultaneously your obligations under this
--License and any other pertinent obligations, then as a consequence you
--may not distribute the Library at all. For example, if a patent
--license would not permit royalty-free redistribution of the Library by
--all those who receive copies directly or indirectly through you, then
--the only way you could satisfy both it and this License would be to
--refrain entirely from distribution of the Library.
--
--If any portion of this section is held invalid or unenforceable under any
--particular circumstance, the balance of the section is intended to apply,
--and the section as a whole is intended to apply in other circumstances.
--
--It is not the purpose of this section to induce you to infringe any
--patents or other property right claims or to contest validity of any
--such claims; this section has the sole purpose of protecting the
--integrity of the free software distribution system which is
--implemented by public license practices. Many people have made
--generous contributions to the wide range of software distributed
--through that system in reliance on consistent application of that
--system; it is up to the author/donor to decide if he or she is willing
--to distribute software through any other system and a licensee cannot
--impose that choice.
--
--This section is intended to make thoroughly clear what is believed to
--be a consequence of the rest of this License.
--
-- 12. If the distribution and/or use of the Library is restricted in
--certain countries either by patents or by copyrighted interfaces, the
--original copyright holder who places the Library under this License may add
--an explicit geographical distribution limitation excluding those countries,
--so that distribution is permitted only in or among countries not thus
--excluded. In such case, this License incorporates the limitation as if
--written in the body of this License.
--
-- 13. The Free Software Foundation may publish revised and/or new
--versions of the Lesser General Public License from time to time.
--Such new versions will be similar in spirit to the present version,
--but may differ in detail to address new problems or concerns.
--
--Each version is given a distinguishing version number. If the Library
--specifies a version number of this License which applies to it and
--"any later version", you have the option of following the terms and
--conditions either of that version or of any later version published by
--the Free Software Foundation. If the Library does not specify a
--license version number, you may choose any version ever published by
--the Free Software Foundation.
--
-- 14. If you wish to incorporate parts of the Library into other free
--programs whose distribution conditions are incompatible with these,
--write to the author to ask for permission. For software which is
--copyrighted by the Free Software Foundation, write to the Free
--Software Foundation; we sometimes make exceptions for this. Our
--decision will be guided by the two goals of preserving the free status
--of all derivatives of our free software and of promoting the sharing
--and reuse of software generally.
--
-- NO WARRANTY
--
-- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
--WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
--EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
--OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
--KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
--IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
--PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
--LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
--THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
--
-- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
--WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
--AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
--FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
--CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
--LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
--RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
--FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
--SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
--DAMAGES.
--
-- END OF TERMS AND CONDITIONS
--
-- How to Apply These Terms to Your New Libraries
--
-- If you develop a new library, and you want it to be of the greatest
--possible use to the public, we recommend making it free software that
--everyone can redistribute and change. You can do so by permitting
--redistribution under these terms (or, alternatively, under the terms of the
--ordinary General Public License).
--
-- To apply these terms, attach the following notices to the library. It is
--safest to attach them to the start of each source file to most effectively
--convey the exclusion of warranty; and each file should have at least the
--"copyright" line and a pointer to where the full notice is found.
--
-- <one line to give the library's name and a brief idea of what it does.>
-- Copyright (C) <year> <name of author>
--
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 2 of the License, or (at your option) any later version.
--
-- This library 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
-- Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public
-- License along with this library; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--
--Also add information on how to contact you by electronic and paper mail.
--
--You should also get your employer (if you work as a programmer) or your
--school, if any, to sign a "copyright disclaimer" for the library, if
--necessary. Here is a sample; alter the names:
--
-- Yoyodyne, Inc., hereby disclaims all copyright interest in the
-- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
--
-- <signature of Ty Coon>, 1 April 1990
-- Ty Coon, President of Vice
--
--That's all there is to it!
--
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/encoding.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/encoding.c
---- pidgin-2.10.7/libpurple/protocols/oscar/encoding.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/encoding.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,285 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--#include "encoding.h"
--
--static gchar *
--encoding_multi_convert_to_utf8(const gchar *text, gssize textlen, const gchar *encodings, GError **error, gboolean fallback)
--{
-- gchar *utf8 = NULL;
-- const gchar *begin = encodings;
-- const gchar *end = NULL;
-- gchar *curr_encoding = NULL; /* allocated buffer for encoding name */
-- const gchar *curr_encoding_ro = NULL; /* read-only encoding name */
--
-- if (!encodings) {
-- purple_debug_error("oscar", "encodings is NULL");
-- return NULL;
-- }
--
-- for (;;)
-- {
-- /* extract next encoding */
-- end = strchr(begin, ',');
-- if (!end) {
-- curr_encoding_ro = begin;
-- } else { /* allocate buffer for encoding */
-- curr_encoding = g_strndup(begin, end - begin);
-- if (!curr_encoding) {
-- purple_debug_error("oscar", "Error allocating memory for encoding");
-- break;
-- }
-- curr_encoding_ro = curr_encoding;
-- }
--
-- if (!g_ascii_strcasecmp(curr_encoding_ro, "utf-8") && g_utf8_validate(text, textlen, NULL)) {
-- break;
-- }
--
-- utf8 = g_convert(text, textlen, "UTF-8", curr_encoding_ro, NULL, NULL, NULL);
--
-- if (!end) /* last occurence. do not free curr_encoding: buffer was'nt allocated */
-- break;
--
-- g_free(curr_encoding); /* free allocated buffer for encoding here */
--
-- if (utf8) /* text was successfully converted */
-- break;
--
-- begin = end + 1;
-- }
--
-- if (!utf8 && fallback)
-- { /* "begin" points to last encoding */
-- utf8 = g_convert_with_fallback(text, textlen, "UTF-8", begin, "?", NULL, NULL, error);
-- }
--
-- return utf8;
--}
--
--static gchar *
--encoding_extract(const char *encoding)
--{
-- char *begin, *end;
--
-- if (encoding == NULL) {
-- return NULL;
-- }
--
-- if (!g_str_has_prefix(encoding, "text/aolrtf; charset=") &&
-- !g_str_has_prefix(encoding, "text/x-aolrtf; charset=") &&
-- !g_str_has_prefix(encoding, "text/plain; charset=")) {
-- return g_strdup(encoding);
-- }
--
-- begin = strchr(encoding, '"');
-- end = strrchr(encoding, '"');
--
-- if ((begin == NULL) || (end == NULL) || (begin >= end)) {
-- return g_strdup(encoding);
-- }
--
-- return g_strndup(begin+1, (end-1) - begin);
--}
--
--gchar *
--oscar_encoding_to_utf8(const char *encoding, const char *text, int textlen)
--{
-- gchar *utf8 = NULL;
-- const gchar *glib_encoding = NULL;
-- gchar *extracted_encoding = encoding_extract(encoding);
--
-- if (extracted_encoding == NULL || *extracted_encoding == '\0') {
-- purple_debug_info("oscar", "Empty encoding, assuming UTF-8\n");
-- } else if (!g_ascii_strcasecmp(extracted_encoding, "iso-8859-1")) {
-- glib_encoding = "iso-8859-1";
-- } else if (!g_ascii_strcasecmp(extracted_encoding, "ISO-8859-1-Windows-3.1-Latin-1") || !g_ascii_strcasecmp(extracted_encoding, "us-ascii")) {
-- glib_encoding = "Windows-1252";
-- } else if (!g_ascii_strcasecmp(extracted_encoding, "unicode-2-0")) {
-- glib_encoding = "UTF-16BE";
-- } else if (g_ascii_strcasecmp(extracted_encoding, "utf-8")) {
-- glib_encoding = extracted_encoding;
-- }
--
-- if (glib_encoding != NULL) {
-- utf8 = encoding_multi_convert_to_utf8(text, textlen, glib_encoding, NULL, FALSE);
-- }
--
-- /*
-- * If utf8 is still NULL then either the encoding is utf-8 or
-- * we have been unable to convert the text to utf-8 from the encoding
-- * that was specified. So we check if the text is valid utf-8 then
-- * just copy it.
-- */
-- if (utf8 == NULL) {
-- if (textlen != 0 && *text != '\0' && !g_utf8_validate(text, textlen, NULL))
-- utf8 = g_strdup(_("(There was an error receiving this message. The buddy you are speaking with is probably using a different encoding than expected. If you know what encoding he is using, you can specify it in the advanced account options for your AIM/ICQ account.)"));
-- else
-- utf8 = g_strndup(text, textlen);
-- }
--
-- g_free(extracted_encoding);
-- return utf8;
--}
--
--gchar *
--oscar_utf8_try_convert(PurpleAccount *account, OscarData *od, const gchar *msg)
--{
-- const char *charset = NULL;
-- char *ret = NULL;
--
-- if (msg == NULL)
-- return NULL;
--
-- if (g_utf8_validate(msg, -1, NULL))
-- return g_strdup(msg);
--
-- if (od->icq)
-- charset = purple_account_get_string(account, "encoding", NULL);
--
-- if(charset && *charset)
-- ret = encoding_multi_convert_to_utf8(msg, -1, charset, NULL, FALSE);
--
-- if(!ret)
-- ret = purple_utf8_try_convert(msg);
--
-- return ret;
--}
--
--static gchar *
--oscar_convert_to_utf8(const gchar *data, gsize datalen, const char *charsetstr, gboolean fallback)
--{
-- gchar *ret = NULL;
-- GError *err = NULL;
--
-- if ((charsetstr == NULL) || (*charsetstr == '\0'))
-- return NULL;
--
-- if (g_ascii_strcasecmp("UTF-8", charsetstr)) {
-- ret = encoding_multi_convert_to_utf8(data, datalen, charsetstr, &err, fallback);
-- if (err != NULL) {
-- purple_debug_warning("oscar", "Conversion from %s failed: %s.\n",
-- charsetstr, err->message);
-- g_error_free(err);
-- }
-- } else {
-- if (g_utf8_validate(data, datalen, NULL))
-- ret = g_strndup(data, datalen);
-- else
-- purple_debug_warning("oscar", "String is not valid UTF-8.\n");
-- }
--
-- return ret;
--}
--
--gchar *
--oscar_decode_im(PurpleAccount *account, const char *sourcebn, guint16 charset, const gchar *data, gsize datalen)
--{
-- gchar *ret = NULL;
-- /* charsetstr1 is always set to what the correct encoding should be. */
-- const gchar *charsetstr1, *charsetstr2, *charsetstr3 = NULL;
--
-- if ((datalen == 0) || (data == NULL))
-- return NULL;
--
-- if (charset == AIM_CHARSET_UNICODE) {
-- charsetstr1 = "UTF-16BE";
-- charsetstr2 = "UTF-8";
-- } else if (charset == AIM_CHARSET_LATIN_1) {
-- if ((sourcebn != NULL) && oscar_util_valid_name_icq(sourcebn))
-- charsetstr1 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING);
-- else
-- charsetstr1 = "ISO-8859-1";
-- charsetstr2 = "UTF-8";
-- } else if (charset == AIM_CHARSET_ASCII) {
-- /* Should just be "ASCII" */
-- charsetstr1 = "ASCII";
-- charsetstr2 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING);
-- } else if (charset == 0x000d) {
-- /* iChat sending unicode over a Direct IM connection = UTF-8 */
-- /* Mobile AIM client on multiple devices (including Blackberry Tour, Nokia 3100, and LG VX6000) = ISO-8859-1 */
-- charsetstr1 = "UTF-8";
-- charsetstr2 = "ISO-8859-1";
-- charsetstr3 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING);
-- } else {
-- /* Unknown, hope for valid UTF-8... */
-- charsetstr1 = "UTF-8";
-- charsetstr2 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING);
-- }
--
-- purple_debug_info("oscar", "Parsing IM, charset=0x%04hx, datalen=%" G_GSIZE_FORMAT ", choice1=%s, choice2=%s, choice3=%s\n",
-- charset, datalen, charsetstr1, charsetstr2, (charsetstr3 ? charsetstr3 : ""));
--
-- ret = oscar_convert_to_utf8(data, datalen, charsetstr1, FALSE);
-- if (ret == NULL) {
-- if (charsetstr3 != NULL) {
-- /* Try charsetstr2 without allowing substitutions, then fall through to charsetstr3 if needed */
-- ret = oscar_convert_to_utf8(data, datalen, charsetstr2, FALSE);
-- if (ret == NULL)
-- ret = oscar_convert_to_utf8(data, datalen, charsetstr3, TRUE);
-- } else {
-- /* Try charsetstr2, allowing substitutions */
-- ret = oscar_convert_to_utf8(data, datalen, charsetstr2, TRUE);
-- }
-- }
-- if (ret == NULL) {
-- char *str, *salvage, *tmp;
--
-- str = g_malloc(datalen + 1);
-- strncpy(str, data, datalen);
-- str[datalen] = '\0';
-- salvage = purple_utf8_salvage(str);
-- tmp = g_strdup_printf(_("(There was an error receiving this message. Either you and %s have different encodings selected, or %s has a buggy client.)"),
-- sourcebn, sourcebn);
-- ret = g_strdup_printf("%s %s", salvage, tmp);
-- g_free(tmp);
-- g_free(str);
-- g_free(salvage);
-- }
--
-- return ret;
--}
--
--static guint16
--get_simplest_charset(const char *utf8)
--{
-- while (*utf8)
-- {
-- if ((unsigned char)(*utf8) > 0x7f) {
-- /* not ASCII! */
-- return AIM_CHARSET_UNICODE;
-- }
-- utf8++;
-- }
-- return AIM_CHARSET_ASCII;
--}
--
--gchar *
--oscar_encode_im(const gchar *msg, gsize *result_len, guint16 *charset, gchar **charsetstr)
--{
-- guint16 msg_charset = get_simplest_charset(msg);
-- if (charset != NULL) {
-- *charset = msg_charset;
-- }
-- if (charsetstr != NULL) {
-- *charsetstr = msg_charset == AIM_CHARSET_ASCII ? "us-ascii" : "unicode-2-0";
-- }
-- return g_convert(msg, -1, msg_charset == AIM_CHARSET_ASCII ? "ASCII" : "UTF-16BE", "UTF-8", NULL, result_len, NULL);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/encoding.h pidgin-2.10.7-nonprism/libpurple/protocols/oscar/encoding.h
---- pidgin-2.10.7/libpurple/protocols/oscar/encoding.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/encoding.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,46 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--#ifndef _ENCODING_H_
--#define _ENCODING_H_
--
--#include "oscar.h"
--#include "oscarcommon.h"
--
--gchar * oscar_encoding_to_utf8(const char *encoding, const char *text, int textlen);
--gchar * oscar_utf8_try_convert(PurpleAccount *account, OscarData *od, const gchar *msg);
--
--/**
-- * This attemps to decode an incoming IM into a UTF8 string.
-- *
-- * We try decoding using two different character sets. The charset
-- * specified in the IM determines the order in which we attempt to
-- * decode. We do this because there are lots of broken ICQ clients
-- * that don't correctly send non-ASCII messages. And if Purple isn't
-- * able to deal with that crap, then people complain like banshees.
-- */
--gchar * oscar_decode_im(PurpleAccount *account, const char *sourcebn, guint16 charset, const gchar *data, gsize datalen);
--
--/**
-- * Figure out what encoding to use when sending a given outgoing message.
-- */
--gchar * oscar_encode_im(const gchar *msg, gsize *result_len, guint16 *charset, gchar **charsetstr);
--
--#endif
-\ No newline at end of file
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_admin.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_admin.c
---- pidgin-2.10.7/libpurple/protocols/oscar/family_admin.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_admin.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,246 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Family 0x0007 - Account Administration.
-- *
-- * Used for stuff like changing the formating of your username, changing your
-- * email address, requesting an account confirmation email, getting account info,
-- */
--
--#include "oscar.h"
--
--/**
-- * Subtype 0x0002 - Request a bit of account info.
-- *
-- * Info should be one of the following:
-- * 0x0001 - Username formatting
-- * 0x0011 - Email address
-- * 0x0013 - Unknown
-- */
--void
--aim_admin_getinfo(OscarData *od, FlapConnection *conn, guint16 info)
--{
-- ByteStream bs;
-- aim_snacid_t snacid;
--
-- byte_stream_new(&bs, 4);
--
-- byte_stream_put16(&bs, info);
-- byte_stream_put16(&bs, 0x0000);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ADMIN, 0x0002, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ADMIN, 0x0002, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--/**
-- * Subtypes 0x0003 and 0x0005 - Parse account info.
-- *
-- * Called in reply to both an information request (subtype 0x0002) and
-- * an information change (subtype 0x0004).
-- */
--static void
--infochange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- aim_rxcallback_t userfunc;
-- char *url=NULL, *sn=NULL, *email=NULL;
-- guint16 perms, tlvcount, err=0;
--
-- perms = byte_stream_get16(bs);
-- tlvcount = byte_stream_get16(bs);
--
-- while (tlvcount && byte_stream_bytes_left(bs)) {
-- guint16 type, length;
--
-- type = byte_stream_get16(bs);
-- length = byte_stream_get16(bs);
--
-- switch (type) {
-- case 0x0001: {
-- g_free(sn);
-- sn = byte_stream_getstr(bs, length);
-- } break;
--
-- case 0x0004: {
-- g_free(url);
-- url = byte_stream_getstr(bs, length);
-- } break;
--
-- case 0x0008: {
-- err = byte_stream_get16(bs);
-- } break;
--
-- case 0x0011: {
-- g_free(email);
-- if (length == 0)
-- email = g_strdup("*suppressed");
-- else
-- email = byte_stream_getstr(bs, length);
-- } break;
-- }
--
-- tlvcount--;
-- }
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- userfunc(od, conn, frame, (snac->subtype == 0x0005) ? 1 : 0, perms, err, url, sn, email);
--
-- g_free(sn);
-- g_free(url);
-- g_free(email);
--}
--
--/**
-- * Subtype 0x0004 - Set the formatting of username (change spaces and capitalization).
-- */
--void
--aim_admin_setnick(OscarData *od, FlapConnection *conn, const char *newnick)
--{
-- ByteStream bs;
-- aim_snacid_t snacid;
-- GSList *tlvlist = NULL;
--
-- byte_stream_new(&bs, 2+2+strlen(newnick));
--
-- aim_tlvlist_add_str(&tlvlist, 0x0001, newnick);
--
-- aim_tlvlist_write(&bs, &tlvlist);
-- aim_tlvlist_free(tlvlist);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ADMIN, 0x0004, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ADMIN, 0x0004, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--/**
-- * Subtype 0x0004 - Change password.
-- */
--void
--aim_admin_changepasswd(OscarData *od, FlapConnection *conn, const char *newpw, const char *curpw)
--{
-- ByteStream bs;
-- GSList *tlvlist = NULL;
-- aim_snacid_t snacid;
--
-- byte_stream_new(&bs, 4+strlen(curpw)+4+strlen(newpw));
--
-- /* new password TLV t(0002) */
-- aim_tlvlist_add_str(&tlvlist, 0x0002, newpw);
--
-- /* current password TLV t(0012) */
-- aim_tlvlist_add_str(&tlvlist, 0x0012, curpw);
--
-- aim_tlvlist_write(&bs, &tlvlist);
-- aim_tlvlist_free(tlvlist);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ADMIN, 0x0004, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ADMIN, 0x0004, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--/**
-- * Subtype 0x0004 - Change email address.
-- */
--void
--aim_admin_setemail(OscarData *od, FlapConnection *conn, const char *newemail)
--{
-- ByteStream bs;
-- aim_snacid_t snacid;
-- GSList *tlvlist = NULL;
--
-- byte_stream_new(&bs, 2+2+strlen(newemail));
--
-- aim_tlvlist_add_str(&tlvlist, 0x0011, newemail);
--
-- aim_tlvlist_write(&bs, &tlvlist);
-- aim_tlvlist_free(tlvlist);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ADMIN, 0x0004, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ADMIN, 0x0004, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--/*
-- * Subtype 0x0006 - Request account confirmation.
-- *
-- * This will cause an email to be sent to the address associated with
-- * the account. By following the instructions in the mail, you can
-- * get the TRIAL flag removed from your account.
-- *
-- */
--void
--aim_admin_reqconfirm(OscarData *od, FlapConnection *conn)
--{
-- aim_genericreq_n(od, conn, SNAC_FAMILY_ADMIN, 0x0006);
--}
--
--/**
-- * Subtype SNAC_FAMILY_ADMIN - Account confirmation request acknowledgement.
-- */
--static int
--accountconfirm(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- guint16 status;
-- /* GSList *tlvlist; */
--
-- status = byte_stream_get16(bs);
-- /* Status is 0x0013 if unable to confirm at this time */
--
-- /* tlvlist = aim_tlvlist_read(bs); */
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, status);
--
-- /* aim_tlvlist_free(tlvlist); */
--
-- return ret;
--}
--
--static int
--snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- if ((snac->subtype == 0x0003) || (snac->subtype == 0x0005)) {
-- infochange(od, conn, mod, frame, snac, bs);
-- return 1;
-- } else if (snac->subtype == SNAC_FAMILY_ADMIN)
-- return accountconfirm(od, conn, mod, frame, snac, bs);
--
-- return 0;
--}
--
--int admin_modfirst(OscarData *od, aim_module_t *mod)
--{
-- mod->family = SNAC_FAMILY_ADMIN;
-- mod->version = 0x0001;
-- mod->toolid = 0x0010;
-- mod->toolversion = 0x0629;
-- mod->flags = 0;
-- strncpy(mod->name, "admin", sizeof(mod->name));
-- mod->snachandler = snachandler;
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_alert.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_alert.c
---- pidgin-2.10.7/libpurple/protocols/oscar/family_alert.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_alert.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,238 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Family 0x0018 - Email notification
-- *
-- * Used for being alerted when the email address(es) associated with
-- * your username get new electronic-m. For normal AIM accounts, you
-- * get the email address username@netscape.net. AOL accounts have
-- * username@aol.com, and can also activate a netscape.net account.
-- * Note: This information might be out of date.
-- */
--
--#include "oscar.h"
--
--/**
-- * Subtype 0x0006 - Request information about your email account
-- *
-- * @param od The oscar session.
-- * @param conn The email connection for this session.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int
--aim_email_sendcookies(OscarData *od)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ALERT)))
-- return -EINVAL;
--
-- byte_stream_new(&bs, 2+16+16);
--
-- /* Number of cookies to follow */
-- byte_stream_put16(&bs, 0x0002);
--
-- /* Cookie */
-- byte_stream_put16(&bs, 0x5d5e);
-- byte_stream_put16(&bs, 0x1708);
-- byte_stream_put16(&bs, 0x55aa);
-- byte_stream_put16(&bs, 0x11d3);
-- byte_stream_put16(&bs, 0xb143);
-- byte_stream_put16(&bs, 0x0060);
-- byte_stream_put16(&bs, 0xb0fb);
-- byte_stream_put16(&bs, 0x1ecb);
--
-- /* Cookie */
-- byte_stream_put16(&bs, 0xb380);
-- byte_stream_put16(&bs, 0x9ad8);
-- byte_stream_put16(&bs, 0x0dba);
-- byte_stream_put16(&bs, 0x11d5);
-- byte_stream_put16(&bs, 0x9f8a);
-- byte_stream_put16(&bs, 0x0060);
-- byte_stream_put16(&bs, 0xb0ee);
-- byte_stream_put16(&bs, 0x0631);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ALERT, 0x0006, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ALERT, 0x0006, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--
--/**
-- * Subtype 0x0007 - Receive information about your email account
-- *
-- * So I don't even know if you can have multiple 16 byte keys,
-- * but this is coded so it will handle that, and handle it well.
-- * This tells you if you have unread mail or not, the URL you
-- * should use to access that mail, and the domain name for the
-- * email account (username@domainname.com). If this is the
-- * first 0x0007 SNAC you've received since you signed on, or if
-- * this is just a periodic status update, this will also contain
-- * the number of unread emails that you have.
-- */
--static int
--parseinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- struct aim_emailinfo *new;
-- GSList *tlvlist;
-- guint8 *cookie8, *cookie16;
-- int tmp, havenewmail = 0; /* Used to tell the client we have _new_ mail */
--
-- char *alertitle = NULL, *alerturl = NULL;
--
-- cookie8 = byte_stream_getraw(bs, 8); /* Possibly the code used to log you in to mail? */
-- cookie16 = byte_stream_getraw(bs, 16); /* Mail cookie sent above */
--
-- /* See if we already have some info associated with this cookie */
-- for (new = od->emailinfo; (new && memcmp(cookie16, new->cookie16, 16)); new = new->next);
-- if (new) {
-- /* Free some of the old info, if it exists */
-- g_free(new->cookie8);
-- g_free(new->cookie16);
-- g_free(new->url);
-- g_free(new->domain);
-- } else {
-- /* We don't already have info, so create a new struct for it */
-- new = g_new0(struct aim_emailinfo, 1);
-- new->next = od->emailinfo;
-- od->emailinfo = new;
-- }
--
-- new->cookie8 = cookie8;
-- new->cookie16 = cookie16;
--
-- tlvlist = aim_tlvlist_readnum(bs, byte_stream_get16(bs));
--
-- tmp = aim_tlv_get16(tlvlist, 0x0080, 1);
-- if (tmp) {
-- if (new->nummsgs < tmp)
-- havenewmail = 1;
-- new->nummsgs = tmp;
-- } else {
-- /* If they don't send a 0x0080 TLV, it means we definitely have new mail */
-- /* (ie. this is not just another status update) */
-- havenewmail = 1;
-- new->nummsgs++; /* We know we have at least 1 new email */
-- }
-- new->url = aim_tlv_getstr(tlvlist, 0x0007, 1);
-- if (!(new->unread = aim_tlv_get8(tlvlist, 0x0081, 1))) {
-- havenewmail = 0;
-- new->nummsgs = 0;
-- }
-- new->domain = aim_tlv_getstr(tlvlist, 0x0082, 1);
-- new->flag = aim_tlv_get16(tlvlist, 0x0084, 1);
--
-- alertitle = aim_tlv_getstr(tlvlist, 0x0005, 1);
-- alerturl = aim_tlv_getstr(tlvlist, 0x000d, 1);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, new, havenewmail, alertitle, (alerturl ? alerturl + 2 : NULL));
--
-- aim_tlvlist_free(tlvlist);
--
-- g_free(alertitle);
-- g_free(alerturl);
--
-- return ret;
--}
--
--/**
-- * Subtype 0x0016 - Send something or other
-- *
-- * @param od The oscar session.
-- * @param conn The email connection for this session.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int
--aim_email_activate(OscarData *od)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ALERT)))
-- return -EINVAL;
--
-- byte_stream_new(&bs, 1+16);
--
-- /* I would guess this tells AIM that you want updates for your mail accounts */
-- /* ...but I really have no idea */
-- byte_stream_put8(&bs, 0x02);
-- byte_stream_put32(&bs, 0x04000000);
-- byte_stream_put32(&bs, 0x04000000);
-- byte_stream_put32(&bs, 0x04000000);
-- byte_stream_put32(&bs, 0x00000000);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ALERT, 0x0016, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ALERT, 0x0006, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--static int
--snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- if (snac->subtype == 0x0007)
-- return parseinfo(od, conn, mod, frame, snac, bs);
--
-- return 0;
--}
--
--static void
--email_shutdown(OscarData *od, aim_module_t *mod)
--{
-- while (od->emailinfo)
-- {
-- struct aim_emailinfo *tmp = od->emailinfo;
-- od->emailinfo = od->emailinfo->next;
-- g_free(tmp->cookie16);
-- g_free(tmp->cookie8);
-- g_free(tmp->url);
-- g_free(tmp->domain);
-- g_free(tmp);
-- }
--
-- return;
--}
--
--int
--email_modfirst(OscarData *od, aim_module_t *mod)
--{
-- mod->family = SNAC_FAMILY_ALERT;
-- mod->version = 0x0001;
-- mod->toolid = 0x0010;
-- mod->toolversion = 0x0629;
-- mod->flags = 0;
-- strncpy(mod->name, "alert", sizeof(mod->name));
-- mod->snachandler = snachandler;
-- mod->shutdown = email_shutdown;
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_auth.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_auth.c
---- pidgin-2.10.7/libpurple/protocols/oscar/family_auth.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_auth.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,631 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Family 0x0017 - Authentication.
-- *
-- * Deals with the authorizer for SNAC-based login, and also old-style
-- * non-SNAC login.
-- *
-- */
--
--#include "oscar.h"
--
--#include <ctype.h>
--
--#include "cipher.h"
--
--/* #define USE_XOR_FOR_ICQ */
--
--#ifdef USE_XOR_FOR_ICQ
--/**
-- * Encode a password using old XOR method
-- *
-- * This takes a const pointer to a (null terminated) string
-- * containing the unencoded password. It also gets passed
-- * an already allocated buffer to store the encoded password.
-- * This buffer should be the exact length of the password without
-- * the null. The encoded password buffer /is not %NULL terminated/.
-- *
-- * The encoding_table seems to be a fixed set of values. We'll
-- * hope it doesn't change over time!
-- *
-- * This is only used for the XOR method, not the better MD5 method.
-- *
-- * @param password Incoming password.
-- * @param encoded Buffer to put encoded password.
-- */
--static int
--aim_encode_password(const char *password, guint8 *encoded)
--{
-- guint8 encoding_table[] = {
-- 0xf3, 0x26, 0x81, 0xc4,
-- 0x39, 0x86, 0xdb, 0x92,
-- 0x71, 0xa3, 0xb9, 0xe6,
-- 0x53, 0x7a, 0x95, 0x7c
-- };
-- unsigned int i;
--
-- for (i = 0; i < strlen(password); i++)
-- encoded[i] = (password[i] ^ encoding_table[i]);
--
-- return 0;
--}
--#endif
--
--#ifdef USE_OLD_MD5
--static int
--aim_encode_password_md5(const char *password, size_t password_len, const char *key, guint8 *digest)
--{
-- PurpleCipherContext *context;
--
-- context = purple_cipher_context_new_by_name("md5", NULL);
-- purple_cipher_context_append(context, (const guchar *)key, strlen(key));
-- purple_cipher_context_append(context, (const guchar *)password, password_len);
-- purple_cipher_context_append(context, (const guchar *)AIM_MD5_STRING, strlen(AIM_MD5_STRING));
-- purple_cipher_context_digest(context, 16, digest, NULL);
-- purple_cipher_context_destroy(context);
--
-- return 0;
--}
--#else
--static int
--aim_encode_password_md5(const char *password, size_t password_len, const char *key, guint8 *digest)
--{
-- PurpleCipher *cipher;
-- PurpleCipherContext *context;
-- guchar passdigest[16];
--
-- cipher = purple_ciphers_find_cipher("md5");
--
-- context = purple_cipher_context_new(cipher, NULL);
-- purple_cipher_context_append(context, (const guchar *)password, password_len);
-- purple_cipher_context_digest(context, 16, passdigest, NULL);
-- purple_cipher_context_destroy(context);
--
-- context = purple_cipher_context_new(cipher, NULL);
-- purple_cipher_context_append(context, (const guchar *)key, strlen(key));
-- purple_cipher_context_append(context, passdigest, 16);
-- purple_cipher_context_append(context, (const guchar *)AIM_MD5_STRING, strlen(AIM_MD5_STRING));
-- purple_cipher_context_digest(context, 16, digest, NULL);
-- purple_cipher_context_destroy(context);
--
-- return 0;
--}
--#endif
--
--#ifdef USE_XOR_FOR_ICQ
--/*
-- * Part two of the ICQ hack. Note the ignoring of the key.
-- */
--static int
--goddamnicq2(OscarData *od, FlapConnection *conn, const char *sn, const char *password, ClientInfo *ci)
--{
-- FlapFrame *frame;
-- GSList *tlvlist = NULL;
-- int passwdlen;
-- guint8 *password_encoded;
-- guint32 distrib;
--
-- passwdlen = strlen(password);
-- password_encoded = (guint8 *)g_malloc(passwdlen+1);
-- if (passwdlen > MAXICQPASSLEN)
-- passwdlen = MAXICQPASSLEN;
--
-- frame = flap_frame_new(od, 0x01, 1152);
--
-- aim_encode_password(password, password_encoded);
--
-- distrib = oscar_get_ui_info_int(
-- od->icq ? "prpl-icq-distid" : "prpl-aim-distid",
-- ci->distrib);
--
-- byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */
-- aim_tlvlist_add_str(&tlvlist, 0x0001, sn);
-- aim_tlvlist_add_raw(&tlvlist, 0x0002, passwdlen, password_encoded);
--
-- if (ci->clientstring != NULL)
-- aim_tlvlist_add_str(&tlvlist, 0x0003, ci->clientstring);
-- else {
-- gchar *clientstring = oscar_get_clientstring();
-- aim_tlvlist_add_str(&tlvlist, 0x0003, clientstring);
-- g_free(clientstring);
-- }
-- aim_tlvlist_add_16(&tlvlist, 0x0016, (guint16)ci->clientid);
-- aim_tlvlist_add_16(&tlvlist, 0x0017, (guint16)ci->major);
-- aim_tlvlist_add_16(&tlvlist, 0x0018, (guint16)ci->minor);
-- aim_tlvlist_add_16(&tlvlist, 0x0019, (guint16)ci->point);
-- aim_tlvlist_add_16(&tlvlist, 0x001a, (guint16)ci->build);
-- aim_tlvlist_add_32(&tlvlist, 0x0014, distrib); /* distribution chan */
-- aim_tlvlist_add_str(&tlvlist, 0x000f, ci->lang);
-- aim_tlvlist_add_str(&tlvlist, 0x000e, ci->country);
--
-- aim_tlvlist_write(&frame->data, &tlvlist);
--
-- g_free(password_encoded);
-- aim_tlvlist_free(tlvlist);
--
-- flap_connection_send(conn, frame);
--
-- return 0;
--}
--#endif
--
--/*
-- * Subtype 0x0002
-- *
-- * This is the initial login request packet.
-- *
-- * NOTE!! If you want/need to make use of the aim_sendmemblock() function,
-- * then the client information you send here must exactly match the
-- * executable that you're pulling the data from.
-- *
-- * Java AIM 1.1.19:
-- * clientstring = "AOL Instant Messenger (TM) version 1.1.19 for Java built 03/24/98, freeMem 215871 totalMem 1048567, i686, Linus, #2 SMP Sun Feb 11 03:41:17 UTC 2001 2.4.1-ac9, IBM Corporation, 1.1.8, 45.3, Tue Mar 27 12:09:17 PST 2001"
-- * clientid = 0x0001
-- * major = 0x0001
-- * minor = 0x0001
-- * point = (not sent)
-- * build = 0x0013
-- * unknown= (not sent)
-- *
-- * AIM for Linux 1.1.112:
-- * clientstring = "AOL Instant Messenger (SM)"
-- * clientid = 0x1d09
-- * major = 0x0001
-- * minor = 0x0001
-- * point = 0x0001
-- * build = 0x0070
-- * unknown= 0x0000008b
-- * serverstore = 0x01
-- *
-- * @param truncate_pass Truncate the password to 8 characters. This
-- * usually happens for AOL accounts. We are told that we
-- * should truncate it if the 0x0017/0x0007 SNAC contains
-- * a TLV of type 0x0026 with data 0x0000.
-- * @param allow_multiple_logins Allow multiple logins? If TRUE, the AIM
-- * server will prompt the user when multiple logins occur. If
-- * FALSE, existing connections (on other clients) will be
-- * disconnected automatically as we connect.
-- */
--int
--aim_send_login(OscarData *od, FlapConnection *conn, const char *sn, const char *password, gboolean truncate_pass, ClientInfo *ci, const char *key, gboolean allow_multiple_logins)
--{
-- FlapFrame *frame;
-- GSList *tlvlist = NULL;
-- guint8 digest[16];
-- aim_snacid_t snacid;
-- size_t password_len;
-- guint32 distrib;
--
-- if (!ci || !sn || !password)
-- return -EINVAL;
--
--#ifdef USE_XOR_FOR_ICQ
-- /* If we're signing on an ICQ account then use the older, XOR login method */
-- if (aim_snvalid_icq(sn))
-- return goddamnicq2(od, conn, sn, password, ci);
--#endif
--
-- frame = flap_frame_new(od, 0x02, 1152);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_AUTH, 0x0002, 0x0000, NULL, 0);
-- aim_putsnac(&frame->data, SNAC_FAMILY_AUTH, 0x0002, snacid);
--
-- aim_tlvlist_add_str(&tlvlist, 0x0001, sn);
--
-- /* Truncate ICQ and AOL passwords, if necessary */
-- password_len = strlen(password);
-- if (oscar_util_valid_name_icq(sn) && (password_len > MAXICQPASSLEN))
-- password_len = MAXICQPASSLEN;
-- else if (truncate_pass && password_len > 8)
-- password_len = 8;
--
-- aim_encode_password_md5(password, password_len, key, digest);
--
-- distrib = oscar_get_ui_info_int(
-- od->icq ? "prpl-icq-distid" : "prpl-aim-distid",
-- ci->distrib);
--
-- aim_tlvlist_add_raw(&tlvlist, 0x0025, 16, digest);
--
--#ifndef USE_OLD_MD5
-- aim_tlvlist_add_noval(&tlvlist, 0x004c);
--#endif
--
-- if (ci->clientstring != NULL)
-- aim_tlvlist_add_str(&tlvlist, 0x0003, ci->clientstring);
-- else {
-- gchar *clientstring = oscar_get_clientstring();
-- aim_tlvlist_add_str(&tlvlist, 0x0003, clientstring);
-- g_free(clientstring);
-- }
-- aim_tlvlist_add_16(&tlvlist, 0x0016, (guint16)ci->clientid);
-- aim_tlvlist_add_16(&tlvlist, 0x0017, (guint16)ci->major);
-- aim_tlvlist_add_16(&tlvlist, 0x0018, (guint16)ci->minor);
-- aim_tlvlist_add_16(&tlvlist, 0x0019, (guint16)ci->point);
-- aim_tlvlist_add_16(&tlvlist, 0x001a, (guint16)ci->build);
-- aim_tlvlist_add_32(&tlvlist, 0x0014, distrib);
-- aim_tlvlist_add_str(&tlvlist, 0x000f, ci->lang);
-- aim_tlvlist_add_str(&tlvlist, 0x000e, ci->country);
--
-- /*
-- * If set, old-fashioned buddy lists will not work. You will need
-- * to use SSI.
-- */
-- aim_tlvlist_add_8(&tlvlist, 0x004a, (allow_multiple_logins ? 0x01 : 0x03));
--
-- aim_tlvlist_write(&frame->data, &tlvlist);
--
-- aim_tlvlist_free(tlvlist);
--
-- flap_connection_send(conn, frame);
--
-- return 0;
--}
--
--/*
-- * This is sent back as a general response to the login command.
-- * It can be either an error or a success, depending on the
-- * presence of certain TLVs.
-- *
-- * The client should check the value passed as errorcode. If
-- * its nonzero, there was an error.
-- */
--static int
--parse(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- GSList *tlvlist;
-- aim_rxcallback_t userfunc;
-- struct aim_authresp_info *info;
-- int ret = 0;
--
-- info = g_new0(struct aim_authresp_info, 1);
--
-- /*
-- * Read block of TLVs. All further data is derived
-- * from what is parsed here.
-- */
-- tlvlist = aim_tlvlist_read(bs);
--
-- /*
-- * No matter what, we should have a username.
-- */
-- if (aim_tlv_gettlv(tlvlist, 0x0001, 1)) {
-- info->bn = aim_tlv_getstr(tlvlist, 0x0001, 1);
-- purple_connection_set_display_name(od->gc, info->bn);
-- }
--
-- /*
-- * Check for an error code. If so, we should also
-- * have an error url.
-- */
-- if (aim_tlv_gettlv(tlvlist, 0x0008, 1))
-- info->errorcode = aim_tlv_get16(tlvlist, 0x0008, 1);
-- if (aim_tlv_gettlv(tlvlist, 0x0004, 1))
-- info->errorurl = aim_tlv_getstr(tlvlist, 0x0004, 1);
--
-- /*
-- * BOS server address.
-- */
-- if (aim_tlv_gettlv(tlvlist, 0x0005, 1))
-- info->bosip = aim_tlv_getstr(tlvlist, 0x0005, 1);
--
-- /*
-- * Authorization cookie.
-- */
-- if (aim_tlv_gettlv(tlvlist, 0x0006, 1)) {
-- aim_tlv_t *tmptlv;
--
-- tmptlv = aim_tlv_gettlv(tlvlist, 0x0006, 1);
-- if (tmptlv != NULL)
-- {
-- info->cookielen = tmptlv->length;
-- info->cookie = tmptlv->value;
-- }
-- }
--
-- /*
-- * The email address attached to this account
-- * Not available for ICQ or @mac.com logins.
-- * If you receive this TLV, then you are allowed to use
-- * family 0x0018 to check the status of your email.
-- * XXX - Not really true!
-- */
-- if (aim_tlv_gettlv(tlvlist, 0x0011, 1))
-- info->email = aim_tlv_getstr(tlvlist, 0x0011, 1);
--
-- /*
-- * The registration status. (Not real sure what it means.)
-- * Not available for ICQ or @mac.com logins.
-- *
-- * 1 = No disclosure
-- * 2 = Limited disclosure
-- * 3 = Full disclosure
-- *
-- * This has to do with whether your email address is available
-- * to other users or not. AFAIK, this feature is no longer used.
-- *
-- * Means you can use the admin family? (0x0007)
-- *
-- */
-- if (aim_tlv_gettlv(tlvlist, 0x0013, 1))
-- info->regstatus = aim_tlv_get16(tlvlist, 0x0013, 1);
--
-- if (aim_tlv_gettlv(tlvlist, 0x0040, 1))
-- info->latestbeta.build = aim_tlv_get32(tlvlist, 0x0040, 1);
-- if (aim_tlv_gettlv(tlvlist, 0x0041, 1))
-- info->latestbeta.url = aim_tlv_getstr(tlvlist, 0x0041, 1);
-- if (aim_tlv_gettlv(tlvlist, 0x0042, 1))
-- info->latestbeta.info = aim_tlv_getstr(tlvlist, 0x0042, 1);
-- if (aim_tlv_gettlv(tlvlist, 0x0043, 1))
-- info->latestbeta.name = aim_tlv_getstr(tlvlist, 0x0043, 1);
--
-- if (aim_tlv_gettlv(tlvlist, 0x0044, 1))
-- info->latestrelease.build = aim_tlv_get32(tlvlist, 0x0044, 1);
-- if (aim_tlv_gettlv(tlvlist, 0x0045, 1))
-- info->latestrelease.url = aim_tlv_getstr(tlvlist, 0x0045, 1);
-- if (aim_tlv_gettlv(tlvlist, 0x0046, 1))
-- info->latestrelease.info = aim_tlv_getstr(tlvlist, 0x0046, 1);
-- if (aim_tlv_gettlv(tlvlist, 0x0047, 1))
-- info->latestrelease.name = aim_tlv_getstr(tlvlist, 0x0047, 1);
--
-- /*
-- * URL to change password.
-- */
-- if (aim_tlv_gettlv(tlvlist, 0x0054, 1))
-- info->chpassurl = aim_tlv_getstr(tlvlist, 0x0054, 1);
--
-- od->authinfo = info;
--
-- if ((userfunc = aim_callhandler(od, snac ? snac->family : SNAC_FAMILY_AUTH, snac ? snac->subtype : 0x0003)))
-- ret = userfunc(od, conn, frame, info);
--
-- aim_tlvlist_free(tlvlist);
--
-- return ret;
--}
--
--#ifdef USE_XOR_FOR_ICQ
--/*
-- * Subtype 0x0007 (kind of) - Send a fake type 0x0007 SNAC to the client
-- *
-- * This is a bit confusing.
-- *
-- * Normal SNAC login goes like this:
-- * - connect
-- * - server sends flap version
-- * - client sends flap version
-- * - client sends username (17/6)
-- * - server sends hash key (17/7)
-- * - client sends auth request (17/2 -- aim_send_login)
-- * - server yells
-- *
-- * XOR login (for ICQ) goes like this:
-- * - connect
-- * - server sends flap version
-- * - client sends auth request which contains flap version (aim_send_login)
-- * - server yells
-- *
-- * For the client API, we make them implement the most complicated version,
-- * and for the simpler version, we fake it and make it look like the more
-- * complicated process.
-- *
-- * This is done by giving the client a faked key, just so we can convince
-- * them to call aim_send_login right away, which will detect the session
-- * flag that says this is XOR login and ignore the key, sending an ICQ
-- * login request instead of the normal SNAC one.
-- *
-- * As soon as AOL makes ICQ log in the same way as AIM, this is /gone/.
-- */
--static int
--goddamnicq(OscarData *od, FlapConnection *conn, const char *sn)
--{
-- FlapFrame frame;
-- aim_rxcallback_t userfunc;
--
-- if ((userfunc = aim_callhandler(od, SNAC_FAMILY_AUTH, 0x0007)))
-- userfunc(od, conn, &frame, "");
--
-- return 0;
--}
--#endif
--
--/*
-- * Subtype 0x0006
-- *
-- * In AIM 3.5 protocol, the first stage of login is to request login from the
-- * Authorizer, passing it the username for verification. If the name is
-- * invalid, a 0017/0003 is spit back, with the standard error contents. If
-- * valid, a 0017/0007 comes back, which is the signal to send it the main
-- * login command (0017/0002).
-- *
-- */
--int
--aim_request_login(OscarData *od, FlapConnection *conn, const char *sn)
--{
-- FlapFrame *frame;
-- aim_snacid_t snacid;
-- GSList *tlvlist = NULL;
--
-- if (!od || !conn || !sn)
-- return -EINVAL;
--
--#ifdef USE_XOR_FOR_ICQ
-- if (aim_snvalid_icq(sn))
-- return goddamnicq(od, conn, sn);
--#endif
--
-- frame = flap_frame_new(od, 0x02, 10+2+2+strlen(sn)+8);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_AUTH, 0x0006, 0x0000, NULL, 0);
-- aim_putsnac(&frame->data, SNAC_FAMILY_AUTH, 0x0006, snacid);
--
-- aim_tlvlist_add_str(&tlvlist, 0x0001, sn);
--
-- /* Tell the server we support SecurID logins. */
-- aim_tlvlist_add_noval(&tlvlist, 0x004b);
--
-- /* Unknown. Sent in recent WinAIM clients.*/
-- aim_tlvlist_add_noval(&tlvlist, 0x005a);
--
-- aim_tlvlist_write(&frame->data, &tlvlist);
-- aim_tlvlist_free(tlvlist);
--
-- flap_connection_send(conn, frame);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0007
-- *
-- * Middle handler for 0017/0007 SNACs. Contains the auth key prefixed
-- * by only its length in a two byte word.
-- *
-- * Calls the client, which should then use the value to call aim_send_login.
-- *
-- */
--static int
--keyparse(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int keylen, ret = 1;
-- aim_rxcallback_t userfunc;
-- char *keystr;
-- GSList *tlvlist;
-- gboolean truncate_pass;
--
-- keylen = byte_stream_get16(bs);
-- keystr = byte_stream_getstr(bs, keylen);
-- tlvlist = aim_tlvlist_read(bs);
--
-- /*
-- * If the truncate_pass TLV exists then we should truncate the
-- * user's password to 8 characters. This flag is sent to us
-- * when logging in with an AOL user's username.
-- */
-- truncate_pass = aim_tlv_gettlv(tlvlist, 0x0026, 1) != NULL;
--
-- /* XXX - When GiantGrayPanda signed on AIM I got a thing asking me to register
-- * for the netscape network. This SNAC had a type 0x0058 TLV with length 10.
-- * Data is 0x0007 0004 3e19 ae1e 0006 0004 0000 0005 */
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, keystr, (int)truncate_pass);
--
-- g_free(keystr);
-- aim_tlvlist_free(tlvlist);
--
-- return ret;
--}
--
--/**
-- * Subtype 0x000a
-- *
-- * Receive SecurID request.
-- */
--static int
--got_securid_request(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame);
--
-- return ret;
--}
--
--/**
-- * Subtype 0x000b
-- *
-- * Send SecurID response.
-- */
--int
--aim_auth_securid_send(OscarData *od, const char *securid)
--{
-- FlapConnection *conn;
-- FlapFrame *frame;
-- aim_snacid_t snacid;
-- int len;
--
-- if (!od || !(conn = flap_connection_getbytype_all(od, SNAC_FAMILY_AUTH)) || !securid)
-- return -EINVAL;
--
-- len = strlen(securid);
--
-- frame = flap_frame_new(od, 0x02, 10+2+len);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_AUTH, SNAC_SUBTYPE_AUTH_SECURID_RESPONSE, 0x0000, NULL, 0);
-- aim_putsnac(&frame->data, SNAC_FAMILY_AUTH, SNAC_SUBTYPE_AUTH_SECURID_RESPONSE, 0);
--
-- byte_stream_put16(&frame->data, len);
-- byte_stream_putstr(&frame->data, securid);
--
-- flap_connection_send(conn, frame);
--
-- return 0;
--}
--
--static void
--auth_shutdown(OscarData *od, aim_module_t *mod)
--{
-- if (od->authinfo != NULL)
-- {
-- g_free(od->authinfo->bn);
-- g_free(od->authinfo->bosip);
-- g_free(od->authinfo->errorurl);
-- g_free(od->authinfo->email);
-- g_free(od->authinfo->chpassurl);
-- g_free(od->authinfo->latestrelease.name);
-- g_free(od->authinfo->latestrelease.url);
-- g_free(od->authinfo->latestrelease.info);
-- g_free(od->authinfo->latestbeta.name);
-- g_free(od->authinfo->latestbeta.url);
-- g_free(od->authinfo->latestbeta.info);
-- g_free(od->authinfo);
-- }
--}
--
--static int
--snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- if (snac->subtype == 0x0003)
-- return parse(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x0007)
-- return keyparse(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x000a)
-- return got_securid_request(od, conn, mod, frame, snac, bs);
--
-- return 0;
--}
--
--int
--auth_modfirst(OscarData *od, aim_module_t *mod)
--{
-- mod->family = SNAC_FAMILY_AUTH;
-- mod->version = 0x0000;
-- mod->flags = 0;
-- strncpy(mod->name, "auth", sizeof(mod->name));
-- mod->snachandler = snachandler;
-- mod->shutdown = auth_shutdown;
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_bart.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_bart.c
---- pidgin-2.10.7/libpurple/protocols/oscar/family_bart.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_bart.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,186 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Family 0x0010 - Server stored buddy art
-- *
-- * Used for storing and retrieving your cute little buddy icon
-- * from the AIM servers.
-- *
-- */
--
--#include "oscar.h"
--
--/**
-- * Subtype 0x0002 - Upload your icon.
-- *
-- * @param od The oscar session.
-- * @param icon The raw data of the icon image file.
-- * @param iconlen Length of the raw data of the icon image file.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int
--aim_bart_upload(OscarData *od, const guint8 *icon, guint16 iconlen)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_BART)) || !icon || !iconlen)
-- return -EINVAL;
--
-- byte_stream_new(&bs, 2 + 2 + iconlen);
--
-- /* The reference number for the icon */
-- byte_stream_put16(&bs, 1);
--
-- /* The icon */
-- byte_stream_put16(&bs, iconlen);
-- byte_stream_putraw(&bs, icon, iconlen);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_BART, 0x0002, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_BART, 0x0002, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/**
-- * Subtype 0x0003 - Acknowledgement for uploading a buddy icon.
-- *
-- * You get this honky after you upload a buddy icon.
-- */
--static int
--uploadack(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- guint16 something, somethingelse;
-- guint8 onemorething;
--
-- something = byte_stream_get16(bs);
-- somethingelse = byte_stream_get16(bs);
-- onemorething = byte_stream_get8(bs);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame);
--
-- return ret;
--}
--
--/**
-- * Subtype 0x0004 - Request someone's icon.
-- *
-- * @param od The oscar session.
-- * @param bn The name of the buddy whose icon you are requesting.
-- * @param iconcsum The MD5 checksum of the icon you are requesting.
-- * @param iconcsumlen Length of the MD5 checksum given above. Should be 10 bytes.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int
--aim_bart_request(OscarData *od, const char *bn, guint8 iconcsumtype, const guint8 *iconcsum, guint16 iconcsumlen)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_BART)) || !bn || !strlen(bn) || !iconcsum || !iconcsumlen)
-- return -EINVAL;
--
-- byte_stream_new(&bs, 1+strlen(bn) + 4 + 1+iconcsumlen);
--
-- /* Buddy name */
-- byte_stream_put8(&bs, strlen(bn));
-- byte_stream_putstr(&bs, bn);
--
-- /* Some numbers. You like numbers, right? */
-- byte_stream_put8(&bs, 0x01);
-- byte_stream_put16(&bs, 0x0001);
-- byte_stream_put8(&bs, iconcsumtype);
--
-- /* Icon string */
-- byte_stream_put8(&bs, iconcsumlen);
-- byte_stream_putraw(&bs, iconcsum, iconcsumlen);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_BART, 0x0004, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_BART, 0x0004, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/**
-- * Subtype 0x0005 - Receive a buddy icon.
-- *
-- * This is sent in response to a buddy icon request.
-- */
--static int
--parseicon(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- char *bn;
-- guint16 flags, iconlen;
-- guint8 iconcsumtype, iconcsumlen, *iconcsum, *icon;
--
-- bn = byte_stream_getstr(bs, byte_stream_get8(bs));
-- flags = byte_stream_get16(bs);
-- iconcsumtype = byte_stream_get8(bs);
-- iconcsumlen = byte_stream_get8(bs);
-- iconcsum = byte_stream_getraw(bs, iconcsumlen);
-- iconlen = byte_stream_get16(bs);
-- icon = byte_stream_getraw(bs, iconlen);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, bn, iconcsumtype, iconcsum, iconcsumlen, icon, iconlen);
--
-- g_free(bn);
-- g_free(iconcsum);
-- g_free(icon);
--
-- return ret;
--}
--
--static int
--snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- if (snac->subtype == 0x0003)
-- return uploadack(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x0005)
-- return parseicon(od, conn, mod, frame, snac, bs);
--
-- return 0;
--}
--
--int
--bart_modfirst(OscarData *od, aim_module_t *mod)
--{
-- mod->family = SNAC_FAMILY_BART;
-- mod->version = 0x0001;
-- mod->toolid = 0x0010;
-- mod->toolversion = 0x0629;
-- mod->flags = 0;
-- strncpy(mod->name, "bart", sizeof(mod->name));
-- mod->snachandler = snachandler;
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_bos.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_bos.c
---- pidgin-2.10.7/libpurple/protocols/oscar/family_bos.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_bos.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,92 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Family 0x0009 - Basic Oscar Service.
-- *
-- * The functionality of this family has been replaced by SSI.
-- */
--
--#include "oscar.h"
--
--#include <string.h>
--
--/* Subtype 0x0002 - Request BOS rights. */
--void
--aim_bos_reqrights(OscarData *od, FlapConnection *conn)
--{
-- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_BOS, 0x0002);
--}
--
--/* Subtype 0x0003 - BOS Rights. */
--static int rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- aim_rxcallback_t userfunc;
-- GSList *tlvlist;
-- guint16 maxpermits = 0, maxdenies = 0;
-- int ret = 0;
--
-- /*
-- * TLVs follow
-- */
-- tlvlist = aim_tlvlist_read(bs);
--
-- /*
-- * TLV type 0x0001: Maximum number of buddies on permit list.
-- */
-- if (aim_tlv_gettlv(tlvlist, 0x0001, 1))
-- maxpermits = aim_tlv_get16(tlvlist, 0x0001, 1);
--
-- /*
-- * TLV type 0x0002: Maximum number of buddies on deny list.
-- */
-- if (aim_tlv_gettlv(tlvlist, 0x0002, 1))
-- maxdenies = aim_tlv_get16(tlvlist, 0x0002, 1);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, maxpermits, maxdenies);
--
-- aim_tlvlist_free(tlvlist);
--
-- return ret;
--}
--
--static int
--snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- if (snac->subtype == 0x0003)
-- return rights(od, conn, mod, frame, snac, bs);
--
-- return 0;
--}
--
--int
--bos_modfirst(OscarData *od, aim_module_t *mod)
--{
-- mod->family = SNAC_FAMILY_BOS;
-- mod->version = 0x0001;
-- mod->toolid = 0x0110;
-- mod->toolversion = 0x0629;
-- mod->flags = 0;
-- strncpy(mod->name, "bos", sizeof(mod->name));
-- mod->snachandler = snachandler;
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_buddy.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_buddy.c
---- pidgin-2.10.7/libpurple/protocols/oscar/family_buddy.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_buddy.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,153 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Family 0x0003 (SNAC_FAMILY_BUDDY) - Old-style Buddylist Management (non-SSI).
-- *
-- */
--
--#include "oscar.h"
--
--#include <string.h>
--
--/*
-- * Subtype 0x0002 - Request rights.
-- *
-- * Request Buddy List rights.
-- *
-- */
--void
--aim_buddylist_reqrights(OscarData *od, FlapConnection *conn)
--{
-- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_REQRIGHTS);
--}
--
--/*
-- * Subtype 0x0003 - Rights.
-- *
-- */
--static int
--rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- aim_rxcallback_t userfunc;
-- GSList *tlvlist;
-- guint16 maxbuddies = 0, maxwatchers = 0;
-- int ret = 0;
--
-- /*
-- * TLVs follow
-- */
-- tlvlist = aim_tlvlist_read(bs);
--
-- /*
-- * TLV type 0x0001: Maximum number of buddies.
-- */
-- if (aim_tlv_gettlv(tlvlist, 0x0001, 1))
-- maxbuddies = aim_tlv_get16(tlvlist, 0x0001, 1);
--
-- /*
-- * TLV type 0x0002: Maximum number of watchers.
-- *
-- * Watchers are other users who have you on their buddy
-- * list. (This is called the "reverse list" by a certain
-- * other IM protocol.)
-- *
-- */
-- if (aim_tlv_gettlv(tlvlist, 0x0002, 1))
-- maxwatchers = aim_tlv_get16(tlvlist, 0x0002, 1);
--
-- /*
-- * TLV type 0x0003: Unknown.
-- *
-- * ICQ only?
-- */
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, maxbuddies, maxwatchers);
--
-- aim_tlvlist_free(tlvlist);
--
-- return ret;
--}
--
--/*
-- * Subtypes 0x000b (SNAC_SUBTYPE_BUDDY_ONCOMING) and 0x000c (SNAC_SUBTYPE_BUDDY_OFFGOING) - Change in buddy status
-- *
-- * Oncoming Buddy notifications contain a subset of the
-- * user information structure. It's close enough to run
-- * through aim_info_extract() however.
-- *
-- * Although the offgoing notification contains no information,
-- * it is still in a format parsable by aim_info_extract().
-- *
-- */
--static int
--buddychange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_userinfo_t userinfo;
-- aim_rxcallback_t userfunc;
--
-- aim_info_extract(od, bs, &userinfo);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, &userinfo);
--
-- if (snac->subtype == SNAC_SUBTYPE_BUDDY_ONCOMING &&
-- userinfo.capabilities & OSCAR_CAPABILITY_XTRAZ) {
-- PurpleAccount *account = purple_connection_get_account(od->gc);
-- PurpleBuddy *buddy = purple_find_buddy(account, userinfo.bn);
--
-- if (buddy) {
-- PurplePresence *presence = purple_buddy_get_presence(buddy);
--
-- if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_MOOD))
-- icq_im_xstatus_request(od, userinfo.bn);
-- }
-- }
-- aim_info_free(&userinfo);
--
-- return ret;
--}
--
--static int
--snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- if (snac->subtype == SNAC_SUBTYPE_BUDDY_RIGHTSINFO)
-- return rights(od, conn, mod, frame, snac, bs);
-- else if ((snac->subtype == SNAC_SUBTYPE_BUDDY_ONCOMING) || (snac->subtype == SNAC_SUBTYPE_BUDDY_OFFGOING))
-- return buddychange(od, conn, mod, frame, snac, bs);
--
-- return 0;
--}
--
--int
--buddylist_modfirst(OscarData *od, aim_module_t *mod)
--{
-- mod->family = SNAC_FAMILY_BUDDY;
-- mod->version = 0x0001;
-- mod->toolid = 0x0110;
-- mod->toolversion = 0x0629;
-- mod->flags = 0;
-- strncpy(mod->name, "buddy", sizeof(mod->name));
-- mod->snachandler = snachandler;
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_chat.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_chat.c
---- pidgin-2.10.7/libpurple/protocols/oscar/family_chat.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_chat.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,398 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Family 0x000e - Routines for the Chat service.
-- *
-- */
--
--#include "oscar.h"
--
--#include <string.h>
--
--/* Stored in the ->internal of chat connections */
--struct chatconnpriv
--{
-- guint16 exchange;
-- char *name;
-- guint16 instance;
--};
--
--void
--flap_connection_destroy_chat(OscarData *od, FlapConnection *conn)
--{
-- struct chatconnpriv *ccp = (struct chatconnpriv *)conn->internal;
--
-- if (ccp)
-- g_free(ccp->name);
-- g_free(ccp);
--
-- return;
--}
--
--int
--aim_chat_readroominfo(ByteStream *bs, struct aim_chat_roominfo *outinfo)
--{
-- if (!bs || !outinfo)
-- return 0;
--
-- outinfo->exchange = byte_stream_get16(bs);
-- outinfo->namelen = byte_stream_get8(bs);
-- outinfo->name = (char *)byte_stream_getraw(bs, outinfo->namelen);
-- outinfo->instance = byte_stream_get16(bs);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0002 - General room information. Lots of stuff.
-- *
-- * Values I know are in here but I haven't attached
-- * them to any of the 'Unknown's:
-- * - Language (English)
-- *
-- */
--static int
--infoupdate(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- aim_rxcallback_t userfunc;
-- int ret = 0;
-- guint8 detaillevel = 0;
-- struct aim_chat_roominfo roominfo;
-- GSList *tlvlist;
-- guint16 maxmsglen, maxvisiblemsglen;
--
-- aim_chat_readroominfo(bs, &roominfo);
--
-- detaillevel = byte_stream_get8(bs);
--
-- if (detaillevel != 0x02) {
-- purple_debug_misc("oscar", "faim: chat_roomupdateinfo: detail level %d not supported\n", detaillevel);
-- return 1;
-- }
--
-- byte_stream_get16(bs); /* skip the TLV count */
--
-- /*
-- * Everything else are TLVs.
-- */
-- tlvlist = aim_tlvlist_read(bs);
--
-- /*
-- * Type 0x00d1: Maximum Message Length
-- */
-- maxmsglen = aim_tlv_get16(tlvlist, 0x00d1, 1);
--
-- /*
-- * Type 0x00da: Maximum visible message length
-- */
-- maxvisiblemsglen = aim_tlv_get16(tlvlist, 0x00da, 1);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) {
-- ret = userfunc(od, conn, frame, maxmsglen, maxvisiblemsglen);
-- }
--
-- g_free(roominfo.name);
--
-- aim_tlvlist_free(tlvlist);
--
-- return ret;
--}
--
--/* Subtypes 0x0003 and 0x0004 */
--static int
--userlistchange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- aim_userinfo_t *userinfo = NULL;
-- aim_rxcallback_t userfunc;
-- int curcount = 0, ret = 0;
--
-- while (byte_stream_bytes_left(bs)) {
-- curcount++;
-- userinfo = g_realloc(userinfo, curcount * sizeof(aim_userinfo_t));
-- aim_info_extract(od, bs, &userinfo[curcount-1]);
-- }
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, curcount, userinfo);
--
-- aim_info_free(userinfo);
-- g_free(userinfo);
--
-- return ret;
--}
--
--/*
-- * Subtype 0x0005 - Send a Chat Message.
-- *
-- * Possible flags:
-- * AIM_CHATFLAGS_NOREFLECT -- Unset the flag that requests messages
-- * should be sent to their sender.
-- * AIM_CHATFLAGS_AWAY -- Mark the message as an autoresponse
-- * (Note that WinAIM does not honor this,
-- * and displays the message as normal.)
-- *
-- * XXX convert this to use tlvchains
-- */
--int
--aim_chat_send_im(OscarData *od, FlapConnection *conn, guint16 flags, const gchar *msg, int msglen, const char *encoding, const char *language)
--{
-- int i;
-- ByteStream bs;
-- IcbmCookie *cookie;
-- aim_snacid_t snacid;
-- guint8 ckstr[8];
-- GSList *tlvlist = NULL, *inner_tlvlist = NULL;
--
-- if (!od || !conn || !msg || (msglen <= 0))
-- return 0;
--
-- byte_stream_new(&bs, 1142);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_CHAT, 0x0005, 0x0000, NULL, 0);
--
-- /*
-- * Cookie
-- *
-- * XXX mkcookie should generate the cookie and cache it in one
-- * operation to preserve uniqueness.
-- */
-- for (i = 0; i < 8; i++)
-- ckstr[i] = (guint8)rand();
--
-- cookie = aim_mkcookie(ckstr, AIM_COOKIETYPE_CHAT, NULL);
-- cookie->data = NULL; /* XXX store something useful here */
--
-- aim_cachecookie(od, cookie);
--
-- /* ICBM Header */
-- byte_stream_putraw(&bs, ckstr, 8); /* Cookie */
-- byte_stream_put16(&bs, 0x0003); /* Channel */
--
-- /*
-- * Type 1: Flag meaning this message is destined to the room.
-- */
-- aim_tlvlist_add_noval(&tlvlist, 0x0001);
--
-- /*
-- * Type 6: Reflect
-- */
-- if (!(flags & AIM_CHATFLAGS_NOREFLECT))
-- aim_tlvlist_add_noval(&tlvlist, 0x0006);
--
-- /*
-- * Type 7: Autoresponse
-- */
-- if (flags & AIM_CHATFLAGS_AWAY)
-- aim_tlvlist_add_noval(&tlvlist, 0x0007);
--
-- /*
-- * SubTLV: Type 1: Message
-- */
-- aim_tlvlist_add_raw(&inner_tlvlist, 0x0001, msglen, (guchar *)msg);
--
-- /*
-- * SubTLV: Type 2: Encoding
-- */
-- if (encoding != NULL)
-- aim_tlvlist_add_str(&inner_tlvlist, 0x0002, encoding);
--
-- /*
-- * SubTLV: Type 3: Language
-- */
-- if (language != NULL)
-- aim_tlvlist_add_str(&inner_tlvlist, 0x0003, language);
--
-- /*
-- * Type 5: Message block. Contains more TLVs.
-- *
-- * This could include other information... We just
-- * put in a message TLV however.
-- *
-- */
-- aim_tlvlist_add_frozentlvlist(&tlvlist, 0x0005, &inner_tlvlist);
--
-- aim_tlvlist_write(&bs, &tlvlist);
--
-- aim_tlvlist_free(inner_tlvlist);
-- aim_tlvlist_free(tlvlist);
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_CHAT, 0x0005, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0006
-- *
-- * We could probably include this in the normal ICBM parsing
-- * code as channel 0x0003, however, since only the start
-- * would be the same, we might as well do it here.
-- *
-- * General outline of this SNAC:
-- * snac
-- * cookie
-- * channel id
-- * tlvlist
-- * unknown
-- * source user info
-- * name
-- * evility
-- * userinfo tlvs
-- * online time
-- * etc
-- * message metatlv
-- * message tlv
-- * message string
-- * possibly others
-- *
-- */
--static int
--incomingim_ch3(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0, i;
-- aim_rxcallback_t userfunc;
-- aim_userinfo_t userinfo;
-- guint8 cookie[8];
-- guint16 channel;
-- GSList *tlvlist;
-- char *msg = NULL;
-- int len = 0;
-- char *encoding = NULL, *language = NULL;
-- IcbmCookie *ck;
-- aim_tlv_t *tlv;
-- ByteStream tbs;
--
-- memset(&userinfo, 0, sizeof(aim_userinfo_t));
--
-- /*
-- * Read ICBM Cookie.
-- */
-- for (i = 0; i < 8; i++)
-- cookie[i] = byte_stream_get8(bs);
--
-- if ((ck = aim_uncachecookie(od, cookie, AIM_COOKIETYPE_CHAT))) {
-- g_free(ck->data);
-- g_free(ck);
-- }
--
-- /*
-- * Channel ID
-- *
-- * Channel 0x0003 is used for chat messages.
-- *
-- */
-- channel = byte_stream_get16(bs);
--
-- if (channel != 0x0003) {
-- purple_debug_misc("oscar", "faim: chat_incoming: unknown channel! (0x%04x)\n", channel);
-- return 0;
-- }
--
-- /*
-- * Start parsing TLVs right away.
-- */
-- tlvlist = aim_tlvlist_read(bs);
--
-- /*
-- * Type 0x0003: Source User Information
-- */
-- tlv = aim_tlv_gettlv(tlvlist, 0x0003, 1);
-- if (tlv != NULL)
-- {
-- byte_stream_init(&tbs, tlv->value, tlv->length);
-- aim_info_extract(od, &tbs, &userinfo);
-- }
--
-- /*
-- * Type 0x0005: Message Block. Conains more TLVs.
-- */
-- tlv = aim_tlv_gettlv(tlvlist, 0x0005, 1);
-- if (tlv != NULL)
-- {
-- GSList *inner_tlvlist;
-- aim_tlv_t *inner_tlv;
--
-- byte_stream_init(&tbs, tlv->value, tlv->length);
-- inner_tlvlist = aim_tlvlist_read(&tbs);
--
-- /*
-- * Type 0x0001: Message.
-- */
-- inner_tlv = aim_tlv_gettlv(inner_tlvlist, 0x0001, 1);
-- if (inner_tlv != NULL)
-- {
-- len = inner_tlv->length;
-- msg = aim_tlv_getvalue_as_string(inner_tlv);
-- }
--
-- /*
-- * Type 0x0002: Encoding.
-- */
-- encoding = aim_tlv_getstr(inner_tlvlist, 0x0002, 1);
--
-- /*
-- * Type 0x0003: Language.
-- */
-- language = aim_tlv_getstr(inner_tlvlist, 0x0003, 1);
--
-- aim_tlvlist_free(inner_tlvlist);
-- }
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, &userinfo, len, msg, encoding, language);
--
-- aim_info_free(&userinfo);
-- g_free(msg);
-- g_free(encoding);
-- g_free(language);
-- aim_tlvlist_free(tlvlist);
--
-- return ret;
--}
--
--static int
--snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- if (snac->subtype == 0x0002)
-- return infoupdate(od, conn, mod, frame, snac, bs);
-- else if ((snac->subtype == 0x0003) || (snac->subtype == 0x0004))
-- return userlistchange(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x0006)
-- return incomingim_ch3(od, conn, mod, frame, snac, bs);
--
-- return 0;
--}
--
--int
--chat_modfirst(OscarData *od, aim_module_t *mod)
--{
-- mod->family = SNAC_FAMILY_CHAT;
-- mod->version = 0x0001;
-- mod->toolid = 0x0010;
-- mod->toolversion = 0x0629;
-- mod->flags = 0;
-- strncpy(mod->name, "chat", sizeof(mod->name));
-- mod->snachandler = snachandler;
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_chatnav.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_chatnav.c
---- pidgin-2.10.7/libpurple/protocols/oscar/family_chatnav.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_chatnav.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,448 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Family 0x000d - Handle ChatNav.
-- *
-- * The ChatNav(igation) service does various things to keep chat
-- * alive. It provides room information, room searching and creating,
-- * as well as giving users the right ("permission") to use chat.
-- *
-- */
--
--#include "oscar.h"
--
--static int
--error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_snac_t *snac2;
-- guint16 error, chatnav_error;
-- GSList *tlvlist;
--
-- snac2 = aim_remsnac(od, snac->id);
-- if (!snac2) {
-- purple_debug_warning("oscar", "chatnav error: received response to unknown request (%08x)\n", snac->id);
-- return 0;
-- }
--
-- if (snac2->family != SNAC_FAMILY_CHATNAV) {
-- purple_debug_warning("oscar", "chatnav error: received response that maps to corrupt request (fam=%04x)\n", snac2->family);
-- g_free(snac2->data);
-- g_free(snac2);
-- return 0;
-- }
--
-- /*
-- * We now know what the original SNAC subtype was.
-- */
-- if (snac2->type == 0x0008) /* create room */
-- {
-- error = byte_stream_get16(bs);
-- tlvlist = aim_tlvlist_read(bs);
-- chatnav_error = aim_tlv_get16(tlvlist, 0x0008, 1);
--
-- purple_debug_warning("oscar",
-- "Could not join room, error=0x%04hx, chatnav_error=0x%04hx\n",
-- error, chatnav_error);
-- purple_notify_error(od->gc, NULL, _("Could not join chat room"),
-- chatnav_error == 0x0033 ? _("Invalid chat room name") : _("Unknown error"));
--
-- ret = 1;
-- }
--
-- g_free(snac2->data);
-- g_free(snac2);
--
-- return ret;
--}
--
--/*
-- * Subtype 0x0002
-- *
-- * conn must be a chatnav connection!
-- *
-- */
--void aim_chatnav_reqrights(OscarData *od, FlapConnection *conn)
--{
-- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_CHATNAV, 0x0002);
--}
--
--/*
-- * Subtype 0x0008
-- */
--int aim_chatnav_createroom(OscarData *od, FlapConnection *conn, const char *name, guint16 exchange)
--{
-- static const char ck[] = {"create"};
-- static const char lang[] = {"en"};
-- static const char charset[] = {"us-ascii"};
-- ByteStream bs;
-- aim_snacid_t snacid;
-- GSList *tlvlist = NULL;
--
-- byte_stream_new(&bs, 1142);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_CHATNAV, 0x0008, 0x0000, NULL, 0);
--
-- /* exchange */
-- byte_stream_put16(&bs, exchange);
--
-- /*
-- * This looks to be a big hack. You'll note that this entire
-- * SNAC is just a room info structure, but the hard room name,
-- * here, is set to "create".
-- *
-- * Either this goes on the "list of questions concerning
-- * why-the-hell-did-you-do-that", or this value is completely
-- * ignored. Without experimental evidence, but a good knowledge of
-- * AOL style, I'm going to guess that it is the latter, and that
-- * the value of the room name in create requests is ignored.
-- */
-- byte_stream_put8(&bs, strlen(ck));
-- byte_stream_putstr(&bs, ck);
--
-- /*
-- * instance
-- *
-- * Setting this to 0xffff apparently assigns the last instance.
-- *
-- */
-- byte_stream_put16(&bs, 0xffff);
--
-- /* detail level */
-- byte_stream_put8(&bs, 0x01);
--
-- aim_tlvlist_add_str(&tlvlist, 0x00d3, name);
-- aim_tlvlist_add_str(&tlvlist, 0x00d6, charset);
-- aim_tlvlist_add_str(&tlvlist, 0x00d7, lang);
--
-- /* tlvcount */
-- byte_stream_put16(&bs, aim_tlvlist_count(tlvlist));
-- aim_tlvlist_write(&bs, &tlvlist);
--
-- aim_tlvlist_free(tlvlist);
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_CHATNAV, 0x0008, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--static int
--parseinfo_perms(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs, aim_snac_t *snac2)
--{
-- aim_rxcallback_t userfunc;
-- int ret = 0;
-- struct aim_chat_exchangeinfo *exchanges = NULL;
-- int curexchange;
-- aim_tlv_t *exchangetlv;
-- guint8 maxrooms = 0;
-- GSList *tlvlist, *innerlist;
--
-- tlvlist = aim_tlvlist_read(bs);
--
-- /*
-- * Type 0x0002: Maximum concurrent rooms.
-- */
-- if (aim_tlv_gettlv(tlvlist, 0x0002, 1))
-- maxrooms = aim_tlv_get8(tlvlist, 0x0002, 1);
--
-- /*
-- * Type 0x0003: Exchange information
-- *
-- * There can be any number of these, each one
-- * representing another exchange.
-- *
-- */
-- for (curexchange = 0; ((exchangetlv = aim_tlv_gettlv(tlvlist, 0x0003, curexchange+1))); ) {
-- ByteStream tbs;
--
-- byte_stream_init(&tbs, exchangetlv->value, exchangetlv->length);
--
-- curexchange++;
--
-- exchanges = g_realloc(exchanges, curexchange * sizeof(struct aim_chat_exchangeinfo));
--
-- /* exchange number */
-- exchanges[curexchange-1].number = byte_stream_get16(&tbs);
-- innerlist = aim_tlvlist_read(&tbs);
--
-- /*
-- * Type 0x0002: Unknown
-- */
-- if (aim_tlv_gettlv(innerlist, 0x0002, 1)) {
-- guint16 classperms;
--
-- classperms = aim_tlv_get16(innerlist, 0x0002, 1);
--
-- purple_debug_misc("oscar", "faim: class permissions %x\n", classperms);
-- }
--
-- /*
-- * Type 0x00c9: Flags
-- *
-- * 1 Evilable
-- * 2 Nav Only
-- * 4 Instancing Allowed
-- * 8 Occupant Peek Allowed
-- *
-- */
-- if (aim_tlv_gettlv(innerlist, 0x00c9, 1))
-- exchanges[curexchange-1].flags = aim_tlv_get16(innerlist, 0x00c9, 1);
--
-- /*
-- * Type 0x00d3: Exchange Description
-- */
-- if (aim_tlv_gettlv(innerlist, 0x00d3, 1))
-- exchanges[curexchange-1].name = aim_tlv_getstr(innerlist, 0x00d3, 1);
-- else
-- exchanges[curexchange-1].name = NULL;
--
-- /*
-- * Type 0x00d5: Creation Permissions
-- *
-- * 0 Creation not allowed
-- * 1 Room creation allowed
-- * 2 Exchange creation allowed
-- *
-- */
-- if (aim_tlv_gettlv(innerlist, 0x00d5, 1)) {
-- guint8 createperms;
--
-- createperms = aim_tlv_get8(innerlist, 0x00d5, 1);
-- }
--
-- /*
-- * Type 0x00d6: Character Set (First Time)
-- */
-- if (aim_tlv_gettlv(innerlist, 0x00d6, 1))
-- exchanges[curexchange-1].charset1 = aim_tlv_getstr(innerlist, 0x00d6, 1);
-- else
-- exchanges[curexchange-1].charset1 = NULL;
--
-- /*
-- * Type 0x00d7: Language (First Time)
-- */
-- if (aim_tlv_gettlv(innerlist, 0x00d7, 1))
-- exchanges[curexchange-1].lang1 = aim_tlv_getstr(innerlist, 0x00d7, 1);
-- else
-- exchanges[curexchange-1].lang1 = NULL;
--
-- /*
-- * Type 0x00d8: Character Set (Second Time)
-- */
-- if (aim_tlv_gettlv(innerlist, 0x00d8, 1))
-- exchanges[curexchange-1].charset2 = aim_tlv_getstr(innerlist, 0x00d8, 1);
-- else
-- exchanges[curexchange-1].charset2 = NULL;
--
-- /*
-- * Type 0x00d9: Language (Second Time)
-- */
-- if (aim_tlv_gettlv(innerlist, 0x00d9, 1))
-- exchanges[curexchange-1].lang2 = aim_tlv_getstr(innerlist, 0x00d9, 1);
-- else
-- exchanges[curexchange-1].lang2 = NULL;
--
-- aim_tlvlist_free(innerlist);
-- }
--
-- /*
-- * Call client.
-- */
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, snac2->type, maxrooms, curexchange, exchanges);
--
-- for (curexchange--; curexchange >= 0; curexchange--) {
-- g_free(exchanges[curexchange].name);
-- g_free(exchanges[curexchange].charset1);
-- g_free(exchanges[curexchange].lang1);
-- g_free(exchanges[curexchange].charset2);
-- g_free(exchanges[curexchange].lang2);
-- }
-- g_free(exchanges);
-- aim_tlvlist_free(tlvlist);
--
-- return ret;
--}
--
--static int
--parseinfo_create(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs, aim_snac_t *snac2)
--{
-- aim_rxcallback_t userfunc;
-- GSList *tlvlist, *innerlist;
-- char *ck = NULL, *fqcn = NULL, *name = NULL;
-- guint16 exchange = 0, instance = 0, unknown = 0, flags = 0, maxmsglen = 0, maxoccupancy = 0;
-- guint32 createtime = 0;
-- guint8 createperms = 0, detaillevel;
-- int cklen;
-- aim_tlv_t *bigblock;
-- int ret = 0;
-- ByteStream bbbs;
--
-- tlvlist = aim_tlvlist_read(bs);
--
-- if (!(bigblock = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {
-- purple_debug_misc("oscar", "no bigblock in top tlv in create room response\n");
-- aim_tlvlist_free(tlvlist);
-- return 0;
-- }
--
-- byte_stream_init(&bbbs, bigblock->value, bigblock->length);
--
-- exchange = byte_stream_get16(&bbbs);
-- cklen = byte_stream_get8(&bbbs);
-- ck = byte_stream_getstr(&bbbs, cklen);
-- instance = byte_stream_get16(&bbbs);
-- detaillevel = byte_stream_get8(&bbbs);
--
-- if (detaillevel != 0x02) {
-- purple_debug_misc("oscar", "unknown detaillevel in create room response (0x%02x)\n", detaillevel);
-- aim_tlvlist_free(tlvlist);
-- g_free(ck);
-- return 0;
-- }
--
-- unknown = byte_stream_get16(&bbbs);
--
-- innerlist = aim_tlvlist_read(&bbbs);
--
-- if (aim_tlv_gettlv(innerlist, 0x006a, 1))
-- fqcn = aim_tlv_getstr(innerlist, 0x006a, 1);
--
-- if (aim_tlv_gettlv(innerlist, 0x00c9, 1))
-- flags = aim_tlv_get16(innerlist, 0x00c9, 1);
--
-- if (aim_tlv_gettlv(innerlist, 0x00ca, 1))
-- createtime = aim_tlv_get32(innerlist, 0x00ca, 1);
--
-- if (aim_tlv_gettlv(innerlist, 0x00d1, 1))
-- maxmsglen = aim_tlv_get16(innerlist, 0x00d1, 1);
--
-- if (aim_tlv_gettlv(innerlist, 0x00d2, 1))
-- maxoccupancy = aim_tlv_get16(innerlist, 0x00d2, 1);
--
-- if (aim_tlv_gettlv(innerlist, 0x00d3, 1))
-- name = aim_tlv_getstr(innerlist, 0x00d3, 1);
--
-- if (aim_tlv_gettlv(innerlist, 0x00d5, 1))
-- createperms = aim_tlv_get8(innerlist, 0x00d5, 1);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) {
-- ret = userfunc(od, conn, frame, snac2->type, fqcn, instance, exchange, flags, createtime, maxmsglen, maxoccupancy, createperms, unknown, name, ck);
-- }
--
-- g_free(ck);
-- g_free(name);
-- g_free(fqcn);
-- aim_tlvlist_free(innerlist);
-- aim_tlvlist_free(tlvlist);
--
-- return ret;
--}
--
--/*
-- * Subtype 0x0009
-- *
-- * Since multiple things can trigger this callback, we must lookup the
-- * snacid to determine the original snac subtype that was called.
-- *
-- * XXX This isn't really how this works. But this is: Every d/9 response
-- * has a 16bit value at the beginning. That matches to:
-- * Short Desc = 1
-- * Full Desc = 2
-- * Instance Info = 4
-- * Nav Short Desc = 8
-- * Nav Instance Info = 16
-- * And then everything is really asynchronous. There is no specific
-- * attachment of a response to a create room request, for example. Creating
-- * the room yields no different a response than requesting the room's info.
-- *
-- */
--static int
--parseinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- aim_snac_t *snac2;
-- int ret = 0;
--
-- if (!(snac2 = aim_remsnac(od, snac->id))) {
-- purple_debug_misc("oscar", "faim: chatnav_parse_info: received response to unknown request! (%08x)\n", snac->id);
-- return 0;
-- }
--
-- if (snac2->family != SNAC_FAMILY_CHATNAV) {
-- purple_debug_misc("oscar", "faim: chatnav_parse_info: received response that maps to corrupt request! (fam=%04x)\n", snac2->family);
-- g_free(snac2->data);
-- g_free(snac2);
-- return 0;
-- }
--
-- /*
-- * We now know what the original SNAC subtype was.
-- */
-- if (snac2->type == 0x0002) /* request chat rights */
-- ret = parseinfo_perms(od, conn, mod, frame, snac, bs, snac2);
-- else if (snac2->type == 0x0003) /* request exchange info */
-- purple_debug_misc("oscar", "chatnav_parse_info: response to exchange info\n");
-- else if (snac2->type == 0x0004) /* request room info */
-- purple_debug_misc("oscar", "chatnav_parse_info: response to room info\n");
-- else if (snac2->type == 0x0005) /* request more room info */
-- purple_debug_misc("oscar", "chatnav_parse_info: response to more room info\n");
-- else if (snac2->type == 0x0006) /* request occupant list */
-- purple_debug_misc("oscar", "chatnav_parse_info: response to occupant info\n");
-- else if (snac2->type == 0x0007) /* search for a room */
-- purple_debug_misc("oscar", "chatnav_parse_info: search results\n");
-- else if (snac2->type == 0x0008) /* create room */
-- ret = parseinfo_create(od, conn, mod, frame, snac, bs, snac2);
-- else
-- purple_debug_misc("oscar", "chatnav_parse_info: unknown request subtype (%04x)\n", snac2->type);
--
-- if (snac2)
-- g_free(snac2->data);
-- g_free(snac2);
--
-- return ret;
--}
--
--static int
--snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- if (snac->subtype == 0x0001)
-- return error(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x0009)
-- return parseinfo(od, conn, mod, frame, snac, bs);
--
-- return 0;
--}
--
--int
--chatnav_modfirst(OscarData *od, aim_module_t *mod)
--{
-- mod->family = SNAC_FAMILY_CHATNAV;
-- mod->version = 0x0001;
-- mod->toolid = 0x0010;
-- mod->toolversion = 0x0629;
-- mod->flags = 0;
-- strncpy(mod->name, "chatnav", sizeof(mod->name));
-- mod->snachandler = snachandler;
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_feedbag.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_feedbag.c
---- pidgin-2.10.7/libpurple/protocols/oscar/family_feedbag.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_feedbag.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1981 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Family 0x0013 - Server-Side/Stored Information.
-- *
-- * Relatively new facility that allows certain types of information, such as
-- * a user's buddy list, permit/deny list, and permit/deny preferences, to be
-- * stored on the server, so that they can be accessed from any client.
-- *
-- * We keep 2 copies of SSI data:
-- * 1) An exact copy of what is stored on the AIM servers.
-- * 2) A local copy that we make changes to, and then send diffs
-- * between this and the exact copy to keep them in sync.
-- *
-- * All the "aim_ssi_itemlist_bleh" functions near the top just modify the list
-- * that is given to them (i.e. they don't send SNACs).
-- *
-- * The SNAC sending and receiving functions are lower down in the file, and
-- * they're simpler. They are in the order of the subtypes they deal with,
-- * starting with the request rights function (subtype 0x0002), then parse
-- * rights (subtype 0x0003), then--well, you get the idea.
-- *
-- * This is entirely too complicated.
-- * You don't know the half of it.
-- *
-- */
--
--#include "oscar.h"
--#include "debug.h"
--
--static int aim_ssi_addmoddel(OscarData *od);
--
--/**
-- * List types based on http://dev.aol.com/aim/oscar/#FEEDBAG (archive.org)
-- * and http://iserverd.khstu.ru/oscar/ssi_item.html
-- *
-- * @param type The type of a list item as integer number, as provided by an aim_ssi_item struct.
-- * @return Returns the name of the item type as a character string.
-- */
--static const gchar*
--aim_ssi_type_to_string(guint16 type)
--{
-- struct TypeStringPair
-- {
-- guint16 type;
-- const gchar *string;
-- };
-- static const struct TypeStringPair type_strings[] = {
-- { 0x0000, "Buddy" },
-- { 0x0001, "Group" },
-- { 0x0002, "Permit/Visible" },
-- { 0x0003, "Deny/Invisible" },
-- { 0x0004, "PDInfo" },
-- { 0x0005, "PresencePrefs" },
-- { 0x0006, "Non-Buddy Info" },
-- { 0x0009, "ClientPrefs" },
-- { 0x000e, "ICQDeny/Ignore" },
-- { 0x0014, "Buddy Icon" },
-- { 0x0015, "Recent Buddies" },
-- { 0x0019, "Non-Buddy" },
-- { 0x001d, "Vanity Info" },
-- { 0x0020, "ICQ-MDir" },
-- { 0x0029, "Facebook" },
-- };
-- int i;
-- for (i = 0; i < G_N_ELEMENTS(type_strings); i++) {
-- if (type_strings[i].type == type) {
-- return type_strings[i].string;
-- }
-- }
-- return "unknown";
--}
--
--/** For debug log output: Appends a line containing information about a given list item to a string.
-- *
-- * @param str String to which the line will be appended.
-- * @param prefix A string which will be prepended to the line.
-- * @param item List item from which information is extracted.
-- */
--static void
--aim_ssi_item_debug_append(GString *str, char *prefix, struct aim_ssi_item *item)
--{
-- g_string_append_printf(str,
-- "%s gid=0x%04hx, bid=0x%04hx, list_type=0x%04hx [%s], name=%s.\n",
-- prefix, item->gid, item->bid, item->type, aim_ssi_type_to_string(item->type),
-- item->name ? item->name : "(null)");
--}
--
--/**
-- * Locally rebuild the 0x00c8 TLV in the additional data of the given group.
-- *
-- * @param list A pointer to a pointer to the current list of items.
-- * @param name A null terminated string containing the group name, or NULL
-- * if you want to modify the master group.
-- * @return Return a pointer to the modified item.
-- */
--static void
--aim_ssi_itemlist_rebuildgroup(struct aim_ssi_item *list, const char *name)
--{
-- int newlen;
-- struct aim_ssi_item *cur, *group;
--
-- /* Find the group */
-- if (!(group = aim_ssi_itemlist_finditem(list, name, NULL, AIM_SSI_TYPE_GROUP)))
-- return;
--
-- /* Find the length for the new additional data */
-- newlen = 0;
-- if (group->gid == 0x0000) {
-- for (cur=list; cur; cur=cur->next)
-- if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000))
-- newlen += 2;
-- } else {
-- for (cur=list; cur; cur=cur->next)
-- if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))
-- newlen += 2;
-- }
--
-- /* Build the new TLV list */
-- if (newlen > 0) {
-- guint8 *newdata;
--
-- newdata = (guint8 *)g_malloc((newlen)*sizeof(guint8));
-- newlen = 0;
-- if (group->gid == 0x0000) {
-- for (cur=list; cur; cur=cur->next)
-- if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000))
-- newlen += aimutil_put16(newdata+newlen, cur->gid);
-- } else {
-- for (cur=list; cur; cur=cur->next)
-- if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))
-- newlen += aimutil_put16(newdata+newlen, cur->bid);
-- }
-- aim_tlvlist_replace_raw(&group->data, 0x00c8, newlen, newdata);
--
-- g_free(newdata);
-- }
--}
--
--/**
-- * Locally add a new item to the given item list.
-- *
-- * @param list A pointer to a pointer to the current list of items.
-- * @param name A null terminated string of the name of the new item, or NULL if the
-- * item should have no name.
-- * @param gid The group ID# you want the new item to have, or 0xFFFF if we should pick something.
-- * @param bid The buddy ID# you want the new item to have, or 0xFFFF if we should pick something.
-- * @param type The type of the item, 0x0000 for a contact, 0x0001 for a group, etc.
-- * @param data The additional data for the new item.
-- * @return A pointer to the newly created item.
-- */
--static struct aim_ssi_item *aim_ssi_itemlist_add(struct aim_ssi_item **list, const char *name, guint16 gid, guint16 bid, guint16 type, GSList *data)
--{
-- gboolean exists;
-- struct aim_ssi_item *cur, *new;
--
-- new = g_new(struct aim_ssi_item, 1);
--
-- /* Set the name */
-- new->name = g_strdup(name);
--
-- /* Set the group ID# and buddy ID# */
-- new->gid = gid;
-- new->bid = bid;
-- if (type == AIM_SSI_TYPE_GROUP) {
-- if ((new->gid == 0xFFFF) && name) {
-- do {
-- new->gid += 0x0001;
-- exists = FALSE;
-- for (cur = *list; cur != NULL; cur = cur->next)
-- if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid == new->gid)) {
-- exists = TRUE;
-- break;
-- }
-- } while (exists);
-- }
-- } else if (new->gid == 0x0000) {
-- /*
-- * This is weird, but apparently items in the root group can't
-- * have a buddy ID equal to any group ID. You'll get error
-- * 0x0003 when trying to add, which is "item already exists"
-- */
-- if (new->bid == 0xFFFF) {
-- do {
-- new->bid += 0x0001;
-- exists = FALSE;
-- for (cur = *list; cur != NULL; cur = cur->next)
-- if (cur->bid == new->bid || cur->gid == new->bid) {
-- exists = TRUE;
-- break;
-- }
-- } while (exists);
-- }
-- } else {
-- if (new->bid == 0xFFFF) {
-- do {
-- new->bid += 0x0001;
-- exists = FALSE;
-- for (cur = *list; cur != NULL; cur = cur->next)
-- if (cur->bid == new->bid && cur->gid == new->gid) {
-- exists = TRUE;
-- break;
-- }
-- } while (exists);
-- }
-- }
--
-- /* Set the type */
-- new->type = type;
--
-- /* Set the TLV list */
-- new->data = aim_tlvlist_copy(data);
--
-- /* Add the item to the list in the correct numerical position. Fancy, eh? */
-- if (*list) {
-- if ((new->gid < (*list)->gid) || ((new->gid == (*list)->gid) && (new->bid < (*list)->bid))) {
-- new->next = *list;
-- *list = new;
-- } else {
-- struct aim_ssi_item *prev;
-- for ((prev=*list, cur=(*list)->next); (cur && ((new->gid > cur->gid) || ((new->gid == cur->gid) && (new->bid > cur->bid)))); prev=cur, cur=cur->next);
-- new->next = prev->next;
-- prev->next = new;
-- }
-- } else {
-- new->next = *list;
-- *list = new;
-- }
--
-- return new;
--}
--
--/**
-- * Locally delete an item from the given item list.
-- *
-- * @param list A pointer to a pointer to the current list of items.
-- * @param del A pointer to the item you want to remove from the list.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--static int aim_ssi_itemlist_del(struct aim_ssi_item **list, struct aim_ssi_item *del)
--{
-- if (!(*list) || !del)
-- return -EINVAL;
--
-- /* Remove the item from the list */
-- if (*list == del) {
-- *list = (*list)->next;
-- } else {
-- struct aim_ssi_item *cur;
-- for (cur=*list; (cur->next && (cur->next!=del)); cur=cur->next);
-- if (cur->next)
-- cur->next = del->next;
-- }
--
-- /* Free the removed item */
-- g_free(del->name);
-- aim_tlvlist_free(del->data);
-- g_free(del);
--
-- return 0;
--}
--
--/**
-- * Compare two items to see if they have the same data.
-- *
-- * @param cur1 A pointer to a pointer to the first item.
-- * @param cur2 A pointer to a pointer to the second item.
-- * @return Return 0 if no differences, or a number if there are differences.
-- */
--static int aim_ssi_itemlist_cmp(struct aim_ssi_item *cur1, struct aim_ssi_item *cur2)
--{
-- if (!cur1 || !cur2)
-- return 1;
--
-- if (cur1->data && !cur2->data)
-- return 2;
--
-- if (!cur1->data && cur2->data)
-- return 3;
--
-- if ((cur1->data && cur2->data) && (aim_tlvlist_cmp(cur1->data, cur2->data)))
-- return 4;
--
-- if (cur1->name && !cur2->name)
-- return 5;
--
-- if (!cur1->name && cur2->name)
-- return 6;
--
-- if (cur1->name && cur2->name && oscar_util_name_compare(cur1->name, cur2->name))
-- return 7;
--
-- if (cur1->gid != cur2->gid)
-- return 8;
--
-- if (cur1->bid != cur2->bid)
-- return 9;
--
-- if (cur1->type != cur2->type)
-- return 10;
--
-- return 0;
--}
--
--static gboolean aim_ssi_itemlist_valid(struct aim_ssi_item *list, struct aim_ssi_item *item)
--{
-- struct aim_ssi_item *cur;
-- for (cur=list; cur; cur=cur->next)
-- if (cur == item)
-- return TRUE;
-- return FALSE;
--}
--
--/**
-- * Locally find an item given a group ID# and a buddy ID#.
-- *
-- * @param list A pointer to the current list of items.
-- * @param gid The group ID# of the desired item.
-- * @param bid The buddy ID# of the desired item.
-- * @return Return a pointer to the item if found, else return NULL;
-- */
--struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid)
--{
-- struct aim_ssi_item *cur;
-- for (cur=list; cur; cur=cur->next)
-- if ((cur->gid == gid) && (cur->bid == bid))
-- return cur;
-- return NULL;
--}
--
--/**
-- * Locally find an item given a group name, buddy name, and type. If group name
-- * and buddy name are null, then just return the first item of the given type.
-- *
-- * @param list A pointer to the current list of items.
-- * @param gn The group name of the desired item.
-- * @param bn The buddy name of the desired item.
-- * @param type The type of the desired item.
-- * @return Return a pointer to the item if found, else return NULL.
-- */
--struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *bn, guint16 type)
--{
-- struct aim_ssi_item *cur;
-- if (!list)
-- return NULL;
--
-- if (gn && bn) { /* For finding buddies in groups */
-- for (cur=list; cur; cur=cur->next)
-- if ((cur->type == type) && (cur->name) && !(oscar_util_name_compare(cur->name, bn))) {
-- struct aim_ssi_item *curg;
-- for (curg=list; curg; curg=curg->next)
-- if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid) && (curg->name) && !(oscar_util_name_compare(curg->name, gn)))
-- return cur;
-- }
--
-- } else if (gn) { /* For finding groups */
-- for (cur=list; cur; cur=cur->next) {
-- if ((cur->type == type) && (cur->bid == 0x0000) && (cur->name) && !(oscar_util_name_compare(cur->name, gn))) {
-- return cur;
-- }
-- }
--
-- } else if (bn) { /* For finding permits, denies, and ignores */
-- for (cur=list; cur; cur=cur->next) {
-- if ((cur->type == type) && (cur->name) && !(oscar_util_name_compare(cur->name, bn))) {
-- return cur;
-- }
-- }
--
-- /* For stuff without names--permit deny setting, visibility mask, etc. */
-- } else for (cur=list; cur; cur=cur->next) {
-- if ((cur->type == type) && (!cur->name))
-- return cur;
-- }
--
-- return NULL;
--}
--
--/**
-- * Check if the given buddy exists in any group in the buddy list.
-- *
-- * @param list A pointer to the current list of items.
-- * @param bn The group name of the desired item.
-- * @return Return a pointer to the name of the item if found, else return NULL;
-- */
--struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *bn)
--{
-- if (!bn)
-- return NULL;
-- return aim_ssi_itemlist_finditem(list, NULL, bn, AIM_SSI_TYPE_BUDDY);
--}
--
--/**
-- * Locally find the parent item of the given buddy name.
-- *
-- * @param list A pointer to the current list of items.
-- * @param bn The buddy name of the desired item.
-- * @return Return a pointer to the name of the item if found, else return NULL;
-- */
--char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *bn)
--{
-- struct aim_ssi_item *cur, *curg;
-- if (!list || !bn)
-- return NULL;
-- if (!(cur = aim_ssi_itemlist_exists(list, bn)))
-- return NULL;
-- if (!(curg = aim_ssi_itemlist_find(list, cur->gid, 0x0000)))
-- return NULL;
-- return curg->name;
--}
--
--/**
-- * Locally find the permit/deny setting item, and return the setting.
-- *
-- * @param list A pointer to the current list of items.
-- * @return Return the current SSI permit deny setting, or 0 if no setting was found.
-- */
--int aim_ssi_getpermdeny(struct aim_ssi_item *list)
--{
-- struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PDINFO);
-- if (cur) {
-- aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x00ca, 1);
-- if (tlv && tlv->value)
-- return aimutil_get8(tlv->value);
-- }
-- return 0;
--}
--
--/**
-- * Locally find the presence flag item, and return the setting. The returned setting is a
-- * bitmask of the preferences. See the AIM_SSI_PRESENCE_FLAG_* #defines in oscar.h.
-- *
-- * @param list A pointer to the current list of items.
-- * @return Return the current set of preferences.
-- */
--guint32 aim_ssi_getpresence(struct aim_ssi_item *list)
--{
-- struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS);
-- if (cur) {
-- aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x00c9, 1);
-- if (tlv && tlv->length)
-- return aimutil_get32(tlv->value);
-- }
-- return 0xFFFFFFFF;
--}
--
--/**
-- * Locally find the alias of the given buddy.
-- *
-- * @param list A pointer to the current list of items.
-- * @param gn The group of the buddy.
-- * @param bn The name of the buddy.
-- * @return A pointer to a NULL terminated string that is the buddy's
-- * alias, or NULL if the buddy has no alias. You should free
-- * this returned value!
-- */
--char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *bn)
--{
-- struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY);
-- if (cur) {
-- aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x0131, 1);
-- if (tlv && tlv->length)
-- return g_strndup((const gchar *)tlv->value, tlv->length);
-- }
-- return NULL;
--}
--
--/**
-- * Locally find the comment of the given buddy.
-- *
-- * @param list A pointer to the current list of items.
-- * @param gn The group of the buddy.
-- * @param bn The name of the buddy.
-- * @return A pointer to a NULL terminated string that is the buddy's
-- * comment, or NULL if the buddy has no comment. You should free
-- * this returned value!
-- */
--char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *bn)
--{
-- struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY);
-- if (cur) {
-- aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x013c, 1);
-- if (tlv && tlv->length) {
-- return g_strndup((const gchar *)tlv->value, tlv->length);
-- }
-- }
-- return NULL;
--}
--
--/**
-- * Locally find if you are waiting for authorization for a buddy.
-- *
-- * @param list A pointer to the current list of items.
-- * @param gn The group of the buddy.
-- * @param bn The name of the buddy.
-- * @return 1 if you are waiting for authorization; 0 if you are not
-- */
--gboolean aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *bn)
--{
-- struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY);
-- if (cur) {
-- if (aim_tlv_gettlv(cur->data, 0x0066, 1))
-- return TRUE;
-- }
-- return FALSE;
--}
--
--/**
-- * If there are changes, then create temporary items and
-- * call addmoddel.
-- *
-- * @param od The oscar session.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--static int aim_ssi_sync(OscarData *od)
--{
-- struct aim_ssi_item *cur1, *cur2;
-- struct aim_ssi_tmp *cur, *new;
-- int n = 0;
-- GString *debugstr = g_string_new("");
--
-- /*
-- * The variable "n" is used to limit the number of addmoddel's that
-- * are performed in a single SNAC. It will hopefully keep the size
-- * of the SNAC below the maximum SNAC size.
-- */
--
-- if (!od)
-- return -EINVAL;
--
-- /* If we're waiting for an ack, we shouldn't do anything else */
-- if (od->ssi.waiting_for_ack)
-- return 0;
--
-- /*
-- * Compare the 2 lists and create an aim_ssi_tmp for each difference.
-- * We should only send either additions, modifications, or deletions
-- * before waiting for an acknowledgement. So first do deletions, then
-- * additions, then modifications. Also, both the official and the local
-- * list should be in ascending numerical order for the group ID#s and the
-- * buddy ID#s, which makes things more efficient. I think.
-- */
--
-- /* Deletions */
-- if (!od->ssi.pending) {
-- for (cur1=od->ssi.official; cur1 && (n < 15); cur1=cur1->next) {
-- if (!aim_ssi_itemlist_find(od->ssi.local, cur1->gid, cur1->bid)) {
-- n++;
-- new = g_new(struct aim_ssi_tmp, 1);
-- new->action = SNAC_SUBTYPE_FEEDBAG_DEL;
-- new->ack = 0xffff;
-- new->name = NULL;
-- new->item = cur1;
-- new->next = NULL;
-- if (od->ssi.pending) {
-- for (cur=od->ssi.pending; cur->next; cur=cur->next);
-- cur->next = new;
-- } else
-- od->ssi.pending = new;
-- aim_ssi_item_debug_append(debugstr, "Deleting item ", cur1);
-- }
-- }
-- }
--
-- /* Additions */
-- if (!od->ssi.pending) {
-- for (cur1=od->ssi.local; cur1 && (n < 15); cur1=cur1->next) {
-- if (!aim_ssi_itemlist_find(od->ssi.official, cur1->gid, cur1->bid)) {
-- n++;
-- new = g_new(struct aim_ssi_tmp, 1);
-- new->action = SNAC_SUBTYPE_FEEDBAG_ADD;
-- new->ack = 0xffff;
-- new->name = NULL;
-- new->item = cur1;
-- new->next = NULL;
-- if (od->ssi.pending) {
-- for (cur=od->ssi.pending; cur->next; cur=cur->next);
-- cur->next = new;
-- } else
-- od->ssi.pending = new;
-- aim_ssi_item_debug_append(debugstr, "Adding item ", cur1);
-- }
-- }
-- }
--
-- /* Modifications */
-- if (!od->ssi.pending) {
-- for (cur1=od->ssi.local; cur1 && (n < 15); cur1=cur1->next) {
-- cur2 = aim_ssi_itemlist_find(od->ssi.official, cur1->gid, cur1->bid);
-- if (cur2 && (aim_ssi_itemlist_cmp(cur1, cur2))) {
-- n++;
-- new = g_new(struct aim_ssi_tmp, 1);
-- new->action = SNAC_SUBTYPE_FEEDBAG_MOD;
-- new->ack = 0xffff;
-- new->name = NULL;
-- new->item = cur1;
-- new->next = NULL;
-- if (od->ssi.pending) {
-- for (cur=od->ssi.pending; cur->next; cur=cur->next);
-- cur->next = new;
-- } else
-- od->ssi.pending = new;
-- aim_ssi_item_debug_append(debugstr, "Modifying item ", cur1);
-- }
-- }
-- }
-- if (debugstr->len > 0) {
-- purple_debug_info("oscar", "%s", debugstr->str);
-- if (purple_debug_is_verbose()) {
-- g_string_truncate(debugstr, 0);
-- for (cur1 = od->ssi.local; cur1; cur1 = cur1->next)
-- aim_ssi_item_debug_append(debugstr, "\t", cur1);
-- purple_debug_misc("oscar", "Dumping item list of account %s:\n%s",
-- purple_connection_get_account(od->gc)->username, debugstr->str);
-- }
-- }
-- g_string_free(debugstr, TRUE);
--
-- /* We're out of stuff to do, so tell the AIM servers we're done and exit */
-- if (!od->ssi.pending) {
-- if (od->ssi.in_transaction) {
-- aim_ssi_modend(od);
-- od->ssi.in_transaction = FALSE;
-- }
-- return 0;
-- }
--
-- /* If this is the first in a series of add/mod/del
-- * requests then send the "begin transaction" message. */
-- if (!od->ssi.in_transaction)
-- {
-- aim_ssi_modbegin(od);
-- od->ssi.in_transaction = TRUE;
-- }
--
-- /* Make sure we don't send anything else between now
-- * and when we receive the ack for the following operation */
-- od->ssi.waiting_for_ack = TRUE;
--
-- /* Now go mail off our data and wait 4 to 6 weeks */
-- return aim_ssi_addmoddel(od);;
--}
--
--/**
-- * Free all SSI data.
-- *
-- * This doesn't remove it from the server, that's different.
-- *
-- * @param od The oscar odion.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--static void
--aim_ssi_freelist(OscarData *od)
--{
-- struct aim_ssi_item *cur, *del;
-- struct aim_ssi_tmp *curtmp, *deltmp;
--
-- cur = od->ssi.official;
-- while (cur) {
-- del = cur;
-- cur = cur->next;
-- g_free(del->name);
-- aim_tlvlist_free(del->data);
-- g_free(del);
-- }
--
-- cur = od->ssi.local;
-- while (cur) {
-- del = cur;
-- cur = cur->next;
-- g_free(del->name);
-- aim_tlvlist_free(del->data);
-- g_free(del);
-- }
--
-- curtmp = od->ssi.pending;
-- while (curtmp) {
-- deltmp = curtmp;
-- curtmp = curtmp->next;
-- g_free(deltmp);
-- }
--
-- od->ssi.numitems = 0;
-- od->ssi.official = NULL;
-- od->ssi.local = NULL;
-- od->ssi.pending = NULL;
-- od->ssi.timestamp = (time_t)0;
--}
--
--/**
-- * This "cleans" the ssi list. It does the following:
-- * 1) Makes sure all buddies, permits, and denies have names.
-- * 2) Makes sure that all buddies are in a group that exist.
-- * 3) Deletes any empty groups
-- *
-- * @param od The oscar odion.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int aim_ssi_cleanlist(OscarData *od)
--{
-- struct aim_ssi_item *cur, *next;
--
-- if (!od)
-- return -EINVAL;
--
-- /* Delete any buddies, permits, or denies with empty names. */
-- /* If there are any buddies directly in the master group, add them to a real group. */
-- /* DESTROY any buddies that are directly in the master group. */
-- /* Do the same for buddies that are in a non-existant group. */
-- /* This will kind of mess up if you hit the item limit, but this function isn't too critical */
-- cur = od->ssi.local;
-- while (cur) {
-- next = cur->next;
-- if (!cur->name) {
-- if (cur->type == AIM_SSI_TYPE_BUDDY)
-- aim_ssi_delbuddy(od, NULL, NULL);
-- else if (cur->type == AIM_SSI_TYPE_PERMIT || cur->type == AIM_SSI_TYPE_DENY || cur->type == AIM_SSI_TYPE_ICQDENY)
-- aim_ssi_del_from_private_list(od, NULL, cur->type);
-- } else if ((cur->type == AIM_SSI_TYPE_BUDDY) && ((cur->gid == 0x0000) || (!aim_ssi_itemlist_find(od->ssi.local, cur->gid, 0x0000)))) {
-- char *alias = aim_ssi_getalias(od->ssi.local, NULL, cur->name);
-- aim_ssi_addbuddy(od, cur->name, "orphans", NULL, alias, NULL, NULL, FALSE);
-- aim_ssi_delbuddy(od, cur->name, NULL);
-- g_free(alias);
-- }
-- cur = next;
-- }
--
-- /* Make sure there aren't any duplicate buddies in a group, or duplicate permits or denies */
-- cur = od->ssi.local;
-- while (cur) {
-- if ((cur->type == AIM_SSI_TYPE_BUDDY) || (cur->type == AIM_SSI_TYPE_PERMIT) || (cur->type == AIM_SSI_TYPE_DENY))
-- {
-- struct aim_ssi_item *cur2, *next2;
-- cur2 = cur->next;
-- while (cur2) {
-- next2 = cur2->next;
-- if ((cur->type == cur2->type) && (cur->gid == cur2->gid) && (cur->name != NULL) && (cur2->name != NULL) && (!oscar_util_name_compare(cur->name, cur2->name))) {
-- aim_ssi_itemlist_del(&od->ssi.local, cur2);
-- }
-- cur2 = next2;
-- }
-- }
-- cur = cur->next;
-- }
--
-- /* If we've made any changes then sync our list with the server's */
-- return aim_ssi_sync(od);
--}
--
--/**
-- * Add a buddy to the list.
-- *
-- * @param od The oscar odion.
-- * @param name The name of the item.
-- * @param group The group of the item.
-- * @param data A TLV list to use as the additional data for this item.
-- * @param alias The alias/nickname of the item, or NULL.
-- * @param comment The buddy comment for the item, or NULL.
-- * @param smsnum The locally assigned SMS number, or NULL.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int aim_ssi_addbuddy(OscarData *od, const char *name, const char *group, GSList *data, const char *alias, const char *comment, const char *smsnum, gboolean needauth)
--{
-- struct aim_ssi_item *parent;
--
-- if (!od || !name || !group)
-- return -EINVAL;
--
-- /* Find the parent */
-- if (!(parent = aim_ssi_itemlist_finditem(od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP))) {
-- /* Find the parent's parent (the master group) */
-- if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
-- aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
--
-- /* Add the parent */
-- parent = aim_ssi_itemlist_add(&od->ssi.local, group, 0xFFFF, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
--
-- /* Modify the parent's parent (the master group) */
-- aim_ssi_itemlist_rebuildgroup(od->ssi.local, NULL);
-- }
--
-- /* Create a TLV list for the new buddy */
-- if (needauth)
-- aim_tlvlist_add_noval(&data, 0x0066);
-- if (alias != NULL)
-- aim_tlvlist_add_str(&data, 0x0131, alias);
-- if (smsnum != NULL)
-- aim_tlvlist_add_str(&data, 0x013a, smsnum);
-- if (comment != NULL)
-- aim_tlvlist_add_str(&data, 0x013c, comment);
--
-- /* Add that bad boy */
-- aim_ssi_itemlist_add(&od->ssi.local, name, parent->gid, 0xFFFF, AIM_SSI_TYPE_BUDDY, data);
-- aim_tlvlist_free(data);
--
-- /* Modify the parent group */
-- aim_ssi_itemlist_rebuildgroup(od->ssi.local, group);
--
-- /* Sync our local list with the server list */
-- return aim_ssi_sync(od);
--}
--
--int
--aim_ssi_add_to_private_list(OscarData *od, const char* name, guint16 list_type)
--{
-- if (!od || !name || !od->ssi.received_data)
-- return -EINVAL;
--
-- if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
-- aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
--
-- aim_ssi_itemlist_add(&od->ssi.local, name, 0x0000, 0xFFFF, list_type, NULL);
-- return aim_ssi_sync(od);
--}
--
--int
--aim_ssi_del_from_private_list(OscarData* od, const char* name, guint16 list_type)
--{
-- struct aim_ssi_item *del;
--
-- if (!od)
-- return -EINVAL;
--
-- if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, NULL, name, list_type)))
-- return -EINVAL;
--
-- aim_ssi_itemlist_del(&od->ssi.local, del);
-- return aim_ssi_sync(od);
--}
--
--/**
-- * Deletes a buddy from the list.
-- *
-- * @param od The oscar odion.
-- * @param name The name of the item, or NULL.
-- * @param group The group of the item, or NULL.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int aim_ssi_delbuddy(OscarData *od, const char *name, const char *group)
--{
-- struct aim_ssi_item *del;
--
-- if (!od)
-- return -EINVAL;
--
-- /* Find the buddy */
-- if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, group, name, AIM_SSI_TYPE_BUDDY)))
-- return -EINVAL;
--
-- /* Remove the item from the list */
-- aim_ssi_itemlist_del(&od->ssi.local, del);
--
-- /* Modify the parent group */
-- aim_ssi_itemlist_rebuildgroup(od->ssi.local, group);
--
-- /* Sync our local list with the server list */
-- return aim_ssi_sync(od);
--}
--
--/**
-- * Deletes a group from the list.
-- *
-- * @param od The oscar odion.
-- * @param group The name of the group.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int aim_ssi_delgroup(OscarData *od, const char *group)
--{
-- struct aim_ssi_item *del;
-- aim_tlv_t *tlv;
--
-- if (!od)
-- return -EINVAL;
--
-- /* Find the group */
-- if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP)))
-- return -EINVAL;
--
-- /* Don't delete the group if it's not empty */
-- tlv = aim_tlv_gettlv(del->data, 0x00c8, 1);
-- if (tlv && tlv->length > 0)
-- return -EINVAL;
--
-- /* Remove the item from the list */
-- aim_ssi_itemlist_del(&od->ssi.local, del);
--
-- /* Modify the parent group */
-- aim_ssi_itemlist_rebuildgroup(od->ssi.local, group);
--
-- /* Sync our local list with the server list */
-- return aim_ssi_sync(od);
--}
--
--/**
-- * Move a buddy from one group to another group. This basically just deletes the
-- * buddy and re-adds it.
-- *
-- * @param od The oscar odion.
-- * @param oldgn The group that the buddy is currently in.
-- * @param newgn The group that the buddy should be moved in to.
-- * @param bn The name of the buddy to be moved.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int aim_ssi_movebuddy(OscarData *od, const char *oldgn, const char *newgn, const char *bn)
--{
-- struct aim_ssi_item *buddy;
-- GSList *data;
--
-- /* Find the buddy */
-- buddy = aim_ssi_itemlist_finditem(od->ssi.local, oldgn, bn, AIM_SSI_TYPE_BUDDY);
-- if (buddy == NULL)
-- return -EINVAL;
--
-- /* Make a copy of the buddy's TLV list */
-- data = aim_tlvlist_copy(buddy->data);
--
-- /* Delete the old item */
-- aim_ssi_delbuddy(od, bn, oldgn);
--
-- /* Add the new item using the EXACT SAME TLV list */
-- aim_ssi_addbuddy(od, bn, newgn, data, NULL, NULL, NULL, FALSE);
--
-- return 0;
--}
--
--/**
-- * Change the alias stored on the server for a given buddy.
-- *
-- * @param od The oscar odion.
-- * @param gn The group that the buddy is currently in.
-- * @param bn The name of the buddy.
-- * @param alias The new alias for the buddy, or NULL if you want to remove
-- * a buddy's comment.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int aim_ssi_aliasbuddy(OscarData *od, const char *gn, const char *bn, const char *alias)
--{
-- struct aim_ssi_item *tmp;
--
-- if (!od || !gn || !bn)
-- return -EINVAL;
--
-- if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, gn, bn, AIM_SSI_TYPE_BUDDY)))
-- return -EINVAL;
--
-- /* Either add or remove the 0x0131 TLV from the TLV chain */
-- if ((alias != NULL) && (strlen(alias) > 0))
-- aim_tlvlist_replace_str(&tmp->data, 0x0131, alias);
-- else
-- aim_tlvlist_remove(&tmp->data, 0x0131);
--
-- /* Sync our local list with the server list */
-- return aim_ssi_sync(od);
--}
--
--/**
-- * Change the comment stored on the server for a given buddy.
-- *
-- * @param od The oscar odion.
-- * @param gn The group that the buddy is currently in.
-- * @param bn The name of the buddy.
-- * @param alias The new comment for the buddy, or NULL if you want to remove
-- * a buddy's comment.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int aim_ssi_editcomment(OscarData *od, const char *gn, const char *bn, const char *comment)
--{
-- struct aim_ssi_item *tmp;
--
-- if (!od || !gn || !bn)
-- return -EINVAL;
--
-- if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, gn, bn, AIM_SSI_TYPE_BUDDY)))
-- return -EINVAL;
--
-- /* Either add or remove the 0x0131 TLV from the TLV chain */
-- if ((comment != NULL) && (strlen(comment) > 0))
-- aim_tlvlist_replace_str(&tmp->data, 0x013c, comment);
-- else
-- aim_tlvlist_remove(&tmp->data, 0x013c);
--
-- /* Sync our local list with the server list */
-- return aim_ssi_sync(od);
--}
--
--/**
-- * Rename a group.
-- *
-- * @param od The oscar odion.
-- * @param oldgn The old group name.
-- * @param newgn The new group name.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int aim_ssi_rename_group(OscarData *od, const char *oldgn, const char *newgn)
--{
-- struct aim_ssi_item *group;
--
-- if (!od || !oldgn || !newgn)
-- return -EINVAL;
--
-- if (!(group = aim_ssi_itemlist_finditem(od->ssi.local, oldgn, NULL, AIM_SSI_TYPE_GROUP)))
-- return -EINVAL;
--
-- g_free(group->name);
-- group->name = g_strdup(newgn);
--
-- /* Sync our local list with the server list */
-- return aim_ssi_sync(od);
--}
--
--/**
-- * Stores your permit/deny setting on the server, and starts using it.
-- *
-- * @param od The oscar odion.
-- * @param permdeny Your permit/deny setting. For ICQ accounts, it actually affects your visibility
-- * and has nothing to do with blocking. Can be one of the following:
-- * 1 - Allow all users
-- * 2 - Block all users
-- * 3 - Allow only the users below
-- * 4 - Block only the users below
-- * 5 - Allow only users on my buddy list
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int aim_ssi_setpermdeny(OscarData *od, guint8 permdeny)
--{
-- struct aim_ssi_item *tmp;
--
-- if (!od || !od->ssi.received_data)
-- return -EINVAL;
--
-- /* Find the PDINFO item, or add it if it does not exist */
-- if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO))) {
-- /* Make sure the master group exists */
-- if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
-- aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
--
-- tmp = aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PDINFO, NULL);
-- }
--
-- /* Need to add the 0x00ca TLV to the TLV chain */
-- aim_tlvlist_replace_8(&tmp->data, 0x00ca, permdeny);
--
-- /* Sync our local list with the server list */
-- return aim_ssi_sync(od);
--}
--
--/**
-- * Set buddy icon information
-- *
-- * @param od The oscar odion.
-- * @param iconcsum The MD5 checksum of the icon you are using.
-- * @param iconcsumlen Length of the MD5 checksum given above. Should be 0x10 bytes.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int aim_ssi_seticon(OscarData *od, const guint8 *iconsum, guint8 iconsumlen)
--{
-- struct aim_ssi_item *tmp;
-- guint8 *csumdata;
--
-- if (!od || !iconsum || !iconsumlen || !od->ssi.received_data)
-- return -EINVAL;
--
-- /* Find the ICONINFO item, or add it if it does not exist */
-- if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) {
-- /* Make sure the master group exists */
-- if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
-- aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
--
-- tmp = aim_ssi_itemlist_add(&od->ssi.local, "1", 0x0000, 0xFFFF, AIM_SSI_TYPE_ICONINFO, NULL);
-- }
--
-- /* Need to add the 0x00d5 TLV to the TLV chain */
-- csumdata = (guint8 *)g_malloc((iconsumlen+2)*sizeof(guint8));
-- aimutil_put8(&csumdata[0], 0x00);
-- aimutil_put8(&csumdata[1], iconsumlen);
-- memcpy(&csumdata[2], iconsum, iconsumlen);
-- aim_tlvlist_replace_raw(&tmp->data, 0x00d5, (iconsumlen+2) * sizeof(guint8), csumdata);
-- g_free(csumdata);
--
-- /* Need to add the 0x0131 TLV to the TLV chain, used to cache the icon */
-- aim_tlvlist_replace_noval(&tmp->data, 0x0131);
--
-- /* Sync our local list with the server list */
-- aim_ssi_sync(od);
-- return 0;
--}
--
--/**
-- * Remove a reference to a server stored buddy icon. This will make your
-- * icon stop showing up to other people.
-- *
-- * Really this function just sets the icon to a dummy value. It's weird...
-- * but I think the dummy value basically means "I don't have an icon!"
-- *
-- * @param od The oscar session.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int aim_ssi_delicon(OscarData *od)
--{
-- const guint8 csumdata[] = {0x02, 0x01, 0xd2, 0x04, 0x72};
--
-- return aim_ssi_seticon(od, csumdata, 5);
--}
--
--/**
-- * Stores your setting for various SSI settings. Whether you
-- * should show up as idle or not, etc.
-- *
-- * @param od The oscar odion.
-- * @param presence A bitmask of the first 32 entries [0-31] from
-- * http://dev.aol.com/aim/oscar/#FEEDBAG__BUDDY_PREFS
-- * 0x00000002 - Hide "eBuddy group" (whatever that is)
-- * 0x00000400 - Allow others to see your idle time
-- * 0x00020000 - Don't show Recent Buddies
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int aim_ssi_setpresence(OscarData *od, guint32 presence) {
-- struct aim_ssi_item *tmp;
--
-- if (!od || !od->ssi.received_data)
-- return -EINVAL;
--
-- /* Find the PRESENCEPREFS item, or add it if it does not exist */
-- if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS))) {
-- /* Make sure the master group exists */
-- if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
-- aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
--
-- tmp = aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PRESENCEPREFS, NULL);
-- }
--
-- /* Need to add the x00c9 TLV to the TLV chain */
-- aim_tlvlist_replace_32(&tmp->data, 0x00c9, presence);
--
-- /* Sync our local list with the server list */
-- return aim_ssi_sync(od);
--}
--
--/*
-- * Subtype 0x0002 - Request SSI Rights.
-- */
--int aim_ssi_reqrights(OscarData *od)
--{
-- FlapConnection *conn;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)))
-- return -EINVAL;
--
-- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_REQRIGHTS);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0003 - SSI Rights Information.
-- */
--static int parserights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0, i;
-- aim_rxcallback_t userfunc;
-- GSList *tlvlist;
-- aim_tlv_t *tlv;
-- ByteStream bstream;
-- guint16 *maxitems;
--
-- /* This SNAC is made up of a bunch of TLVs */
-- tlvlist = aim_tlvlist_read(bs);
--
-- /* TLV 0x0004 contains the maximum number of each item */
-- if (!(tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {
-- aim_tlvlist_free(tlvlist);
-- return 0;
-- }
--
-- byte_stream_init(&bstream, tlv->value, tlv->length);
--
-- maxitems = (guint16 *)g_malloc((tlv->length/2)*sizeof(guint16));
--
-- for (i=0; i<(tlv->length/2); i++)
-- maxitems[i] = byte_stream_get16(&bstream);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, tlv->length/2, maxitems);
--
-- aim_tlvlist_free(tlvlist);
-- g_free(maxitems);
--
-- return ret;
--}
--
--/*
-- * Subtype 0x0004 - Request SSI Data when you don't have a timestamp and
-- * revision number.
-- *
-- */
--int aim_ssi_reqdata(OscarData *od)
--{
-- FlapConnection *conn;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)))
-- return -EINVAL;
--
-- /* Free any current data, just in case */
-- aim_ssi_freelist(od);
--
-- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_REQDATA);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0006 - SSI Data.
-- */
--static int parsedata(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- guint8 fmtver; /* guess */
-- guint16 namelen, gid, bid, type;
-- char *name;
-- GSList *data;
-- GString *debugstr = g_string_new("");
--
-- fmtver = byte_stream_get8(bs); /* Version of ssi data. Should be 0x00 */
-- od->ssi.numitems += byte_stream_get16(bs); /* # of items in this SSI SNAC */
--
-- /* Read in the list */
-- while (byte_stream_bytes_left(bs) > 4) { /* last four bytes are timestamp */
-- if ((namelen = byte_stream_get16(bs)))
-- name = byte_stream_getstr(bs, namelen);
-- else
-- name = NULL;
-- gid = byte_stream_get16(bs);
-- bid = byte_stream_get16(bs);
-- type = byte_stream_get16(bs);
-- data = aim_tlvlist_readlen(bs, byte_stream_get16(bs));
-- aim_ssi_item_debug_append(debugstr, "\t", aim_ssi_itemlist_add(&od->ssi.official, name, gid, bid, type, data));
-- g_free(name);
-- aim_tlvlist_free(data);
-- }
-- purple_debug_misc("oscar", "Reading items from tlvlist for account %s:\n%s",
-- purple_connection_get_account(od->gc)->username, debugstr->str);
-- g_string_free(debugstr, TRUE);
--
-- /* Read in the timestamp */
-- od->ssi.timestamp = byte_stream_get32(bs);
--
-- if (!(snac->flags & 0x0001)) {
-- /* Make a copy of the list */
-- struct aim_ssi_item *cur;
-- for (cur=od->ssi.official; cur; cur=cur->next)
-- aim_ssi_itemlist_add(&od->ssi.local, cur->name, cur->gid, cur->bid, cur->type, cur->data);
--
-- od->ssi.received_data = TRUE;
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, fmtver, od->ssi.numitems, od->ssi.timestamp);
-- }
--
-- return ret;
--}
--
--/*
-- * Subtype 0x0007 - SSI Activate Data.
-- *
-- * Should be sent after receiving 13/6 or 13/f to tell the server you
-- * are ready to begin using the list. It will promptly give you the
-- * presence information for everyone in your list and put your permit/deny
-- * settings into effect.
-- *
-- */
--int aim_ssi_enable(OscarData *od)
--{
-- FlapConnection *conn;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)))
-- return -EINVAL;
--
-- aim_genericreq_n(od, conn, SNAC_FAMILY_FEEDBAG, 0x0007);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0008/0x0009/0x000a - SSI Add/Mod/Del Item(s).
-- *
-- * Sends the SNAC to add, modify, or delete items from the server-stored
-- * information. These 3 SNACs all have an identical structure. The only
-- * difference is the subtype that is set for the SNAC.
-- *
-- */
--static int aim_ssi_addmoddel(OscarData *od)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- int bslen;
-- struct aim_ssi_tmp *cur;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)) || !od->ssi.pending || !od->ssi.pending->item)
-- return -EINVAL;
--
-- /* Calculate total SNAC size */
-- bslen = 0;
-- for (cur=od->ssi.pending; cur; cur=cur->next) {
-- bslen += 10; /* For length, GID, BID, type, and length */
-- if (cur->item->name)
-- bslen += strlen(cur->item->name);
-- if (cur->item->data)
-- bslen += aim_tlvlist_size(cur->item->data);
-- }
--
-- byte_stream_new(&bs, bslen);
--
-- for (cur=od->ssi.pending; cur; cur=cur->next) {
-- byte_stream_put16(&bs, cur->item->name ? strlen(cur->item->name) : 0);
-- if (cur->item->name)
-- byte_stream_putstr(&bs, cur->item->name);
-- byte_stream_put16(&bs, cur->item->gid);
-- byte_stream_put16(&bs, cur->item->bid);
-- byte_stream_put16(&bs, cur->item->type);
-- byte_stream_put16(&bs, cur->item->data ? aim_tlvlist_size(cur->item->data) : 0);
-- if (cur->item->data)
-- aim_tlvlist_write(&bs, &cur->item->data);
-- }
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_FEEDBAG, od->ssi.pending->action, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_FEEDBAG, od->ssi.pending->action, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0008 - Incoming SSI add.
-- *
-- * Sent by the server, for example, when someone is added to
-- * your "Recent Buddies" group.
-- */
--static int parseadd(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- char *name;
-- guint16 len, gid, bid, type;
-- GSList *data;
--
-- while (byte_stream_bytes_left(bs)) {
-- if ((len = byte_stream_get16(bs)))
-- name = byte_stream_getstr(bs, len);
-- else
-- name = NULL;
-- gid = byte_stream_get16(bs);
-- bid = byte_stream_get16(bs);
-- type = byte_stream_get16(bs);
-- if ((len = byte_stream_get16(bs)))
-- data = aim_tlvlist_readlen(bs, len);
-- else
-- data = NULL;
--
-- aim_ssi_itemlist_add(&od->ssi.local, name, gid, bid, type, data);
-- aim_ssi_itemlist_add(&od->ssi.official, name, gid, bid, type, data);
-- aim_tlvlist_free(data);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, snac->subtype, type, name);
--
-- g_free(name);
-- }
--
-- return ret;
--}
--
--/*
-- * Subtype 0x0009 - Incoming SSI mod.
-- */
--static int parsemod(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- char *name;
-- guint16 len, gid, bid, type;
-- GSList *data;
-- struct aim_ssi_item *item;
--
-- while (byte_stream_bytes_left(bs)) {
-- if ((len = byte_stream_get16(bs)))
-- name = byte_stream_getstr(bs, len);
-- else
-- name = NULL;
-- gid = byte_stream_get16(bs);
-- bid = byte_stream_get16(bs);
-- type = byte_stream_get16(bs);
-- if ((len = byte_stream_get16(bs)))
-- data = aim_tlvlist_readlen(bs, len);
-- else
-- data = NULL;
--
-- /* Replace the 2 local items with the given one */
-- if ((item = aim_ssi_itemlist_find(od->ssi.local, gid, bid))) {
-- item->type = type;
-- g_free(item->name);
-- item->name = g_strdup(name);
-- aim_tlvlist_free(item->data);
-- item->data = aim_tlvlist_copy(data);
-- }
--
-- if ((item = aim_ssi_itemlist_find(od->ssi.official, gid, bid))) {
-- item->type = type;
-- g_free(item->name);
-- item->name = g_strdup(name);
-- aim_tlvlist_free(item->data);
-- item->data = aim_tlvlist_copy(data);
-- }
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, snac->subtype, type, name);
--
-- g_free(name);
-- aim_tlvlist_free(data);
-- }
--
-- return ret;
--}
--
--/*
-- * Subtype 0x000a - Incoming SSI del.
-- *
-- * XXX - It would probably be good for the client to actually do something when it gets this.
-- */
--static int parsedel(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- guint16 gid, bid;
-- struct aim_ssi_item *del;
--
-- while (byte_stream_bytes_left(bs)) {
-- byte_stream_advance(bs, byte_stream_get16(bs));
-- gid = byte_stream_get16(bs);
-- bid = byte_stream_get16(bs);
-- byte_stream_get16(bs);
-- byte_stream_advance(bs, byte_stream_get16(bs));
--
-- if ((del = aim_ssi_itemlist_find(od->ssi.local, gid, bid)))
-- aim_ssi_itemlist_del(&od->ssi.local, del);
-- if ((del = aim_ssi_itemlist_find(od->ssi.official, gid, bid)))
-- aim_ssi_itemlist_del(&od->ssi.official, del);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame);
-- }
--
-- return ret;
--}
--
--/*
-- * Subtype 0x000e - SSI Add/Mod/Del Ack.
-- *
-- * Response to add, modify, or delete SNAC (sent with aim_ssi_addmoddel).
-- *
-- */
--static int parseack(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- struct aim_ssi_tmp *cur, *del;
--
-- /* Read in the success/failure flags from the ack SNAC */
-- cur = od->ssi.pending;
-- while (cur && (byte_stream_bytes_left(bs)>0)) {
-- cur->ack = byte_stream_get16(bs);
-- cur = cur->next;
-- }
--
-- /*
-- * If outcome is 0, then add the item to the item list, or replace the other item,
-- * or remove the old item. If outcome is non-zero, then remove the item from the
-- * local list, or unmodify it, or add it.
-- */
-- for (cur=od->ssi.pending; (cur && (cur->ack != 0xffff)); cur=cur->next) {
-- if (cur->item) {
-- if (cur->ack) {
-- /* Our action was unsuccessful, so change the local list back to how it was */
-- if (cur->action == SNAC_SUBTYPE_FEEDBAG_ADD) {
-- /* Remove the item from the local list */
-- /* Make sure cur->item is still valid memory */
-- if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) {
-- cur->name = g_strdup(cur->item->name);
-- aim_ssi_itemlist_del(&od->ssi.local, cur->item);
-- }
-- cur->item = NULL;
--
-- } else if (cur->action == SNAC_SUBTYPE_FEEDBAG_MOD) {
-- /* Replace the local item with the item from the official list */
-- if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) {
-- struct aim_ssi_item *cur1;
-- if ((cur1 = aim_ssi_itemlist_find(od->ssi.official, cur->item->gid, cur->item->bid))) {
-- g_free(cur->item->name);
-- cur->item->name = g_strdup(cur1->name);
-- aim_tlvlist_free(cur->item->data);
-- cur->item->data = aim_tlvlist_copy(cur1->data);
-- }
-- } else
-- cur->item = NULL;
--
-- } else if (cur->action == SNAC_SUBTYPE_FEEDBAG_DEL) {
-- /* Add the item back into the local list */
-- if (aim_ssi_itemlist_valid(od->ssi.official, cur->item)) {
-- aim_ssi_itemlist_add(&od->ssi.local, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data);
-- } else
-- cur->item = NULL;
-- }
--
-- } else {
-- /* Do the exact opposite */
-- if (cur->action == SNAC_SUBTYPE_FEEDBAG_ADD) {
-- /* Add the local item to the official list */
-- if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) {
-- aim_ssi_itemlist_add(&od->ssi.official, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data);
-- } else
-- cur->item = NULL;
--
-- } else if (cur->action == SNAC_SUBTYPE_FEEDBAG_MOD) {
-- /* Replace the official item with the item from the local list */
-- if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) {
-- struct aim_ssi_item *cur1;
-- if ((cur1 = aim_ssi_itemlist_find(od->ssi.official, cur->item->gid, cur->item->bid))) {
-- g_free(cur1->name);
-- cur1->name = g_strdup(cur->item->name);
-- aim_tlvlist_free(cur1->data);
-- cur1->data = aim_tlvlist_copy(cur->item->data);
-- }
-- } else
-- cur->item = NULL;
--
-- } else if (cur->action == SNAC_SUBTYPE_FEEDBAG_DEL) {
-- /* Remove the item from the official list */
-- if (aim_ssi_itemlist_valid(od->ssi.official, cur->item))
-- aim_ssi_itemlist_del(&od->ssi.official, cur->item);
-- cur->item = NULL;
-- }
--
-- }
-- } /* End if (cur->item) */
-- } /* End for loop */
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, od->ssi.pending);
--
-- /* Free all aim_ssi_tmp's with an outcome */
-- cur = od->ssi.pending;
-- while (cur && (cur->ack != 0xffff)) {
-- del = cur;
-- cur = cur->next;
-- g_free(del->name);
-- g_free(del);
-- }
-- od->ssi.pending = cur;
--
-- /* If we're not waiting for any more acks, then send more SNACs */
-- if (!od->ssi.pending) {
-- od->ssi.waiting_for_ack = FALSE;
-- aim_ssi_sync(od);
-- }
--
-- return ret;
--}
--
--/*
-- * Subtype 0x000f - SSI Data Unchanged.
-- *
-- * Response to aim_ssi_reqifchanged() if the server-side data is not newer than
-- * posted local stamp/revision.
-- *
-- */
--static int parsedataunchanged(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
--
-- od->ssi.received_data = TRUE;
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame);
--
-- return ret;
--}
--
--/*
-- * Subtype 0x0011 - SSI Begin Data Modification.
-- *
-- * Tell the server you're going to start modifying data. This marks
-- * the beginning of a transaction.
-- */
--int aim_ssi_modbegin(OscarData *od)
--{
-- FlapConnection *conn;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)))
-- return -EINVAL;
--
-- aim_genericreq_n(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_EDITSTART);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0012 - SSI End Data Modification.
-- *
-- * Tell the server you're finished modifying data. The marks the end
-- * of a transaction.
-- */
--int aim_ssi_modend(OscarData *od)
--{
-- FlapConnection *conn;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)))
-- return -EINVAL;
--
-- aim_genericreq_n(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_EDITSTOP);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0015 - Receive an authorization grant
-- */
--static int receiveauthgrant(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- guint16 tmp;
-- char *bn, *msg, *tmpstr;
--
-- /* Read buddy name */
-- tmp = byte_stream_get8(bs);
-- if (!tmp) {
-- purple_debug_warning("oscar", "Dropping auth grant SNAC "
-- "because username was empty\n");
-- return 0;
-- }
-- bn = byte_stream_getstr(bs, tmp);
-- if (!g_utf8_validate(bn, -1, NULL)) {
-- purple_debug_warning("oscar", "Dropping auth grant SNAC "
-- "because the username was not valid UTF-8\n");
-- g_free(bn);
-- }
--
-- /* Read message */
-- tmp = byte_stream_get16(bs);
-- if (tmp) {
-- msg = byte_stream_getstr(bs, tmp);
-- if (!g_utf8_validate(msg, -1, NULL)) {
-- /* Ugh, msg isn't UTF8. Let's salvage. */
-- purple_debug_warning("oscar", "Got non-UTF8 message in auth "
-- "grant from %s\n", bn);
-- tmpstr = purple_utf8_salvage(msg);
-- g_free(msg);
-- msg = tmpstr;
-- }
-- } else
-- msg = NULL;
--
-- /* Unknown */
-- tmp = byte_stream_get16(bs);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, bn, msg);
--
-- g_free(bn);
-- g_free(msg);
--
-- return ret;
--}
--
--/*
-- * Subtype 0x0018 - Send authorization request
-- *
-- * Sends a request for authorization to the given contact. The request will either be
-- * granted, denied, or dropped.
-- *
-- */
--int aim_ssi_sendauthrequest(OscarData *od, const char *bn, const char *msg)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)) || !bn)
-- return -EINVAL;
--
-- byte_stream_new(&bs, 1+strlen(bn) + 2+(msg ? strlen(msg)+1 : 0) + 2);
--
-- /* Username */
-- byte_stream_put8(&bs, strlen(bn));
-- byte_stream_putstr(&bs, bn);
--
-- /* Message (null terminated) */
-- byte_stream_put16(&bs, msg ? strlen(msg) : 0);
-- if (msg) {
-- byte_stream_putstr(&bs, msg);
-- byte_stream_put8(&bs, 0x00);
-- }
--
-- /* Unknown */
-- byte_stream_put16(&bs, 0x0000);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SENDAUTHREQ, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SENDAUTHREQ, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0019 - Receive an authorization request
-- */
--static int receiveauthrequest(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- guint16 tmp;
-- char *bn, *msg, *tmpstr;
--
-- /* Read buddy name */
-- tmp = byte_stream_get8(bs);
-- if (!tmp) {
-- purple_debug_warning("oscar", "Dropping auth request SNAC "
-- "because username was empty\n");
-- return 0;
-- }
-- bn = byte_stream_getstr(bs, tmp);
-- if (!g_utf8_validate(bn, -1, NULL)) {
-- purple_debug_warning("oscar", "Dropping auth request SNAC "
-- "because the username was not valid UTF-8\n");
-- g_free(bn);
-- }
--
-- /* Read message */
-- tmp = byte_stream_get16(bs);
-- if (tmp) {
-- msg = byte_stream_getstr(bs, tmp);
-- if (!g_utf8_validate(msg, -1, NULL)) {
-- /* Ugh, msg isn't UTF8. Let's salvage. */
-- purple_debug_warning("oscar", "Got non-UTF8 message in auth "
-- "request from %s\n", bn);
-- tmpstr = purple_utf8_salvage(msg);
-- g_free(msg);
-- msg = tmpstr;
-- }
-- } else
-- msg = NULL;
--
-- /* Unknown */
-- tmp = byte_stream_get16(bs);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, bn, msg);
--
-- g_free(bn);
-- g_free(msg);
--
-- return ret;
--}
--
--/*
-- * Subtype 0x001a - Send authorization reply
-- *
-- * Sends a reply to a request for authorization. The reply can either
-- * grant authorization or deny authorization.
-- *
-- * if reply=0x00 then deny
-- * if reply=0x01 then grant
-- *
-- */
--int aim_ssi_sendauthreply(OscarData *od, const char *bn, guint8 reply, const char *msg)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)) || !bn)
-- return -EINVAL;
--
-- byte_stream_new(&bs, 1+strlen(bn) + 1 + 2+(msg ? (strlen(msg)+1) : 0) + 2);
--
-- /* Username */
-- byte_stream_put8(&bs, strlen(bn));
-- byte_stream_putstr(&bs, bn);
--
-- /* Grant or deny */
-- byte_stream_put8(&bs, reply);
--
-- /* Message (null terminated) */
-- byte_stream_put16(&bs, msg ? (strlen(msg)+1) : 0);
-- if (msg) {
-- byte_stream_putstr(&bs, msg);
-- byte_stream_put8(&bs, 0x00);
-- }
--
-- /* Unknown */
-- byte_stream_put16(&bs, 0x0000);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SENDAUTHREP, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SENDAUTHREP, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x001b - Receive an authorization reply
-- *
-- * You get this bad boy when other people respond to the authorization
-- * request that you have previously sent them.
-- */
--static int receiveauthreply(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- guint16 tmp;
-- guint8 reply;
-- char *bn, *msg, *tmpstr;
--
-- /* Read buddy name */
-- tmp = byte_stream_get8(bs);
-- if (!tmp) {
-- purple_debug_warning("oscar", "Dropping auth reply SNAC "
-- "because username was empty\n");
-- return 0;
-- }
-- bn = byte_stream_getstr(bs, tmp);
-- if (!g_utf8_validate(bn, -1, NULL)) {
-- purple_debug_warning("oscar", "Dropping auth reply SNAC "
-- "because the username was not valid UTF-8\n");
-- g_free(bn);
-- }
--
-- /* Read reply */
-- reply = byte_stream_get8(bs);
--
-- /* Read message */
-- tmp = byte_stream_get16(bs);
-- if (tmp) {
-- msg = byte_stream_getstr(bs, tmp);
-- if (!g_utf8_validate(msg, -1, NULL)) {
-- /* Ugh, msg isn't UTF8. Let's salvage. */
-- purple_debug_warning("oscar", "Got non-UTF8 message in auth "
-- "reply from %s\n", bn);
-- tmpstr = purple_utf8_salvage(msg);
-- g_free(msg);
-- msg = tmpstr;
-- }
-- } else
-- msg = NULL;
--
-- /* Unknown */
-- tmp = byte_stream_get16(bs);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, bn, reply, msg);
--
-- g_free(bn);
-- g_free(msg);
--
-- return ret;
--}
--
--/*
-- * Subtype 0x001c - Receive a message telling you someone added you to their list.
-- */
--static int receiveadded(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- guint16 tmp;
-- char *bn;
--
-- /* Read buddy name */
-- tmp = byte_stream_get8(bs);
-- if (!tmp) {
-- purple_debug_warning("oscar", "Dropping 'you were added' SNAC "
-- "because username was empty\n");
-- return 0;
-- }
-- bn = byte_stream_getstr(bs, tmp);
-- if (!g_utf8_validate(bn, -1, NULL)) {
-- purple_debug_warning("oscar", "Dropping 'you were added' SNAC "
-- "because the username was not valid UTF-8\n");
-- g_free(bn);
-- }
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, bn);
--
-- g_free(bn);
--
-- return ret;
--}
--
--/*
-- * If we're on ICQ, then AIM_SSI_TYPE_DENY is used for the "permanently invisible" list.
-- * AIM_SSI_TYPE_ICQDENY is used for blocking users instead.
-- */
--guint16
--aim_ssi_getdenyentrytype(OscarData* od)
--{
-- return od->icq ? AIM_SSI_TYPE_ICQDENY : AIM_SSI_TYPE_DENY;
--}
--
--static int
--snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_RIGHTSINFO)
-- return parserights(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_LIST)
-- return parsedata(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_ADD)
-- return parseadd(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_MOD)
-- return parsemod(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_DEL)
-- return parsedel(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_SRVACK)
-- return parseack(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_NOLIST)
-- return parsedataunchanged(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_RECVAUTH)
-- return receiveauthgrant(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_RECVAUTHREQ)
-- return receiveauthrequest(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_RECVAUTHREP)
-- return receiveauthreply(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_ADDED)
-- return receiveadded(od, conn, mod, frame, snac, bs);
--
-- return 0;
--}
--
--static void
--ssi_shutdown(OscarData *od, aim_module_t *mod)
--{
-- aim_ssi_freelist(od);
--}
--
--int
--ssi_modfirst(OscarData *od, aim_module_t *mod)
--{
-- mod->family = SNAC_FAMILY_FEEDBAG;
-- mod->version = 0x0004;
-- mod->toolid = 0x0110;
-- mod->toolversion = 0x0629;
-- mod->flags = 0;
-- strncpy(mod->name, "feedbag", sizeof(mod->name));
-- mod->snachandler = snachandler;
-- mod->shutdown = ssi_shutdown;
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_icbm.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_icbm.c
---- pidgin-2.10.7/libpurple/protocols/oscar/family_icbm.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_icbm.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,2138 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Family 0x0004 - Routines for sending/receiving Instant Messages.
-- *
-- * Note the term ICBM (Inter-Client Basic Message) which blankets
-- * all types of generically routed through-server messages. Within
-- * the ICBM types (family 4), a channel is defined. Each channel
-- * represents a different type of message. Channel 1 is used for
-- * what would commonly be called an "instant message". Channel 2
-- * is used for negotiating "rendezvous". These transactions end in
-- * something more complex happening, such as a chat invitation, or
-- * a file transfer. Channel 3 is used for chat messages (not in
-- * the same family as these channels). Channel 4 is used for
-- * various ICQ messages. Examples are normal messages, URLs, and
-- * old-style authorization.
-- *
-- * In addition to the channel, every ICBM contains a cookie. For
-- * standard IMs, these are only used for error messages. However,
-- * the more complex rendezvous messages make suitably more complex
-- * use of this field.
-- *
-- * TODO: Split this up into an im.c file an an icbm.c file. It
-- * will be beautiful, you'll see.
-- *
-- * Make sure flap_connection_findbygroup is used by all functions.
-- */
--
--#include "encoding.h"
--#include "oscar.h"
--#include "peer.h"
--
--#ifdef _WIN32
--#include "win32dep.h"
--#endif
--
--#include "util.h"
--
--static const char * const errcodereason[] = {
-- N_("Invalid error"),
-- N_("Not logged in"),
-- N_("Cannot receive IM due to parental controls"),
-- N_("Cannot send SMS without accepting terms"),
-- N_("Cannot send SMS"), /* SMS_WITHOUT_DISCLAIMER is weird */
-- N_("Cannot send SMS to this country"),
-- N_("Unknown error"), /* Undocumented */
-- N_("Unknown error"), /* Undocumented */
-- N_("Cannot send SMS to unknown country"),
-- N_("Bot accounts cannot initiate IMs"),
-- N_("Bot account cannot IM this user"),
-- N_("Bot account reached IM limit"),
-- N_("Bot account reached daily IM limit"),
-- N_("Bot account reached monthly IM limit"),
-- N_("Unable to receive offline messages"),
-- N_("Offline message store full")
--};
--static const int errcodereasonlen = G_N_ELEMENTS(errcodereason);
--
--/**
-- * Add a standard ICBM header to the given bstream with the given
-- * information.
-- *
-- * @param bs The bstream to write the ICBM header to.
-- * @param c c is for cookie, and cookie is for me.
-- * @param channel The ICBM channel (1 through 4).
-- * @param bn Null-terminated scrizeen nizame.
-- * @return The number of bytes written. It's really not useful.
-- */
--static int aim_im_puticbm(ByteStream *bs, const guchar *c, guint16 channel, const char *bn)
--{
-- byte_stream_putraw(bs, c, 8);
-- byte_stream_put16(bs, channel);
-- byte_stream_put8(bs, strlen(bn));
-- byte_stream_putstr(bs, bn);
-- return 8+2+1+strlen(bn);
--}
--
--/**
-- * Generates a random ICBM cookie in a character array of length 8
-- * and copies it into the variable passed as cookie
-- * TODO: Maybe we should stop limiting our characters to the visible range?
-- */
--void aim_icbm_makecookie(guchar *cookie)
--{
-- int i;
--
-- /* Should be like "21CBF95" and null terminated */
-- for (i = 0; i < 7; i++)
-- cookie[i] = 0x30 + ((guchar)rand() % 10);
-- cookie[7] = '\0';
--}
--
--/*
-- * Subtype 0x0001 - Error
-- */
--static int
--error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- aim_snac_t *snac2;
-- guint16 reason, errcode = 0;
-- const char *bn;
-- GSList *tlvlist;
-- PurpleConnection *gc = od->gc;
--#ifdef TODOFT
-- PurpleXfer *xfer;
--#endif
-- const char *reason_str;
-- char *buf;
--
-- snac2 = aim_remsnac(od, snac->id);
-- if (!snac2) {
-- purple_debug_misc("oscar", "icbm error: received response from unknown request!\n");
-- return 1;
-- }
--
-- if (snac2->family != SNAC_FAMILY_ICBM) {
-- purple_debug_misc("oscar", "icbm error: received response from invalid request! %d\n", snac2->family);
-- g_free(snac2->data);
-- g_free(snac2);
-- return 1;
-- }
--
-- /* Data is assumed to be the destination bn */
-- bn = snac2->data;
-- if (!bn || bn[0] == '\0') {
-- purple_debug_misc("oscar", "icbm error: received response from request without a buddy name!\n");
-- g_free(snac2->data);
-- g_free(snac2);
-- return 1;
-- }
--
-- reason = byte_stream_get16(bs);
--
-- tlvlist = aim_tlvlist_read(bs);
-- if (aim_tlv_gettlv(tlvlist, 0x0008, 1))
-- errcode = aim_tlv_get16(tlvlist, 0x0008, 1);
-- aim_tlvlist_free(tlvlist);
--
-- purple_debug_error("oscar",
-- "Message error with bn %s and reason %hu and errcode %hu\n",
-- (bn != NULL ? bn : ""), reason, errcode);
--
--#ifdef TODOFT
-- /* If this was a file transfer request, bn is a cookie */
-- if ((xfer = oscar_find_xfer_by_cookie(od->file_transfers, bn))) {
-- purple_xfer_cancel_remote(xfer);
-- return 1;
-- }
--#endif
--
-- /* Notify the user that the message wasn't delivered */
-- reason_str = oscar_get_msgerr_reason(reason);
-- if (errcode != 0 && errcode < errcodereasonlen)
-- buf = g_strdup_printf(_("Unable to send message: %s (%s)"), reason_str,
-- _(errcodereason[errcode]));
-- else
-- buf = g_strdup_printf(_("Unable to send message: %s"), reason_str);
--
-- if (!purple_conv_present_error(bn, purple_connection_get_account(gc), buf)) {
-- g_free(buf);
-- if (errcode != 0 && errcode < errcodereasonlen)
-- buf = g_strdup_printf(_("Unable to send message to %s: %s (%s)"),
-- bn ? bn : "(unknown)", reason_str,
-- _(errcodereason[errcode]));
-- else
-- buf = g_strdup_printf(_("Unable to send message to %s: %s"),
-- bn ? bn : "(unknown)", reason_str);
-- purple_notify_error(od->gc, NULL, buf, reason_str);
-- }
-- g_free(buf);
--
-- g_free(snac2->data);
-- g_free(snac2);
--
-- return 1;
--}
--
--/**
-- * Subtype 0x0002 - Set ICBM parameters.
-- *
-- * I definitely recommend sending this. If you don't, you'll be stuck
-- * with the rather unreasonable defaults.
-- *
-- */
--int aim_im_setparams(OscarData *od, struct aim_icbmparameters *params)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
-- return -EINVAL;
--
-- if (!params)
-- return -EINVAL;
--
-- byte_stream_new(&bs, 16);
--
-- /* This is read-only (see Parameter Reply). Must be set to zero here. */
-- byte_stream_put16(&bs, 0x0000);
--
-- /* These are all read-write */
-- byte_stream_put32(&bs, params->flags);
-- byte_stream_put16(&bs, params->maxmsglen);
-- byte_stream_put16(&bs, params->maxsenderwarn);
-- byte_stream_put16(&bs, params->maxrecverwarn);
-- byte_stream_put32(&bs, params->minmsginterval);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0002, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0002, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/**
-- * Subtype 0x0004 - Request ICBM parameter information.
-- *
-- */
--int aim_im_reqparams(OscarData *od)
--{
-- FlapConnection *conn;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
-- return -EINVAL;
--
-- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_ICBM, 0x0004);
--
-- return 0;
--}
--
--/**
-- * Subtype 0x0005 - Receive parameter information.
-- *
-- */
--static int aim_im_paraminfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- struct aim_icbmparameters params;
--
-- params.maxchan = byte_stream_get16(bs);
-- params.flags = byte_stream_get32(bs);
-- params.maxmsglen = byte_stream_get16(bs);
-- params.maxsenderwarn = byte_stream_get16(bs);
-- params.maxrecverwarn = byte_stream_get16(bs);
-- params.minmsginterval = byte_stream_get32(bs);
--
-- params.flags = AIM_IMPARAM_FLAG_CHANNEL_MSGS_ALLOWED
-- | AIM_IMPARAM_FLAG_MISSED_CALLS_ENABLED
-- | AIM_IMPARAM_FLAG_EVENTS_ALLOWED
-- | AIM_IMPARAM_FLAG_SMS_SUPPORTED
-- | AIM_IMPARAM_FLAG_OFFLINE_MSGS_ALLOWED
-- | AIM_IMPARAM_FLAG_USE_HTML_FOR_ICQ;
-- params.maxmsglen = 8000;
-- params.minmsginterval = 0;
--
-- aim_im_setparams(od, &params);
--
-- return 0;
--}
--
--/**
-- * Subtype 0x0006 - Send an ICBM (instant message).
-- *
-- *
-- * Possible flags:
-- * AIM_IMFLAGS_AWAY -- Marks the message as an autoresponse
-- * AIM_IMFLAGS_OFFLINE--If destination is offline, store it until they are
-- * online (probably ICQ only).
-- *
-- * Implementation note: Since this is one of the most-used functions
-- * in all of libfaim, it is written with performance in mind. As such,
-- * it is not as clear as it could be in respect to how this message is
-- * supposed to be layed out. Most obviously, tlvlists should be used
-- * instead of writing out the bytes manually.
-- */
--int aim_im_sendch1_ext(OscarData *od, struct aim_sendimext_args *args)
--{
-- FlapConnection *conn;
-- aim_snacid_t snacid;
-- ByteStream data;
-- guchar cookie[8];
-- int msgtlvlen;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
-- return -EINVAL;
--
-- if (!args)
-- return -EINVAL;
--
-- if (!args->msg || (args->msglen <= 0))
-- return -EINVAL;
--
-- if (args->msglen > MAXMSGLEN)
-- return -E2BIG;
--
-- /* Painfully calculate the size of the message TLV */
-- msgtlvlen = 1 + 1; /* 0501 */
-- msgtlvlen += 2 + args->featureslen;
-- msgtlvlen += 2 /* 0101 */ + 2 /* block len */;
-- msgtlvlen += 4 /* charset */ + args->msglen;
--
-- byte_stream_new(&data, msgtlvlen + 128);
--
-- /* Generate an ICBM cookie */
-- aim_icbm_makecookie(cookie);
--
-- /* ICBM header */
-- aim_im_puticbm(&data, cookie, 0x0001, args->destbn);
--
-- /* Message TLV (type 0x0002) */
-- byte_stream_put16(&data, 0x0002);
-- byte_stream_put16(&data, msgtlvlen);
--
-- /* Features TLV (type 0x0501) */
-- byte_stream_put16(&data, 0x0501);
-- byte_stream_put16(&data, args->featureslen);
-- byte_stream_putraw(&data, args->features, args->featureslen);
--
-- /* Insert message text in a TLV (type 0x0101) */
-- byte_stream_put16(&data, 0x0101);
--
-- /* Message block length */
-- byte_stream_put16(&data, args->msglen + 0x04);
--
-- /* Character set */
-- byte_stream_put16(&data, args->charset);
-- /* Character subset -- we always use 0 here */
-- byte_stream_put16(&data, 0x0);
--
-- /* Message. Not terminated */
-- byte_stream_putraw(&data, (guchar *)args->msg, args->msglen);
--
-- /* Set the Autoresponse flag */
-- if (args->flags & AIM_IMFLAGS_AWAY) {
-- byte_stream_put16(&data, 0x0004);
-- byte_stream_put16(&data, 0x0000);
-- } else {
-- /* Set the Request Acknowledge flag */
-- byte_stream_put16(&data, 0x0003);
-- byte_stream_put16(&data, 0x0000);
--
-- if (args->flags & AIM_IMFLAGS_OFFLINE) {
-- /* Allow this message to be queued as an offline message */
-- byte_stream_put16(&data, 0x0006);
-- byte_stream_put16(&data, 0x0000);
-- }
-- }
--
-- /*
-- * Set the I HAVE A REALLY PURTY ICON flag.
-- * XXX - This should really only be sent on initial
-- * IMs and when you change your icon.
-- */
-- if (args->flags & AIM_IMFLAGS_HASICON) {
-- byte_stream_put16(&data, 0x0008);
-- byte_stream_put16(&data, 0x000c);
-- byte_stream_put32(&data, args->iconlen);
-- byte_stream_put16(&data, 0x0001);
-- byte_stream_put16(&data, args->iconsum);
-- byte_stream_put32(&data, args->iconstamp);
-- }
--
-- /*
-- * Set the Buddy Icon Requested flag.
-- * XXX - Every time? Surely not...
-- */
-- if (args->flags & AIM_IMFLAGS_BUDDYREQ) {
-- byte_stream_put16(&data, 0x0009);
-- byte_stream_put16(&data, 0x0000);
-- }
--
-- /* XXX - should be optional */
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, args->destbn, strlen(args->destbn)+1);
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &data);
-- byte_stream_destroy(&data);
--
-- /* clean out SNACs over 60sec old */
-- aim_cleansnacs(od, 60);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0006 - Send a chat invitation.
-- */
--int aim_im_sendch2_chatinvite(OscarData *od, const char *bn, const char *msg, guint16 exchange, const char *roomname, guint16 instance)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- IcbmCookie *msgcookie;
-- struct aim_invite_priv *priv;
-- guchar cookie[8];
-- GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
-- ByteStream hdrbs;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
-- return -EINVAL;
--
-- if (!bn || !msg || !roomname)
-- return -EINVAL;
--
-- aim_icbm_makecookie(cookie);
--
-- byte_stream_new(&bs, 1142+strlen(bn)+strlen(roomname)+strlen(msg));
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, bn, strlen(bn)+1);
--
-- /* XXX should be uncached by an unwritten 'invite accept' handler */
-- priv = g_malloc(sizeof(struct aim_invite_priv));
-- priv->bn = g_strdup(bn);
-- priv->roomname = g_strdup(roomname);
-- priv->exchange = exchange;
-- priv->instance = instance;
--
-- if ((msgcookie = aim_mkcookie(cookie, AIM_COOKIETYPE_INVITE, priv)))
-- aim_cachecookie(od, msgcookie);
-- else
-- g_free(priv);
--
-- /* ICBM Header */
-- aim_im_puticbm(&bs, cookie, 0x0002, bn);
--
-- /*
-- * TLV t(0005)
-- *
-- * Everything else is inside this TLV.
-- *
-- * Sigh. AOL was rather inconsistent right here. So we have
-- * to play some minor tricks. Right inside the type 5 is some
-- * raw data, followed by a series of TLVs.
-- *
-- */
-- byte_stream_new(&hdrbs, 2+8+16+6+4+4+strlen(msg)+4+2+1+strlen(roomname)+2);
--
-- byte_stream_put16(&hdrbs, 0x0000); /* Unknown! */
-- byte_stream_putraw(&hdrbs, cookie, sizeof(cookie)); /* I think... */
-- byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_CHAT);
--
-- aim_tlvlist_add_16(&inner_tlvlist, 0x000a, 0x0001);
-- aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
-- aim_tlvlist_add_str(&inner_tlvlist, 0x000c, msg);
-- aim_tlvlist_add_chatroom(&inner_tlvlist, 0x2711, exchange, roomname, instance);
-- aim_tlvlist_write(&hdrbs, &inner_tlvlist);
--
-- aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
-- byte_stream_destroy(&hdrbs);
--
-- aim_tlvlist_write(&bs, &outer_tlvlist);
--
-- aim_tlvlist_free(inner_tlvlist);
-- aim_tlvlist_free(outer_tlvlist);
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/**
-- * Subtype 0x0006 - Send your icon to a given user.
-- *
-- * This is also performance sensitive. (If you can believe it...)
-- *
-- */
--int aim_im_sendch2_icon(OscarData *od, const char *bn, const guint8 *icon, int iconlen, time_t stamp, guint16 iconsum)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- guchar cookie[8];
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
-- return -EINVAL;
--
-- if (!bn || !icon || (iconlen <= 0) || (iconlen >= MAXICONLEN))
-- return -EINVAL;
--
-- aim_icbm_makecookie(cookie);
--
-- byte_stream_new(&bs, 8+2+1+strlen(bn)+2+2+2+8+16+2+2+2+2+2+2+2+4+4+4+iconlen+strlen(AIM_ICONIDENT)+2+2);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
--
-- /* ICBM header */
-- aim_im_puticbm(&bs, cookie, 0x0002, bn);
--
-- /*
-- * TLV t(0005)
-- *
-- * Encompasses everything below.
-- */
-- byte_stream_put16(&bs, 0x0005);
-- byte_stream_put16(&bs, 2+8+16+6+4+4+iconlen+4+4+4+strlen(AIM_ICONIDENT));
--
-- byte_stream_put16(&bs, 0x0000);
-- byte_stream_putraw(&bs, cookie, 8);
-- byte_stream_putcaps(&bs, OSCAR_CAPABILITY_BUDDYICON);
--
-- /* TLV t(000a) */
-- byte_stream_put16(&bs, 0x000a);
-- byte_stream_put16(&bs, 0x0002);
-- byte_stream_put16(&bs, 0x0001);
--
-- /* TLV t(000f) */
-- byte_stream_put16(&bs, 0x000f);
-- byte_stream_put16(&bs, 0x0000);
--
-- /* TLV t(2711) */
-- byte_stream_put16(&bs, 0x2711);
-- byte_stream_put16(&bs, 4+4+4+iconlen+strlen(AIM_ICONIDENT));
-- byte_stream_put16(&bs, 0x0000);
-- byte_stream_put16(&bs, iconsum);
-- byte_stream_put32(&bs, iconlen);
-- byte_stream_put32(&bs, stamp);
-- byte_stream_putraw(&bs, icon, iconlen);
-- byte_stream_putstr(&bs, AIM_ICONIDENT);
--
-- /* TLV t(0003) */
-- byte_stream_put16(&bs, 0x0003);
-- byte_stream_put16(&bs, 0x0000);
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/**
-- * Cancel a rendezvous invitation. It could be an invitation to
-- * establish a direct connection, or a file-send, or a chat invite.
-- */
--void
--aim_im_sendch2_cancel(PeerConnection *peer_conn)
--{
-- OscarData *od;
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
-- ByteStream hdrbs;
--
-- od = peer_conn->od;
-- conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
-- if (conn == NULL)
-- return;
--
-- byte_stream_new(&bs, 118+strlen(peer_conn->bn));
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
--
-- /* ICBM header */
-- aim_im_puticbm(&bs, peer_conn->cookie, 0x0002, peer_conn->bn);
--
-- aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
--
-- byte_stream_new(&hdrbs, 64);
--
-- byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_CANCEL);
-- byte_stream_putraw(&hdrbs, peer_conn->cookie, 8);
-- byte_stream_putcaps(&hdrbs, peer_conn->type);
--
-- /* This TLV means "cancel!" */
-- aim_tlvlist_add_16(&inner_tlvlist, 0x000b, 0x0001);
-- aim_tlvlist_write(&hdrbs, &inner_tlvlist);
--
-- aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
-- byte_stream_destroy(&hdrbs);
--
-- aim_tlvlist_write(&bs, &outer_tlvlist);
--
-- aim_tlvlist_free(inner_tlvlist);
-- aim_tlvlist_free(outer_tlvlist);
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--/**
-- * Subtype 0x0006 - Send an "I accept and I've connected to
-- * you" message.
-- */
--void
--aim_im_sendch2_connected(PeerConnection *peer_conn)
--{
-- OscarData *od;
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
--
-- od = peer_conn->od;
-- conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
-- if (conn == NULL)
-- return;
--
-- byte_stream_new(&bs, 11+strlen(peer_conn->bn) + 4+2+8+16);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
--
-- /* ICBM header */
-- aim_im_puticbm(&bs, peer_conn->cookie, 0x0002, peer_conn->bn);
--
-- byte_stream_put16(&bs, 0x0005);
-- byte_stream_put16(&bs, 0x001a);
-- byte_stream_put16(&bs, AIM_RENDEZVOUS_CONNECTED);
-- byte_stream_putraw(&bs, peer_conn->cookie, 8);
-- byte_stream_putcaps(&bs, peer_conn->type);
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--/**
-- * Subtype 0x0006 - Send a direct connect rendezvous ICBM. This
-- * could have a number of meanings, depending on the content:
-- * "I want you to connect to me"
-- * "I want to connect to you"
-- * "I want to connect through a proxy server"
-- */
--void
--aim_im_sendch2_odc_requestdirect(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 port, guint16 requestnumber)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
-- ByteStream hdrbs;
--
-- conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
-- if (conn == NULL)
-- return;
--
-- byte_stream_new(&bs, 246+strlen(bn));
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
--
-- /* ICBM header */
-- aim_im_puticbm(&bs, cookie, 0x0002, bn);
--
-- aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
--
-- byte_stream_new(&hdrbs, 128);
--
-- byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_PROPOSE);
-- byte_stream_putraw(&hdrbs, cookie, 8);
-- byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_DIRECTIM);
--
-- aim_tlvlist_add_raw(&inner_tlvlist, 0x0002, 4, ip);
-- aim_tlvlist_add_raw(&inner_tlvlist, 0x0003, 4, ip);
-- aim_tlvlist_add_16(&inner_tlvlist, 0x0005, port);
-- aim_tlvlist_add_16(&inner_tlvlist, 0x000a, requestnumber);
-- aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
-- aim_tlvlist_write(&hdrbs, &inner_tlvlist);
--
-- aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
-- byte_stream_destroy(&hdrbs);
--
-- aim_tlvlist_write(&bs, &outer_tlvlist);
--
-- aim_tlvlist_free(inner_tlvlist);
-- aim_tlvlist_free(outer_tlvlist);
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--/**
-- * Subtype 0x0006 - Send a direct connect rendezvous ICBM asking the
-- * remote user to connect to us via a proxy server.
-- */
--void
--aim_im_sendch2_odc_requestproxy(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 pin, guint16 requestnumber)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
-- ByteStream hdrbs;
-- guint8 ip_comp[4];
--
-- conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
-- if (conn == NULL)
-- return;
--
-- byte_stream_new(&bs, 246+strlen(bn));
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
--
-- /* ICBM header */
-- aim_im_puticbm(&bs, cookie, 0x0002, bn);
--
-- aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
--
-- byte_stream_new(&hdrbs, 128);
--
-- byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_PROPOSE);
-- byte_stream_putraw(&hdrbs, cookie, 8);
-- byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_DIRECTIM);
--
-- aim_tlvlist_add_raw(&inner_tlvlist, 0x0002, 4, ip);
-- aim_tlvlist_add_raw(&inner_tlvlist, 0x0003, 4, ip);
-- aim_tlvlist_add_16(&inner_tlvlist, 0x0005, pin);
-- aim_tlvlist_add_16(&inner_tlvlist, 0x000a, requestnumber);
-- aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
-- aim_tlvlist_add_noval(&inner_tlvlist, 0x0010);
--
-- /* Send the bitwise complement of the port and ip. As a check? */
-- ip_comp[0] = ~ip[0];
-- ip_comp[1] = ~ip[1];
-- ip_comp[2] = ~ip[2];
-- ip_comp[3] = ~ip[3];
-- aim_tlvlist_add_raw(&inner_tlvlist, 0x0016, 4, ip_comp);
-- aim_tlvlist_add_16(&inner_tlvlist, 0x0017, ~pin);
--
-- aim_tlvlist_write(&hdrbs, &inner_tlvlist);
--
-- aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
-- byte_stream_destroy(&hdrbs);
--
-- aim_tlvlist_write(&bs, &outer_tlvlist);
--
-- aim_tlvlist_free(inner_tlvlist);
-- aim_tlvlist_free(outer_tlvlist);
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--/**
-- * Subtype 0x0006 - Send an "I want to send you this file" message
-- *
-- */
--void
--aim_im_sendch2_sendfile_requestdirect(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 port, guint16 requestnumber, const gchar *filename, guint32 size, guint16 numfiles)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
-- ByteStream hdrbs;
--
-- g_return_if_fail(bn != NULL);
-- g_return_if_fail(ip != NULL);
--
-- conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
-- if (conn == NULL)
-- return;
--
-- byte_stream_new(&bs, 1014);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
--
-- /* ICBM header */
-- aim_im_puticbm(&bs, cookie, 0x0002, bn);
--
-- aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
--
-- byte_stream_new(&hdrbs, 512);
--
-- byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_PROPOSE);
-- byte_stream_putraw(&hdrbs, cookie, 8);
-- byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_SENDFILE);
--
-- aim_tlvlist_add_raw(&inner_tlvlist, 0x0002, 4, ip);
-- aim_tlvlist_add_raw(&inner_tlvlist, 0x0003, 4, ip);
-- aim_tlvlist_add_16(&inner_tlvlist, 0x0005, port);
-- aim_tlvlist_add_16(&inner_tlvlist, 0x000a, requestnumber);
-- aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
-- /* TODO: Send 0x0016 and 0x0017 */
--
-- if (filename != NULL)
-- {
-- ByteStream inner_bs;
--
-- /* Begin TLV t(2711) */
-- byte_stream_new(&inner_bs, 2+2+4+strlen(filename)+1);
-- byte_stream_put16(&inner_bs, (numfiles > 1) ? 0x0002 : 0x0001);
-- byte_stream_put16(&inner_bs, numfiles);
-- byte_stream_put32(&inner_bs, size);
--
-- /* Filename - NULL terminated, for some odd reason */
-- byte_stream_putstr(&inner_bs, filename);
-- byte_stream_put8(&inner_bs, 0x00);
--
-- aim_tlvlist_add_raw(&inner_tlvlist, 0x2711, inner_bs.len, inner_bs.data);
-- byte_stream_destroy(&inner_bs);
-- /* End TLV t(2711) */
-- }
--
-- aim_tlvlist_write(&hdrbs, &inner_tlvlist);
-- aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
-- byte_stream_destroy(&hdrbs);
--
-- aim_tlvlist_write(&bs, &outer_tlvlist);
--
-- aim_tlvlist_free(inner_tlvlist);
-- aim_tlvlist_free(outer_tlvlist);
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--/**
-- * Subtype 0x0006 - Send a sendfile connect rendezvous ICBM asking the
-- * remote user to connect to us via a proxy server.
-- */
--void
--aim_im_sendch2_sendfile_requestproxy(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 pin, guint16 requestnumber, const gchar *filename, guint32 size, guint16 numfiles)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
-- ByteStream hdrbs;
-- guint8 ip_comp[4];
--
-- conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
-- if (conn == NULL)
-- return;
--
-- byte_stream_new(&bs, 1014);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
--
-- /* ICBM header */
-- aim_im_puticbm(&bs, cookie, 0x0002, bn);
--
-- aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
--
-- byte_stream_new(&hdrbs, 512);
--
-- byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_PROPOSE);
-- byte_stream_putraw(&hdrbs, cookie, 8);
-- byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_SENDFILE);
--
-- aim_tlvlist_add_raw(&inner_tlvlist, 0x0002, 4, ip);
-- aim_tlvlist_add_raw(&inner_tlvlist, 0x0003, 4, ip);
-- aim_tlvlist_add_16(&inner_tlvlist, 0x0005, pin);
-- aim_tlvlist_add_16(&inner_tlvlist, 0x000a, requestnumber);
-- aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
-- aim_tlvlist_add_noval(&inner_tlvlist, 0x0010);
--
-- /* Send the bitwise complement of the port and ip. As a check? */
-- ip_comp[0] = ~ip[0];
-- ip_comp[1] = ~ip[1];
-- ip_comp[2] = ~ip[2];
-- ip_comp[3] = ~ip[3];
-- aim_tlvlist_add_raw(&inner_tlvlist, 0x0016, 4, ip_comp);
-- aim_tlvlist_add_16(&inner_tlvlist, 0x0017, ~pin);
--
-- if (filename != NULL)
-- {
-- ByteStream filename_bs;
--
-- /* Begin TLV t(2711) */
-- byte_stream_new(&filename_bs, 2+2+4+strlen(filename)+1);
-- byte_stream_put16(&filename_bs, (numfiles > 1) ? 0x0002 : 0x0001);
-- byte_stream_put16(&filename_bs, numfiles);
-- byte_stream_put32(&filename_bs, size);
--
-- /* Filename - NULL terminated, for some odd reason */
-- byte_stream_putstr(&filename_bs, filename);
-- byte_stream_put8(&filename_bs, 0x00);
--
-- aim_tlvlist_add_raw(&inner_tlvlist, 0x2711, filename_bs.len, filename_bs.data);
-- byte_stream_destroy(&filename_bs);
-- /* End TLV t(2711) */
-- }
--
-- aim_tlvlist_write(&hdrbs, &inner_tlvlist);
--
-- aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
-- byte_stream_destroy(&hdrbs);
--
-- aim_tlvlist_write(&bs, &outer_tlvlist);
--
-- aim_tlvlist_free(inner_tlvlist);
-- aim_tlvlist_free(outer_tlvlist);
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--static void
--incomingim_ch1_parsemsg(OscarData *od, aim_userinfo_t *userinfo, ByteStream *message, struct aim_incomingim_ch1_args *args)
--{
-- PurpleAccount *account = purple_connection_get_account(od->gc);
-- /*
-- * We're interested in the inner TLV 0x101, which contains precious, precious message.
-- */
-- while (byte_stream_bytes_left(message) >= 4) {
-- guint16 type = byte_stream_get16(message);
-- guint16 length = byte_stream_get16(message);
-- if (type == 0x101) {
-- gchar *msg;
-- guint16 msglen = length - 4; /* charset + charsubset */
-- guint16 charset = byte_stream_get16(message);
-- byte_stream_advance(message, 2); /* charsubset */
--
-- msg = byte_stream_getstr(message, msglen);
-- args->msg = oscar_decode_im(account, userinfo->bn, charset, msg, msglen);
-- g_free(msg);
-- } else {
-- byte_stream_advance(message, length);
-- }
-- }
--}
--
--static int
--incomingim_ch1(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, ByteStream *bs, guint8 *cookie)
--{
-- guint16 type, length;
-- aim_rxcallback_t userfunc;
-- int ret = 0;
-- struct aim_incomingim_ch1_args args;
-- unsigned int endpos;
--
-- memset(&args, 0, sizeof(args));
--
-- /*
-- * This used to be done using tlvchains. For performance reasons,
-- * I've changed it to process the TLVs in-place. This avoids lots
-- * of per-IM memory allocations.
-- */
-- while (byte_stream_bytes_left(bs) >= 4)
-- {
-- type = byte_stream_get16(bs);
-- length = byte_stream_get16(bs);
--
-- if (length > byte_stream_bytes_left(bs))
-- {
-- purple_debug_misc("oscar", "Received an IM containing an invalid message part from %s. They are probably trying to do something malicious.\n", userinfo->bn);
-- break;
-- }
--
-- endpos = byte_stream_curpos(bs) + length;
--
-- if (type == 0x0002) { /* Message Block */
-- ByteStream tlv02;
-- byte_stream_init(&tlv02, bs->data + bs->offset, length);
-- incomingim_ch1_parsemsg(od, userinfo, &tlv02, &args);
-- } else if (type == 0x0003) { /* Server Ack Requested */
-- args.icbmflags |= AIM_IMFLAGS_ACK;
-- } else if (type == 0x0004) { /* Message is Auto Response */
-- args.icbmflags |= AIM_IMFLAGS_AWAY;
-- } else if (type == 0x0006) { /* Message was received offline. */
-- /*
-- * This flag is set on incoming offline messages for both
-- * AIM and ICQ accounts.
-- */
-- args.icbmflags |= AIM_IMFLAGS_OFFLINE;
-- } else if (type == 0x0008) { /* I-HAVE-A-REALLY-PURTY-ICON Flag */
-- args.iconlen = byte_stream_get32(bs);
-- byte_stream_get16(bs); /* 0x0001 */
-- args.iconsum = byte_stream_get16(bs);
-- args.iconstamp = byte_stream_get32(bs);
--
-- /*
-- * This looks to be a client bug. MacAIM 4.3 will
-- * send this tag, but with all zero values, in the
-- * first message of a conversation. This makes no
-- * sense whatsoever, so I'm going to say its a bug.
-- *
-- * You really shouldn't advertise a zero-length icon
-- * anyway.
-- *
-- */
-- if (args.iconlen)
-- args.icbmflags |= AIM_IMFLAGS_HASICON;
-- } else if (type == 0x0009) {
-- args.icbmflags |= AIM_IMFLAGS_BUDDYREQ;
-- } else if (type == 0x000b) { /* Non-direct connect typing notification */
-- args.icbmflags |= AIM_IMFLAGS_TYPINGNOT;
-- } else if (type == 0x0016) {
-- /*
-- * UTC timestamp for when the message was sent. Only
-- * provided for offline messages.
-- */
-- args.timestamp = byte_stream_get32(bs);
-- }
--
-- /*
-- * This is here to protect ourselves from ourselves. That
-- * is, if something above doesn't completely parse its value
-- * section, or, worse, overparses it, this will set the
-- * stream where it needs to be in order to land on the next
-- * TLV when the loop continues.
-- *
-- */
-- byte_stream_setpos(bs, endpos);
-- }
--
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, channel, userinfo, &args);
--
-- g_free(args.msg);
-- return ret;
--}
--
--static void
--incomingim_ch2_buddylist(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata)
--{
-- /*
-- * This goes like this...
-- *
-- * group name length
-- * group name
-- * num of buddies in group
-- * buddy name length
-- * buddy name
-- * buddy name length
-- * buddy name
-- * ...
-- * group name length
-- * group name
-- * num of buddies in group
-- * buddy name length
-- * buddy name
-- * ...
-- * ...
-- */
-- while (byte_stream_bytes_left(servdata))
-- {
-- guint16 gnlen, numb;
-- int i;
-- char *gn;
--
-- gnlen = byte_stream_get16(servdata);
-- gn = byte_stream_getstr(servdata, gnlen);
-- numb = byte_stream_get16(servdata);
--
-- for (i = 0; i < numb; i++) {
-- guint16 bnlen;
-- char *bn;
--
-- bnlen = byte_stream_get16(servdata);
-- bn = byte_stream_getstr(servdata, bnlen);
--
-- purple_debug_misc("oscar", "got a buddy list from %s: group %s, buddy %s\n", userinfo->bn, gn, bn);
--
-- g_free(bn);
-- }
--
-- g_free(gn);
-- }
--
-- return;
--}
--
--static void
--incomingim_ch2_buddyicon_free(OscarData *od, IcbmArgsCh2 *args)
--{
-- g_free(args->info.icon.icon);
--
-- return;
--}
--
--static void
--incomingim_ch2_buddyicon(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata)
--{
-- args->info.icon.checksum = byte_stream_get32(servdata);
-- args->info.icon.length = byte_stream_get32(servdata);
-- args->info.icon.timestamp = byte_stream_get32(servdata);
-- args->info.icon.icon = byte_stream_getraw(servdata, args->info.icon.length);
--
-- args->destructor = (void *)incomingim_ch2_buddyicon_free;
--
-- return;
--}
--
--static void
--incomingim_ch2_chat_free(OscarData *od, IcbmArgsCh2 *args)
--{
-- /* XXX - aim_chat_roominfo_free() */
-- g_free(args->info.chat.roominfo.name);
--
-- return;
--}
--
--static void
--incomingim_ch2_chat(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata)
--{
-- /*
-- * Chat room info.
-- */
-- aim_chat_readroominfo(servdata, &args->info.chat.roominfo);
--
-- args->destructor = (void *)incomingim_ch2_chat_free;
--}
--
--static void
--incomingim_ch2_icqserverrelay_free(OscarData *od, IcbmArgsCh2 *args)
--{
-- g_free((char *)args->info.rtfmsg.msg);
--}
--
--/*
-- * The relationship between OSCAR_CAPABILITY_ICQSERVERRELAY and OSCAR_CAPABILITY_ICQRTF is
-- * kind of odd. This sends the client ICQRTF since that is all that I've seen
-- * SERVERRELAY used for.
-- *
-- * Note that this is all little-endian. Cringe.
-- *
-- */
--static void
--incomingim_ch2_icqserverrelay(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata)
--{
-- guint16 hdrlen, msglen;
--
-- args->destructor = (void *)incomingim_ch2_icqserverrelay_free;
--
--#define SKIP_HEADER(expected_hdrlen) \
-- hdrlen = byte_stream_getle16(servdata); \
-- if (hdrlen != expected_hdrlen) { \
-- purple_debug_warning("oscar", "Expected to find a header with length " #expected_hdrlen "; ignoring message"); \
-- return; \
-- } \
-- byte_stream_advance(servdata, hdrlen);
--
-- SKIP_HEADER(0x001b);
-- SKIP_HEADER(0x000e);
--
-- args->info.rtfmsg.msgtype = byte_stream_get8(servdata);
-- /*
-- * Copied from http://iserverd.khstu.ru/oscar/message.html:
-- * xx byte message flags
-- * xx xx word (LE) status code
-- * xx xx word (LE) priority code
-- *
-- * We don't need any of these, so just skip them.
-- */
-- byte_stream_advance(servdata, 1 + 2 + 2);
--
-- msglen = byte_stream_getle16(servdata);
-- args->info.rtfmsg.msg = byte_stream_getstr(servdata, msglen);
--}
--
--static void
--incomingim_ch2_sendfile_free(OscarData *od, IcbmArgsCh2 *args)
--{
-- g_free(args->info.sendfile.filename);
--}
--
--/* Someone is sending us a file */
--static void
--incomingim_ch2_sendfile(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata)
--{
-- int flen;
--
-- args->destructor = (void *)incomingim_ch2_sendfile_free;
--
-- /* Maybe there is a better way to tell what kind of sendfile
-- * this is? Maybe TLV t(000a)? */
--
-- /* subtype is one of AIM_OFT_SUBTYPE_* */
-- args->info.sendfile.subtype = byte_stream_get16(servdata);
-- args->info.sendfile.totfiles = byte_stream_get16(servdata);
-- args->info.sendfile.totsize = byte_stream_get32(servdata);
--
-- /*
-- * I hope to God I'm right when I guess that there is a
-- * 32 char max filename length for single files. I think
-- * OFT tends to do that. Gotta love inconsistency. I saw
-- * a 26 byte filename?
-- */
-- /* AAA - create an byte_stream_getnullstr function (don't anymore)(maybe) */
-- /* Use an inelegant way of getting the null-terminated filename,
-- * since there's no easy bstream routine. */
-- for (flen = 0; byte_stream_get8(servdata); flen++);
-- byte_stream_advance(servdata, -flen -1);
-- args->info.sendfile.filename = byte_stream_getstr(servdata, flen);
--
-- /* There is sometimes more after the null-terminated filename,
-- * but I'm unsure of its format. */
-- /* I don't believe him. */
-- /* There is sometimes a null byte inside a unicode filename,
-- * but as far as I can tell the filename is the last
-- * piece of data that will be in this message. --Jonathan */
--}
--
--typedef void (*ch2_args_destructor_t)(OscarData *od, IcbmArgsCh2 *args);
--
--static int incomingim_ch2(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, GSList *tlvlist, guint8 *cookie)
--{
-- aim_rxcallback_t userfunc;
-- aim_tlv_t *block1, *servdatatlv;
-- GSList *list2;
-- aim_tlv_t *tlv;
-- IcbmArgsCh2 args;
-- ByteStream bbs, sdbs, *sdbsptr = NULL;
-- guint8 *cookie2;
-- int ret = 0;
--
-- char proxyip[30] = {""};
-- char clientip[30] = {""};
-- char verifiedip[30] = {""};
--
-- memset(&args, 0, sizeof(args));
--
-- /*
-- * There's another block of TLVs embedded in the type 5 here.
-- */
-- block1 = aim_tlv_gettlv(tlvlist, 0x0005, 1);
-- if (block1 == NULL)
-- {
-- /* The server sent us ch2 ICBM without ch2 info? Weird. */
-- return 1;
-- }
-- byte_stream_init(&bbs, block1->value, block1->length);
--
-- /*
-- * First two bytes represent the status of the connection.
-- * One of the AIM_RENDEZVOUS_ defines.
-- *
-- * 0 is a request, 1 is a cancel, 2 is an accept
-- */
-- args.status = byte_stream_get16(&bbs);
--
-- /*
-- * Next comes the cookie. Should match the ICBM cookie.
-- */
-- cookie2 = byte_stream_getraw(&bbs, 8);
-- if (memcmp(cookie, cookie2, 8) != 0)
-- {
-- purple_debug_warning("oscar",
-- "Cookies don't match in rendezvous ICBM, bailing out.\n");
-- g_free(cookie2);
-- return 1;
-- }
-- memcpy(args.cookie, cookie2, 8);
-- g_free(cookie2);
--
-- /*
-- * The next 16bytes are a capability block so we can
-- * identify what type of rendezvous this is.
-- */
-- args.type = aim_locate_getcaps(od, &bbs, 0x10);
--
-- /*
-- * What follows may be TLVs or nothing, depending on the
-- * purpose of the message.
-- *
-- * Ack packets for instance have nothing more to them.
-- */
-- list2 = aim_tlvlist_read(&bbs);
--
-- /*
-- * IP address to proxy the file transfer through.
-- *
-- * TODO: I don't like this. Maybe just read in an int? Or inet_ntoa...
-- */
-- tlv = aim_tlv_gettlv(list2, 0x0002, 1);
-- if ((tlv != NULL) && (tlv->length == 4))
-- snprintf(proxyip, sizeof(proxyip), "%hhu.%hhu.%hhu.%hhu",
-- tlv->value[0], tlv->value[1],
-- tlv->value[2], tlv->value[3]);
--
-- /*
-- * IP address from the perspective of the client.
-- */
-- tlv = aim_tlv_gettlv(list2, 0x0003, 1);
-- if ((tlv != NULL) && (tlv->length == 4))
-- snprintf(clientip, sizeof(clientip), "%hhu.%hhu.%hhu.%hhu",
-- tlv->value[0], tlv->value[1],
-- tlv->value[2], tlv->value[3]);
--
-- /*
-- * Verified IP address (from the perspective of Oscar).
-- *
-- * This is added by the server.
-- */
-- tlv = aim_tlv_gettlv(list2, 0x0004, 1);
-- if ((tlv != NULL) && (tlv->length == 4))
-- snprintf(verifiedip, sizeof(verifiedip), "%hhu.%hhu.%hhu.%hhu",
-- tlv->value[0], tlv->value[1],
-- tlv->value[2], tlv->value[3]);
--
-- /*
-- * Port number for something.
-- */
-- if (aim_tlv_gettlv(list2, 0x0005, 1))
-- args.port = aim_tlv_get16(list2, 0x0005, 1);
--
-- /*
-- * File transfer "request number":
-- * 0x0001 - Initial file transfer request for no proxy or stage 1 proxy
-- * 0x0002 - "Reply request" for a stage 2 proxy (receiver wants to use proxy)
-- * 0x0003 - A third request has been sent; applies only to stage 3 proxied transfers
-- */
-- if (aim_tlv_gettlv(list2, 0x000a, 1))
-- args.requestnumber = aim_tlv_get16(list2, 0x000a, 1);
--
-- /*
-- * Terminate connection/error code. 0x0001 means the other user
-- * cancelled the connection.
-- */
-- if (aim_tlv_gettlv(list2, 0x000b, 1))
-- args.errorcode = aim_tlv_get16(list2, 0x000b, 1);
--
-- /*
-- * Invitation message / chat description.
-- */
-- if (aim_tlv_gettlv(list2, 0x000c, 1)) {
-- args.msg = aim_tlv_getstr(list2, 0x000c, 1);
-- args.msglen = aim_tlv_getlength(list2, 0x000c, 1);
-- }
--
-- /*
-- * Character set.
-- */
-- if (aim_tlv_gettlv(list2, 0x000d, 1))
-- args.encoding = aim_tlv_getstr(list2, 0x000d, 1);
--
-- /*
-- * Language.
-- */
-- if (aim_tlv_gettlv(list2, 0x000e, 1))
-- args.language = aim_tlv_getstr(list2, 0x000e, 1);
--
-- /*
-- * Flag meaning we should proxy the file transfer through an AIM server
-- */
-- if (aim_tlv_gettlv(list2, 0x0010, 1))
-- args.use_proxy = TRUE;
--
-- if (strlen(proxyip))
-- args.proxyip = (char *)proxyip;
-- if (strlen(clientip))
-- args.clientip = (char *)clientip;
-- if (strlen(verifiedip))
-- args.verifiedip = (char *)verifiedip;
--
-- /*
-- * This must be present in PROPOSALs, but will probably not
-- * exist in CANCELs and ACCEPTs. Also exists in ICQ Lite
-- * Beta 4.0 URLs (OSCAR_CAPABILITY_ICQSERVERRELAY).
-- *
-- * Service Data blocks are module-specific in format.
-- */
-- if ((servdatatlv = aim_tlv_gettlv(list2, 0x2711 /* 10001 */, 1))) {
--
-- byte_stream_init(&sdbs, servdatatlv->value, servdatatlv->length);
-- sdbsptr = &sdbs;
--
-- /*
-- * The rest of the handling depends on what type it is.
-- *
-- * Not all of them have special handling (yet).
-- */
-- if (args.type & OSCAR_CAPABILITY_BUDDYICON)
-- incomingim_ch2_buddyicon(od, conn, mod, frame, snac, userinfo, &args, sdbsptr);
-- else if (args.type & OSCAR_CAPABILITY_SENDBUDDYLIST)
-- incomingim_ch2_buddylist(od, conn, mod, frame, snac, userinfo, &args, sdbsptr);
-- else if (args.type & OSCAR_CAPABILITY_CHAT)
-- incomingim_ch2_chat(od, conn, mod, frame, snac, userinfo, &args, sdbsptr);
-- else if (args.type & OSCAR_CAPABILITY_ICQSERVERRELAY)
-- incomingim_ch2_icqserverrelay(od, conn, mod, frame, snac, userinfo, &args, sdbsptr);
-- else if (args.type & OSCAR_CAPABILITY_SENDFILE)
-- incomingim_ch2_sendfile(od, conn, mod, frame, snac, userinfo, &args, sdbsptr);
-- }
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, channel, userinfo, &args);
--
--
-- if (args.destructor)
-- ((ch2_args_destructor_t)args.destructor)(od, &args);
--
-- g_free((char *)args.msg);
-- g_free((char *)args.encoding);
-- g_free((char *)args.language);
--
-- aim_tlvlist_free(list2);
--
-- return ret;
--}
--
--static int incomingim_ch4(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, GSList *tlvlist, guint8 *cookie)
--{
-- ByteStream meat;
-- aim_rxcallback_t userfunc;
-- aim_tlv_t *block;
-- struct aim_incomingim_ch4_args args;
-- int ret = 0;
--
-- /*
-- * Make a bstream for the meaty part. Yum. Meat.
-- */
-- if (!(block = aim_tlv_gettlv(tlvlist, 0x0005, 1)))
-- return -1;
-- byte_stream_init(&meat, block->value, block->length);
--
-- args.uin = byte_stream_getle32(&meat);
-- args.type = byte_stream_getle8(&meat);
-- args.flags = byte_stream_getle8(&meat);
-- if (args.type == 0x1a)
-- /* There seems to be a problem with the length in SMS msgs from server, this fixed it */
-- args.msglen = block->length - 6;
-- else
-- args.msglen = byte_stream_getle16(&meat);
-- args.msg = (gchar *)byte_stream_getraw(&meat, args.msglen);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, channel, userinfo, &args);
--
-- g_free(args.msg);
--
-- return ret;
--}
--
--/*
-- * Subtype 0x0007
-- *
-- * It can easily be said that parsing ICBMs is THE single
-- * most difficult thing to do in the in AIM protocol. In
-- * fact, I think I just did say that.
-- *
-- * Below is the best damned solution I've come up with
-- * over the past sixteen months of battling with it. This
-- * can parse both away and normal messages from every client
-- * I have access to. Its not fast, its not clean. But it works.
-- *
-- */
--static int incomingim(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- guchar *cookie;
-- guint16 channel;
-- aim_userinfo_t userinfo;
--
-- memset(&userinfo, 0x00, sizeof(aim_userinfo_t));
--
-- /*
-- * Read ICBM Cookie.
-- */
-- cookie = byte_stream_getraw(bs, 8);
--
-- /*
-- * Channel ID.
-- *
-- * Channel 0x0001 is the message channel. It is
-- * used to send basic ICBMs.
-- *
-- * Channel 0x0002 is the Rendezvous channel, which
-- * is where Chat Invitiations and various client-client
-- * connection negotiations come from.
-- *
-- * Channel 0x0003 is used for chat messages.
-- *
-- * Channel 0x0004 is used for ICQ authorization, or
-- * possibly any system notice.
-- *
-- */
-- channel = byte_stream_get16(bs);
--
-- /*
-- * Extract the standard user info block.
-- *
-- * Note that although this contains TLVs that appear contiguous
-- * with the TLVs read below, they are two different pieces. The
-- * userinfo block contains the number of TLVs that contain user
-- * information, the rest are not even though there is no separation.
-- * You can start reading the message TLVs after aim_info_extract()
-- * parses out the standard userinfo block.
-- *
-- * That also means that TLV types can be duplicated between the
-- * userinfo block and the rest of the message, however there should
-- * never be two TLVs of the same type in one block.
-- *
-- */
-- aim_info_extract(od, bs, &userinfo);
--
-- /*
-- * From here on, its depends on what channel we're on.
-- *
-- * Technically all channels have a TLV list have this, however,
-- * for the common channel 1 case, in-place parsing is used for
-- * performance reasons (less memory allocation).
-- */
-- if (channel == 1) {
--
-- ret = incomingim_ch1(od, conn, mod, frame, snac, channel, &userinfo, bs, cookie);
--
-- } else if (channel == 2) {
-- GSList *tlvlist;
--
-- /*
-- * Read block of TLVs (not including the userinfo data). All
-- * further data is derived from what is parsed here.
-- */
-- tlvlist = aim_tlvlist_read(bs);
--
-- ret = incomingim_ch2(od, conn, mod, frame, snac, channel, &userinfo, tlvlist, cookie);
--
-- aim_tlvlist_free(tlvlist);
--
-- } else if (channel == 4) {
-- GSList *tlvlist;
--
-- tlvlist = aim_tlvlist_read(bs);
-- ret = incomingim_ch4(od, conn, mod, frame, snac, channel, &userinfo, tlvlist, cookie);
-- aim_tlvlist_free(tlvlist);
--
-- } else {
-- purple_debug_misc("oscar", "icbm: ICBM received on an unsupported channel. Ignoring. (chan = %04x)\n", channel);
-- }
--
-- aim_info_free(&userinfo);
-- g_free(cookie);
--
-- return ret;
--}
--
--/* Subtype 0x000a */
--static int missedcall(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- guint16 channel, nummissed, reason;
-- aim_userinfo_t userinfo;
--
-- while (byte_stream_bytes_left(bs)) {
--
-- channel = byte_stream_get16(bs);
-- aim_info_extract(od, bs, &userinfo);
-- nummissed = byte_stream_get16(bs);
-- reason = byte_stream_get16(bs);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, channel, &userinfo, nummissed, reason);
--
-- aim_info_free(&userinfo);
-- }
--
-- return ret;
--}
--
--/*
-- * Subtype 0x000b
-- *
-- * Possible codes:
-- * AIM_TRANSFER_DENY_DECLINE -- "client has declined transfer"
-- *
-- */
--int aim_im_denytransfer(OscarData *od, const char *bn, const guchar *cookie, guint16 code)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- GSList *tlvlist = NULL;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
-- return -EINVAL;
--
-- byte_stream_new(&bs, 8+2+1+strlen(bn)+6);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x000b, 0x0000, NULL, 0);
--
-- byte_stream_putraw(&bs, cookie, 8);
--
-- byte_stream_put16(&bs, 0x0002); /* channel */
-- byte_stream_put8(&bs, strlen(bn));
-- byte_stream_putstr(&bs, bn);
--
-- aim_tlvlist_add_16(&tlvlist, 0x0003, code);
-- aim_tlvlist_write(&bs, &tlvlist);
-- aim_tlvlist_free(tlvlist);
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x000b, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x000b.
-- * Send confirmation for a channel 2 message (Miranda wants it by default).
-- */
--void
--aim_im_send_icq_confirmation(OscarData *od, const char *bn, const guchar *cookie)
--{
-- ByteStream bs;
-- aim_snacid_t snacid;
-- guint32 header_size, data_size;
-- guint16 cookie2 = (guint16)g_random_int();
--
-- purple_debug_misc("oscar", "Sending message ack to %s\n", bn);
--
-- header_size = 8 + 2 + 1 + strlen(bn) + 2;
-- data_size = 2 + 1 + 16 + 4*2 + 2*3 + 4*3 + 1*2 + 2*3 + 1;
-- byte_stream_new(&bs, header_size + data_size);
--
-- /* The message header. */
-- aim_im_puticbm(&bs, cookie, 0x0002, bn);
-- byte_stream_put16(&bs, 0x0003); /* reason */
--
-- /* The actual message. */
-- byte_stream_putle16(&bs, 0x1b); /* subheader #1 length */
-- byte_stream_put8(&bs, 0x08); /* protocol version */
-- byte_stream_putcaps(&bs, OSCAR_CAPABILITY_EMPTY);
-- byte_stream_put32(&bs, 0x3); /* client features */
-- byte_stream_put32(&bs, 0x0004); /* DC type */
-- byte_stream_put16(&bs, cookie2); /* a cookie, chosen by fair dice roll */
-- byte_stream_putle16(&bs, 0x0e); /* header #2 len? */
-- byte_stream_put16(&bs, cookie2); /* the same cookie again */
-- byte_stream_put32(&bs, 0); /* unknown */
-- byte_stream_put32(&bs, 0); /* unknown */
-- byte_stream_put32(&bs, 0); /* unknown */
-- byte_stream_put8(&bs, 0x01); /* plain text message */
-- byte_stream_put8(&bs, 0x00); /* no message flags */
-- byte_stream_put16(&bs, 0x0000); /* no icq status */
-- byte_stream_put16(&bs, 0x0100); /* priority */
-- byte_stream_putle16(&bs, 1); /* query message len */
-- byte_stream_put8(&bs, 0x00); /* empty query message */
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x000b, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, flap_connection_findbygroup(od, SNAC_FAMILY_ICBM), SNAC_FAMILY_ICBM, 0x000b, snacid, &bs);
-- byte_stream_destroy(&bs);
--}
--
--/*
-- * Subtype 0x000b - Receive the response from an ICQ status message
-- * request (in which case this contains the ICQ status message) or
-- * a file transfer or direct IM request was declined.
-- */
--static int clientautoresp(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- guint16 channel, reason;
-- char *bn;
-- guchar *cookie;
-- guint8 bnlen;
-- char *xml = NULL;
-- guint16 hdrlen;
-- int curpos;
-- guint16 num1, num2;
-- PurpleAccount *account;
-- PurpleBuddy *buddy;
-- PurplePresence *presence;
-- PurpleStatus *status;
--
-- cookie = byte_stream_getraw(bs, 8);
-- channel = byte_stream_get16(bs);
-- bnlen = byte_stream_get8(bs);
-- bn = byte_stream_getstr(bs, bnlen);
-- reason = byte_stream_get16(bs);
--
-- if (channel == 0x0002)
-- {
-- hdrlen = byte_stream_getle16(bs);
-- if (hdrlen == 27 && bs->len > (27 + 51)) {
-- byte_stream_advance(bs, 51);
-- num1 = byte_stream_getle16(bs);
-- num2 = byte_stream_getle16(bs);
-- purple_debug_misc("oscar", "X-Status: num1 %hu, num2 %hu\n", num1, num2);
--
-- if (num1 == 0x4f00 && num2 == 0x3b00) {
-- byte_stream_advance(bs, 86);
-- curpos = byte_stream_curpos(bs);
-- xml = byte_stream_getstr(bs, bs->len - curpos);
-- purple_debug_misc("oscar", "X-Status: Received XML reply\n");
-- if (xml) {
-- GString *xstatus;
-- char *tmp1, *tmp2, *unescaped_xstatus;
--
-- /* purple_debug_misc("oscar", "X-Status: XML reply: %s\n", xml); */
--
-- xstatus = g_string_new(NULL);
--
-- tmp1 = strstr(xml, "&lt;title&gt;");
-- if (tmp1 != NULL) {
-- tmp1 += 13;
-- tmp2 = strstr(tmp1, "&lt;/title&gt;");
-- if (tmp2 != NULL)
-- g_string_append_len(xstatus, tmp1, tmp2 - tmp1);
-- }
-- tmp1 = strstr(xml, "&lt;desc&gt;");
-- if (tmp1 != NULL) {
-- tmp1 += 12;
-- tmp2 = strstr(tmp1, "&lt;/desc&gt;");
-- if (tmp2 != NULL) {
-- if (xstatus->len > 0 && tmp2 > tmp1)
-- g_string_append(xstatus, " - ");
-- g_string_append_len(xstatus, tmp1, tmp2 - tmp1);
-- }
-- }
-- unescaped_xstatus = purple_unescape_text(xstatus->str);
-- g_string_free(xstatus, TRUE);
-- if (*unescaped_xstatus) {
-- purple_debug_misc("oscar", "X-Status reply: %s\n", unescaped_xstatus);
-- account = purple_connection_get_account(od->gc);
-- buddy = purple_find_buddy(account, bn);
-- presence = purple_buddy_get_presence(buddy);
-- status = purple_presence_get_status(presence, "mood");
-- if (status) {
-- purple_prpl_got_user_status(account, bn,
-- "mood",
-- PURPLE_MOOD_NAME, purple_status_get_attr_string(status, PURPLE_MOOD_NAME),
-- PURPLE_MOOD_COMMENT, unescaped_xstatus, NULL);
-- }
-- }
-- g_free(unescaped_xstatus);
-- } else {
-- purple_debug_misc("oscar", "X-Status: Can't get XML reply string\n");
-- }
-- } else {
-- purple_debug_misc("oscar", "X-Status: 0x0004, 0x000b not an xstatus reply\n");
-- }
--
-- }
--
-- } else if (channel == 0x0004) { /* ICQ message */
-- switch (reason) {
-- case 0x0003: { /* ICQ status message. Maybe other stuff too, you never know with these people. */
-- guint8 statusmsgtype, *msg;
-- guint16 len;
-- guint32 state;
--
-- len = byte_stream_getle16(bs); /* Should be 0x001b */
-- byte_stream_advance(bs, len); /* Unknown */
--
-- len = byte_stream_getle16(bs); /* Should be 0x000e */
-- byte_stream_advance(bs, len); /* Unknown */
--
-- statusmsgtype = byte_stream_getle8(bs);
-- switch (statusmsgtype) {
-- case 0xe8:
-- state = AIM_ICQ_STATE_AWAY;
-- break;
-- case 0xe9:
-- state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY;
-- break;
-- case 0xea:
-- state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_OUT;
-- break;
-- case 0xeb:
-- state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY;
-- break;
-- case 0xec:
-- state = AIM_ICQ_STATE_CHAT;
-- break;
-- default:
-- state = 0;
-- break;
-- }
--
-- byte_stream_getle8(bs); /* Unknown - 0x03 Maybe this means this is an auto-reply */
-- byte_stream_getle16(bs); /* Unknown - 0x0000 */
-- byte_stream_getle16(bs); /* Unknown - 0x0000 */
--
-- len = byte_stream_getle16(bs);
-- msg = byte_stream_getraw(bs, len);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, channel, bn, reason, state, msg);
--
-- g_free(msg);
-- } break;
--
-- default: {
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, channel, bn, reason);
-- } break;
-- } /* end switch */
-- }
--
-- g_free(cookie);
-- g_free(bn);
-- g_free(xml);
--
-- return ret;
--}
--
--/*
-- * Subtype 0x000c - Receive an ack after sending an ICBM. The ack contains the ICBM header of the message you sent.
-- */
--static int msgack(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- guint16 ch;
-- guchar *cookie;
-- char *bn;
-- int ret = 0;
--
-- cookie = byte_stream_getraw(bs, 8);
-- ch = byte_stream_get16(bs);
-- bn = byte_stream_getstr(bs, byte_stream_get8(bs));
--
-- purple_debug_info("oscar", "Sent message to %s.\n", bn);
--
-- g_free(bn);
-- g_free(cookie);
--
-- return ret;
--}
--
--/*
-- * Subtype 0x0010 - Request any offline messages that are waiting for
-- * us. This is the "new" way of handling offline messages which is
-- * used for both AIM and ICQ. The old way is to use the ugly
-- * aim_icq_reqofflinemsgs() function, but that is no longer necessary.
-- *
-- * We set the 0x00000100 flag on the ICBM message parameters, which
-- * tells the oscar servers that we support offline messages. When we
-- * set that flag the servers do not automatically send us offline
-- * messages. Instead we must request them using this function. This
-- * should happen after sending the 0x0001/0x0002 "client online" SNAC.
-- */
--int aim_im_reqofflinemsgs(OscarData *od)
--{
-- FlapConnection *conn;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, 0x0002)))
-- return -EINVAL;
--
-- aim_genericreq_n(od, conn, SNAC_FAMILY_ICBM, 0x0010);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0014 - Send a mini typing notification (mtn) packet.
-- *
-- * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer,
-- * and Purple 0.60 and newer.
-- *
-- */
--int aim_im_sendmtn(OscarData *od, guint16 channel, const char *bn, guint16 event)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, 0x0002)))
-- return -EINVAL;
--
-- if (!bn)
-- return -EINVAL;
--
-- byte_stream_new(&bs, 11 + strlen(bn) + 2);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0014, 0x0000, NULL, 0);
--
-- /* ICBM cookie */
-- byte_stream_put32(&bs, 0x00000000);
-- byte_stream_put32(&bs, 0x00000000);
--
-- /*
-- * Channel (should be 0x0001 for mtn)
-- */
-- byte_stream_put16(&bs, channel);
--
-- /*
-- * Dest buddy name
-- */
-- byte_stream_put8(&bs, strlen(bn));
-- byte_stream_putstr(&bs, bn);
--
-- /*
-- * Event (should be 0x0000, 0x0001, or 0x0002 for mtn)
-- */
-- byte_stream_put16(&bs, event);
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0014, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0006 - Send eXtra Status request
-- */
--int icq_im_xstatus_request(OscarData *od, const char *sn)
--{
-- FlapConnection *conn;
-- aim_snacid_t snacid;
-- guchar cookie[8];
-- GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
-- ByteStream bs, header, plugindata;
-- PurpleAccount *account;
-- const char *fmt;
-- char *statxml;
-- int xmllen;
--
-- static const guint8 pluginid[] = {
-- 0x09, 0x46, 0x13, 0x49, 0x4C, 0x7F, 0x11, 0xD1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00
-- };
--
-- static const guint8 c_plugindata[] = {
-- 0x1B, 0x00, 0x0A,
-- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-- 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xF9, 0xD1, 0x0E, 0x00, 0xF9, 0xD1, 0x00, 0x00,
-- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x01, 0x00,
-- 0x01, 0x00, 0x00, 0x4F, 0x00, 0x3B, 0x60, 0xB3, 0xEF, 0xD8, 0x2A, 0x6C, 0x45, 0xA4, 0xE0, 0x9C,
-- 0x5A, 0x5E, 0x67, 0xE8, 0x65, 0x08, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x53, 0x63, 0x72, 0x69, 0x70,
-- 0x74, 0x20, 0x50, 0x6C, 0x75, 0x67, 0x2D, 0x69, 0x6E, 0x3A, 0x20, 0x52, 0x65, 0x6D, 0x6F, 0x74,
-- 0x65, 0x20, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41,
-- 0x72, 0x72, 0x69, 0x76, 0x65, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-- 0x00, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00
-- };
--
-- if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)))
-- return -EINVAL;
--
-- if (!sn)
-- return -EINVAL;
--
-- fmt = "<N><QUERY>&lt;Q&gt;&lt;PluginID&gt;srvMng&lt;/PluginID&gt;&lt;/Q&gt;</QUERY><NOTIFY>&lt;srv&gt;&lt;id&gt;cAwaySrv&lt;/id&gt;&lt;req&gt;&lt;id&gt;AwayStat&lt;/id&gt;&lt;trans&gt;2&lt;/trans&gt;&lt;senderId&gt;%s&lt;/senderId&gt;&lt;/req&gt;&lt;/srv&gt;</NOTIFY></N>\r\n";
--
-- account = purple_connection_get_account(od->gc);
--
-- statxml = g_strdup_printf(fmt, account->username);
-- xmllen = strlen(statxml);
--
-- aim_icbm_makecookie(cookie);
--
-- byte_stream_new(&bs, 10 + 8 + 2 + 1 + strlen(sn) + 2
-- + 2 + 2 + 8 + 16 + 2 + 2 + 2 + 2 + 2
-- + 2 + 2 + sizeof(c_plugindata) + xmllen
-- + 2 + 2);
--
-- snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
-- aim_im_puticbm(&bs, cookie, 0x0002, sn);
--
-- byte_stream_new(&header, (7*2) + 16 + 8 + 2 + sizeof(c_plugindata) + xmllen); /* TLV 0x0005 Stream + Size */
-- byte_stream_put16(&header, 0x0000); /* Message Type: Request */
-- byte_stream_putraw(&header, cookie, sizeof(cookie)); /* Message ID */
-- byte_stream_putraw(&header, pluginid, sizeof(pluginid)); /* Plugin ID */
--
-- aim_tlvlist_add_16(&inner_tlvlist, 0x000a, 0x0001);
-- aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
--
-- /* Add Plugin Specific Data */
-- byte_stream_new(&plugindata, (sizeof(c_plugindata) + xmllen));
-- byte_stream_putraw(&plugindata, c_plugindata, sizeof(c_plugindata)); /* Content of TLV 0x2711 */
-- byte_stream_putraw(&plugindata, (const guint8*)statxml, xmllen);
--
-- aim_tlvlist_add_raw(&inner_tlvlist, 0x2711, (sizeof(c_plugindata) + xmllen), plugindata.data);
--
-- aim_tlvlist_write(&header, &inner_tlvlist);
-- aim_tlvlist_free(inner_tlvlist);
--
-- aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&header), header.data);
-- aim_tlvlist_add_noval(&outer_tlvlist, 0x0003); /* Empty TLV 0x0003 */
--
-- aim_tlvlist_write(&bs, &outer_tlvlist);
--
-- purple_debug_misc("oscar", "X-Status Request\n");
-- flap_connection_send_snac_with_priority(od, conn, 0x0004, 0x0006, snacid, &bs, TRUE);
--
-- aim_tlvlist_free(outer_tlvlist);
-- byte_stream_destroy(&header);
-- byte_stream_destroy(&plugindata);
-- byte_stream_destroy(&bs);
-- g_free(statxml);
--
-- return 0;
--}
--
--int icq_relay_xstatus(OscarData *od, const char *sn, const guchar *cookie)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- PurpleAccount *account;
-- PurpleStatus *status;
-- const char *fmt;
-- const char *formatted_msg;
-- char *msg;
-- char *statxml;
-- const char *title;
-- int len;
--
-- static const guint8 plugindata[] = {
-- 0x1B, 0x00,
-- 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-- 0x01, 0x00, 0x00, 0x00, 0x00, 0xF9, 0xD1, 0x0E, 0x00, 0xF9, 0xD1,
-- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-- 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x4F,
-- 0x00, 0x3B, 0x60, 0xB3, 0xEF, 0xD8, 0x2A, 0x6C, 0x45, 0xA4, 0xE0,
-- 0x9C, 0x5A, 0x5E, 0x67, 0xE8, 0x65, 0x08, 0x00, 0x2A, 0x00, 0x00,
-- 0x00, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x50, 0x6C, 0x75,
-- 0x67, 0x2D, 0x69, 0x6E, 0x3A, 0x20, 0x52, 0x65, 0x6D, 0x6F, 0x74,
-- 0x65, 0x20, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
-- 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x72, 0x72, 0x69, 0x76, 0x65, 0x00,
-- 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-- 0x00, 0x00, 0x00, 0xF3, 0x01, 0x00, 0x00, 0xEF, 0x01, 0x00, 0x00
-- };
--
-- fmt = "<NR><RES>&lt;ret event='OnRemoteNotification'&gt;&lt;srv&gt;&lt;id&gt;cAwaySrv&lt;/id&gt;&lt;val srv_id='cAwaySrv'&gt;&lt;Root&gt;&lt;CASXtraSetAwayMessage&gt;&lt;/CASXtraSetAwayMessage&gt;&l t;uin&gt;%s&lt;/uin&gt;&lt;index&gt;1&lt;/index&gt;&lt;title&gt;%s&lt;/title&gt;&lt;desc&gt;%s&lt;/desc&gt;&lt;/Root&gt;&lt;/val&gt;&lt;/srv&gt;&lt;srv&gt;&lt;id&gt;cRandomizerSrv&lt;/id&gt;&lt;val srv_id='cRandomizerSrv'&gt;undefined&lt;/val&gt;&lt;/srv&gt;&lt;/ret&gt;</RES></NR>\r\n";
--
-- if (!od || !(conn = flap_connection_findbygroup(od, 0x0002)))
-- return -EINVAL;
--
-- if (!sn)
-- return -EINVAL;
--
-- account = purple_connection_get_account(od->gc);
-- if (!account)
-- return -EINVAL;
--
-- /* if (!strcmp(account->username, sn))
-- icq_im_xstatus_request(od, sn); */
--
-- status = purple_presence_get_active_status(account->presence);
-- if (!status)
-- return -EINVAL;
--
-- title = purple_status_get_name(status);
-- if (!title)
-- return -EINVAL;
--
-- formatted_msg = purple_status_get_attr_string(status, "message");
-- if (!formatted_msg)
-- return -EINVAL;
--
-- msg = purple_markup_strip_html(formatted_msg);
-- if (!msg)
-- return -EINVAL;
--
-- statxml = g_strdup_printf(fmt, account->username, title, msg);
-- len = strlen(statxml);
--
-- purple_debug_misc("oscar", "X-Status AutoReply: %s, %s\n", formatted_msg, msg);
--
-- byte_stream_new(&bs, 10 + 8 + 2 + 1 + strlen(sn) + 2 + sizeof(plugindata) + len); /* 16 extra */
--
-- snacid = aim_cachesnac(od, 0x0004, 0x000b, 0x0000, NULL, 0);
-- aim_im_puticbm(&bs, cookie, 0x0002, sn);
-- byte_stream_put16(&bs, 0x0003);
-- byte_stream_putraw(&bs, plugindata, sizeof(plugindata));
-- byte_stream_putraw(&bs, (const guint8*)statxml, len);
--
-- flap_connection_send_snac_with_priority(od, conn, 0x0004, 0x000b, snacid, &bs, TRUE);
--
-- g_free(statxml);
-- g_free(msg);
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0014 - Receive a mini typing notification (mtn) packet.
-- *
-- * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer,
-- * and Purple 0.60 and newer.
-- *
-- */
--static int mtn_receive(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- char *bn;
-- guint8 bnlen;
-- guint16 channel, event;
--
-- byte_stream_advance(bs, 8); /* ICBM cookie */
-- channel = byte_stream_get16(bs);
-- bnlen = byte_stream_get8(bs);
-- bn = byte_stream_getstr(bs, bnlen);
-- event = byte_stream_get16(bs);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, channel, bn, event);
--
-- g_free(bn);
--
-- return ret;
--}
--
--static int
--snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- if (snac->subtype == 0x0001)
-- return error(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x0005)
-- return aim_im_paraminfo(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x0007)
-- return incomingim(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x000a)
-- return missedcall(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x000b)
-- return clientautoresp(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x000c)
-- return msgack(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x0014)
-- return mtn_receive(od, conn, mod, frame, snac, bs);
--
-- return 0;
--}
--
--int
--msg_modfirst(OscarData *od, aim_module_t *mod)
--{
-- mod->family = SNAC_FAMILY_ICBM;
-- mod->version = 0x0001;
-- mod->toolid = 0x0110;
-- mod->toolversion = 0x0629;
-- mod->flags = 0;
-- strncpy(mod->name, "messaging", sizeof(mod->name));
-- mod->snachandler = snachandler;
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_icq.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_icq.c
---- pidgin-2.10.7/libpurple/protocols/oscar/family_icq.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_icq.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,793 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Family 0x0015 - Encapsulated ICQ.
-- *
-- */
--
--#include "encoding.h"
--#include "oscar.h"
--
--#define AIM_ICQ_INFO_REQUEST 0x04b2
--#define AIM_ICQ_ALIAS_REQUEST 0x04ba
--
--static
--int compare_icq_infos(gconstpointer a, gconstpointer b)
--{
-- const struct aim_icq_info* aa = a;
-- const guint16* bb = b;
-- return aa->reqid - *bb;
--}
--
--static void aim_icq_freeinfo(struct aim_icq_info *info) {
-- int i;
--
-- if (!info)
-- return;
-- g_free(info->nick);
-- g_free(info->first);
-- g_free(info->last);
-- g_free(info->email);
-- g_free(info->homecity);
-- g_free(info->homestate);
-- g_free(info->homephone);
-- g_free(info->homefax);
-- g_free(info->homeaddr);
-- g_free(info->mobile);
-- g_free(info->homezip);
-- g_free(info->personalwebpage);
-- if (info->email2)
-- for (i = 0; i < info->numaddresses; i++)
-- g_free(info->email2[i]);
-- g_free(info->email2);
-- g_free(info->workcity);
-- g_free(info->workstate);
-- g_free(info->workphone);
-- g_free(info->workfax);
-- g_free(info->workaddr);
-- g_free(info->workzip);
-- g_free(info->workcompany);
-- g_free(info->workdivision);
-- g_free(info->workposition);
-- g_free(info->workwebpage);
-- g_free(info->info);
-- g_free(info->status_note_title);
-- g_free(info->auth_request_reason);
--}
--
--static
--int error(OscarData *od, aim_modsnac_t *error_snac, ByteStream *bs)
--{
-- aim_snac_t *original_snac = aim_remsnac(od, error_snac->id);
-- guint16 *request_type;
-- GSList *original_info_ptr;
-- struct aim_icq_info *original_info;
-- guint16 reason;
-- gchar *uin;
--
-- if (!original_snac || (original_snac->family != SNAC_FAMILY_ICQ) || !original_snac->data) {
-- purple_debug_misc("oscar", "icq: the original snac for the error packet was not found");
-- g_free(original_snac);
-- return 0;
-- }
--
-- request_type = original_snac->data;
-- original_info_ptr = g_slist_find_custom(od->icq_info, &original_snac->id, compare_icq_infos);
--
-- if (!original_info_ptr) {
-- purple_debug_misc("oscar", "icq: the request info for the error packet was not found");
-- g_free(original_snac);
-- return 0;
-- }
--
-- original_info = original_info_ptr->data;
--
-- reason = byte_stream_get16(bs);
-- uin = g_strdup_printf("%u", original_info->uin);
-- switch (*request_type) {
-- case AIM_ICQ_INFO_REQUEST:
-- oscar_user_info_display_error(od, reason, uin);
-- break;
-- case AIM_ICQ_ALIAS_REQUEST:
-- /* Couldn't retrieve an alias for the buddy requesting authorization; have to make do with UIN only. */
-- if (original_info->for_auth_request)
-- oscar_auth_recvrequest(od->gc, uin, NULL, original_info->auth_request_reason);
-- break;
-- default:
-- purple_debug_misc("oscar", "icq: got an error packet with unknown request type %u", *request_type);
-- break;
-- }
--
-- aim_icq_freeinfo(original_info);
-- od->icq_info = g_slist_remove(od->icq_info, original_info_ptr);
-- g_free(original_snac->data);
-- g_free(original_snac);
-- return 1;
--}
--
--int
--aim_icq_setsecurity(OscarData *od, gboolean auth_required, gboolean webaware)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- int bslen;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
-- return -EINVAL;
--
-- bslen = 2+4+2+2+2+2+2+1+1+1+1+1+1;
--
-- byte_stream_new(&bs, 4 + bslen);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
--
-- /* For simplicity, don't bother using a tlvlist */
-- byte_stream_put16(&bs, 0x0001);
-- byte_stream_put16(&bs, bslen);
--
-- byte_stream_putle16(&bs, bslen - 2);
-- byte_stream_putuid(&bs, od);
-- byte_stream_putle16(&bs, 0x07d0); /* I command thee. */
-- byte_stream_putle16(&bs, snacid); /* eh. */
-- byte_stream_putle16(&bs, 0x0c3a); /* shrug. */
-- byte_stream_putle16(&bs, 0x030c);
-- byte_stream_putle16(&bs, 0x0001);
-- byte_stream_putle8(&bs, webaware);
-- byte_stream_putle8(&bs, 0xf8);
-- byte_stream_putle8(&bs, 0x02);
-- byte_stream_putle8(&bs, 0x01);
-- byte_stream_putle8(&bs, 0x00);
-- byte_stream_putle8(&bs, !auth_required);
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/**
-- * Change your ICQ password.
-- *
-- * @param od The oscar session
-- * @param passwd The new password. If this is longer than 8 characters it
-- * will be truncated.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int aim_icq_changepasswd(OscarData *od, const char *passwd)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- int bslen, passwdlen;
--
-- if (!passwd)
-- return -EINVAL;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
-- return -EINVAL;
--
-- passwdlen = strlen(passwd);
-- if (passwdlen > MAXICQPASSLEN)
-- passwdlen = MAXICQPASSLEN;
-- bslen = 2+4+2+2+2+2+passwdlen+1;
--
-- byte_stream_new(&bs, 4 + bslen);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
--
-- /* For simplicity, don't bother using a tlvlist */
-- byte_stream_put16(&bs, 0x0001);
-- byte_stream_put16(&bs, bslen);
--
-- byte_stream_putle16(&bs, bslen - 2);
-- byte_stream_putuid(&bs, od);
-- byte_stream_putle16(&bs, 0x07d0); /* I command thee. */
-- byte_stream_putle16(&bs, snacid); /* eh. */
-- byte_stream_putle16(&bs, 0x042e); /* shrug. */
-- byte_stream_putle16(&bs, passwdlen+1);
-- byte_stream_putraw(&bs, (const guint8 *)passwd, passwdlen);
-- byte_stream_putle8(&bs, '\0');
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--int aim_icq_getallinfo(OscarData *od, const char *uin)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- int bslen;
-- struct aim_icq_info *info;
-- guint16 request_type = AIM_ICQ_INFO_REQUEST;
--
-- if (!uin || uin[0] < '0' || uin[0] > '9')
-- return -EINVAL;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
-- return -EINVAL;
--
-- bslen = 2 + 4 + 2 + 2 + 2 + 4;
--
-- byte_stream_new(&bs, 4 + bslen);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, &request_type, sizeof(request_type));
--
-- /* For simplicity, don't bother using a tlvlist */
-- byte_stream_put16(&bs, 0x0001);
-- byte_stream_put16(&bs, bslen);
--
-- byte_stream_putle16(&bs, bslen - 2);
-- byte_stream_putuid(&bs, od);
-- byte_stream_putle16(&bs, 0x07d0); /* I command thee. */
-- byte_stream_putle16(&bs, snacid); /* eh. */
-- byte_stream_putle16(&bs, request_type); /* shrug. */
-- byte_stream_putle32(&bs, atoi(uin));
--
-- flap_connection_send_snac_with_priority(od, conn, SNAC_FAMILY_ICQ, 0x0002, snacid, &bs, FALSE);
--
-- byte_stream_destroy(&bs);
--
-- /* Keep track of this request and the ICQ number and request ID */
-- info = (struct aim_icq_info *)g_new0(struct aim_icq_info, 1);
-- info->reqid = snacid;
-- info->uin = atoi(uin);
-- od->icq_info = g_slist_prepend(od->icq_info, info);
--
-- return 0;
--}
--
--int aim_icq_getalias(OscarData *od, const char *uin, gboolean for_auth_request, char *auth_request_reason)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- int bslen;
-- struct aim_icq_info *info;
-- guint16 request_type = AIM_ICQ_ALIAS_REQUEST;
--
-- if (!uin || uin[0] < '0' || uin[0] > '9')
-- return -EINVAL;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
-- return -EINVAL;
--
-- purple_debug_info("oscar", "Requesting ICQ alias for %s\n", uin);
--
-- bslen = 2 + 4 + 2 + 2 + 2 + 4;
--
-- byte_stream_new(&bs, 4 + bslen);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, &request_type, sizeof(request_type));
--
-- /* For simplicity, don't bother using a tlvlist */
-- byte_stream_put16(&bs, 0x0001);
-- byte_stream_put16(&bs, bslen);
--
-- byte_stream_putle16(&bs, bslen - 2);
-- byte_stream_putuid(&bs, od);
-- byte_stream_putle16(&bs, 0x07d0); /* I command thee. */
-- byte_stream_putle16(&bs, snacid); /* eh. */
-- byte_stream_putle16(&bs, request_type); /* shrug. */
-- byte_stream_putle32(&bs, atoi(uin));
--
-- flap_connection_send_snac_with_priority(od, conn, SNAC_FAMILY_ICQ, 0x0002, snacid, &bs, FALSE);
--
-- byte_stream_destroy(&bs);
--
-- /* Keep track of this request and the ICQ number and request ID */
-- info = (struct aim_icq_info *)g_new0(struct aim_icq_info, 1);
-- info->reqid = snacid;
-- info->uin = atoi(uin);
-- info->for_auth_request = for_auth_request;
-- info->auth_request_reason = g_strdup(auth_request_reason);
-- od->icq_info = g_slist_prepend(od->icq_info, info);
--
-- return 0;
--}
--
--/*
-- * Send an SMS message. This is the non-US way. The US-way is to IM
-- * their cell phone number (+19195551234).
-- *
-- * We basically construct and send an XML message. The format is:
-- * <icq_sms_message>
-- * <destination>full_phone_without_leading_+</destination>
-- * <text>message</text>
-- * <codepage>1252</codepage>
-- * <senders_UIN>self_uin</senders_UIN>
-- * <senders_name>self_name</senders_name>
-- * <delivery_receipt>Yes|No</delivery_receipt>
-- * <time>Wkd, DD Mmm YYYY HH:MM:SS TMZ</time>
-- * </icq_sms_message>
-- *
-- * Yeah hi Peter, whaaaat's happening. If there's any way to use
-- * a codepage other than 1252 that would be great. Thaaaanks.
-- */
--int aim_icq_sendsms(OscarData *od, const char *name, const char *msg, const char *alias)
--{
-- FlapConnection *conn;
-- PurpleAccount *account;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- int bslen, xmllen;
-- char *xml;
-- const char *timestr, *username;
-- time_t t;
-- struct tm *tm;
-- gchar *stripped;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
-- return -EINVAL;
--
-- if (!name || !msg || !alias)
-- return -EINVAL;
--
-- account = purple_connection_get_account(od->gc);
-- username = purple_account_get_username(account);
--
-- time(&t);
-- tm = gmtime(&t);
-- timestr = purple_utf8_strftime("%a, %d %b %Y %T %Z", tm);
--
-- stripped = purple_markup_strip_html(msg);
--
-- /* The length of xml included the null terminating character */
-- xmllen = 209 + strlen(name) + strlen(stripped) + strlen(username) + strlen(alias) + strlen(timestr) + 1;
--
-- xml = g_new(char, xmllen);
-- snprintf(xml, xmllen, "<icq_sms_message>"
-- "<destination>%s</destination>"
-- "<text>%s</text>"
-- "<codepage>1252</codepage>"
-- "<senders_UIN>%s</senders_UIN>"
-- "<senders_name>%s</senders_name>"
-- "<delivery_receipt>Yes</delivery_receipt>"
-- "<time>%s</time>"
-- "</icq_sms_message>",
-- name, stripped, username, alias, timestr);
--
-- bslen = 36 + xmllen;
--
-- byte_stream_new(&bs, 4 + bslen);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
--
-- /* For simplicity, don't bother using a tlvlist */
-- byte_stream_put16(&bs, 0x0001);
-- byte_stream_put16(&bs, bslen);
--
-- byte_stream_putle16(&bs, bslen - 2);
-- byte_stream_putuid(&bs, od);
-- byte_stream_putle16(&bs, 0x07d0); /* I command thee. */
-- byte_stream_putle16(&bs, snacid); /* eh. */
--
-- /* From libicq200-0.3.2/src/SNAC-SRV.cpp */
-- byte_stream_putle16(&bs, 0x1482);
-- byte_stream_put16(&bs, 0x0001);
-- byte_stream_put16(&bs, 0x0016);
-- byte_stream_put32(&bs, 0x00000000);
-- byte_stream_put32(&bs, 0x00000000);
-- byte_stream_put32(&bs, 0x00000000);
-- byte_stream_put32(&bs, 0x00000000);
--
-- byte_stream_put16(&bs, 0x0000);
-- byte_stream_put16(&bs, xmllen);
-- byte_stream_putstr(&bs, xml);
-- byte_stream_put8(&bs, 0x00);
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- g_free(xml);
-- g_free(stripped);
--
-- return 0;
--}
--
--static void
--gotalias(OscarData *od, struct aim_icq_info *info)
--{
-- PurpleConnection *gc = od->gc;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- PurpleBuddy *b;
-- gchar *utf8 = oscar_utf8_try_convert(account, od, info->nick);
--
-- if (info->for_auth_request) {
-- oscar_auth_recvrequest(gc, g_strdup_printf("%u", info->uin), utf8, info->auth_request_reason);
-- } else {
-- if (utf8 && *utf8) {
-- gchar who[16];
-- g_snprintf(who, sizeof(who), "%u", info->uin);
-- serv_got_alias(gc, who, utf8);
-- if ((b = purple_find_buddy(account, who))) {
-- purple_blist_node_set_string((PurpleBlistNode*)b, "servernick", utf8);
-- }
-- }
-- g_free(utf8);
-- }
--}
--
--/**
-- * Subtype 0x0003 - Response to SNAC_FAMILY_ICQ/0x002, contains an ICQesque packet.
-- */
--static int
--icqresponse(OscarData *od, aim_modsnac_t *snac, ByteStream *bs)
--{
-- GSList *tlvlist;
-- aim_tlv_t *datatlv;
-- ByteStream qbs;
-- guint32 ouruin;
-- guint16 cmdlen, cmd, reqid;
--
-- if (!(tlvlist = aim_tlvlist_read(bs)) || !(datatlv = aim_tlv_gettlv(tlvlist, 0x0001, 1))) {
-- aim_tlvlist_free(tlvlist);
-- purple_debug_misc("oscar", "corrupt ICQ response\n");
-- return 0;
-- }
--
-- byte_stream_init(&qbs, datatlv->value, datatlv->length);
--
-- cmdlen = byte_stream_getle16(&qbs);
-- ouruin = byte_stream_getle32(&qbs);
-- cmd = byte_stream_getle16(&qbs);
-- reqid = byte_stream_getle16(&qbs);
--
-- purple_debug_misc("oscar", "icq response: %d bytes, %u, 0x%04x, 0x%04x\n", cmdlen, ouruin, cmd, reqid);
--
-- if (cmd == 0x07da) { /* information */
-- guint16 subtype;
-- GSList *info_ptr;
-- struct aim_icq_info *info;
--
-- subtype = byte_stream_getle16(&qbs);
-- byte_stream_advance(&qbs, 1); /* 0x0a */
--
-- /* find other data from the same request */
-- info_ptr = g_slist_find_custom(od->icq_info, &reqid, compare_icq_infos);
-- if (!info_ptr) {
-- struct aim_icq_info *new_info = (struct aim_icq_info *)g_new0(struct aim_icq_info, 1);
-- new_info->reqid = reqid;
-- info_ptr = od->icq_info = g_slist_prepend(od->icq_info, new_info);
-- }
--
-- info = info_ptr->data;
-- switch (subtype) {
-- case 0x00a0: { /* hide ip status */
-- /* nothing */
-- } break;
--
-- case 0x00aa: { /* password change status */
-- /* nothing */
-- } break;
--
-- case 0x00c8: { /* general and "home" information */
-- info->nick = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->first = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->last = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->email = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->homecity = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->homestate = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->homephone = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->homefax = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->homeaddr = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->mobile = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->homezip = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->homecountry = byte_stream_getle16(&qbs);
-- /* 0x0a 00 02 00 */
-- /* 1 byte timezone? */
-- /* 1 byte hide email flag? */
-- } break;
--
-- case 0x00dc: { /* personal information */
-- info->age = byte_stream_getle8(&qbs);
-- info->unknown = byte_stream_getle8(&qbs);
-- info->gender = byte_stream_getle8(&qbs); /* Not specified=0x00, Female=0x01, Male=0x02 */
-- info->personalwebpage = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->birthyear = byte_stream_getle16(&qbs);
-- info->birthmonth = byte_stream_getle8(&qbs);
-- info->birthday = byte_stream_getle8(&qbs);
-- info->language1 = byte_stream_getle8(&qbs);
-- info->language2 = byte_stream_getle8(&qbs);
-- info->language3 = byte_stream_getle8(&qbs);
-- /* 0x00 00 01 00 00 01 00 00 00 00 00 */
-- } break;
--
-- case 0x00d2: { /* work information */
-- info->workcity = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->workstate = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->workphone = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->workfax = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->workaddr = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->workzip = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->workcountry = byte_stream_getle16(&qbs);
-- info->workcompany = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->workdivision = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->workposition = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- byte_stream_advance(&qbs, 2); /* 0x01 00 */
-- info->workwebpage = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- } break;
--
-- case 0x00e6: { /* additional personal information */
-- info->info = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)-1);
-- } break;
--
-- case 0x00eb: { /* email address(es) */
-- int i;
-- info->numaddresses = byte_stream_getle16(&qbs);
-- info->email2 = (char **)g_new0(char *, info->numaddresses);
-- for (i = 0; i < info->numaddresses; i++) {
-- info->email2[i] = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- if (i+1 != info->numaddresses)
-- byte_stream_advance(&qbs, 1); /* 0x00 */
-- }
-- } break;
--
-- case 0x00f0: { /* personal interests */
-- } break;
--
-- case 0x00fa: { /* past background and current organizations */
-- } break;
--
-- case 0x0104: { /* alias info */
-- info->nick = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->first = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->last = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- byte_stream_advance(&qbs, byte_stream_getle16(&qbs)); /* email address? */
-- /* Then 0x00 02 00 */
-- } break;
--
-- case 0x010e: { /* unknown */
-- /* 0x00 00 */
-- } break;
--
-- case 0x019a: { /* simple info */
-- byte_stream_advance(&qbs, 2);
-- info->uin = byte_stream_getle32(&qbs);
-- info->nick = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->first = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->last = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- info->email = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
-- /* Then 0x00 02 00 00 00 00 00 */
-- } break;
--
-- /* status note title and send request for status note text */
-- case 0x0fb4: {
-- GSList *tlvlist;
-- aim_tlv_t *tlv;
-- FlapConnection *conn;
-- char *uin = NULL;
-- char *status_note_title = NULL;
--
-- conn = flap_connection_findbygroup(od, 0x0004);
-- if (conn == NULL)
-- {
-- purple_debug_misc("oscar", "icq/0x0fb4: flap connection was not found.\n");
-- break;
-- }
--
-- byte_stream_advance(&qbs, 0x02); /* length */
-- byte_stream_advance(&qbs, 0x2f); /* unknown stuff */
--
-- tlvlist = aim_tlvlist_read(&qbs);
--
-- tlv = aim_tlv_gettlv(tlvlist, 0x0032, 1);
-- if (tlv != NULL)
-- /* Get user number */
-- uin = aim_tlv_getvalue_as_string(tlv);
--
-- tlv = aim_tlv_gettlv(tlvlist, 0x0226, 1);
-- if (tlv != NULL)
-- /* Get status note title */
-- status_note_title = aim_tlv_getvalue_as_string(tlv);
--
-- aim_tlvlist_free(tlvlist);
--
-- if (uin == NULL || status_note_title == NULL)
-- {
-- purple_debug_misc("oscar", "icq/0x0fb4: uin or "
-- "status_note_title was not found\n");
-- g_free(uin);
-- g_free(status_note_title);
-- break;
-- }
--
-- if (status_note_title[0] == '\0')
-- {
-- PurpleAccount *account;
-- PurpleBuddy *buddy;
-- PurplePresence *presence;
-- PurpleStatus *status;
--
-- account = purple_connection_get_account(od->gc);
-- buddy = purple_find_buddy(account, uin);
-- presence = purple_buddy_get_presence(buddy);
-- status = purple_presence_get_active_status(presence);
--
-- purple_prpl_got_user_status(account, uin,
-- purple_status_get_id(status),
-- "message", NULL, NULL);
--
-- g_free(status_note_title);
-- }
-- else
-- {
-- struct aim_icq_info *info;
-- ByteStream bs;
-- guint32 bslen;
-- aim_snacid_t snacid;
-- guchar cookie[8];
--
-- info = g_new0(struct aim_icq_info, 1);
--
-- bslen = 13 + strlen(uin) + 30 + 6 + 4 + 55 + 85 + 4;
-- byte_stream_new(&bs, 4 + bslen);
--
-- snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
--
-- aim_icbm_makecookie(cookie);
--
-- byte_stream_putraw(&bs, cookie, 8); /* ICBM cookie */
-- byte_stream_put16(&bs, 0x0002); /* message channel */
-- byte_stream_put8(&bs, strlen(uin)); /* uin */
-- byte_stream_putstr(&bs, uin);
--
-- byte_stream_put16(&bs, 0x0005); /* rendez vous data */
-- byte_stream_put16(&bs, 0x00b2);
-- byte_stream_put16(&bs, 0x0000); /* request */
-- byte_stream_putraw(&bs, cookie, 8); /* ICBM cookie */
-- byte_stream_put32(&bs, 0x09461349); /* ICQ server relaying */
-- byte_stream_put16(&bs, 0x4c7f);
-- byte_stream_put16(&bs, 0x11d1);
-- byte_stream_put32(&bs, 0x82224445);
-- byte_stream_put32(&bs, 0x53540000);
--
-- byte_stream_put16(&bs, 0x000a); /* unknown TLV */
-- byte_stream_put16(&bs, 0x0002);
-- byte_stream_put16(&bs, 0x0001);
--
-- byte_stream_put16(&bs, 0x000f); /* unknown TLV */
-- byte_stream_put16(&bs, 0x0000);
--
-- byte_stream_put16(&bs, 0x2711); /* extended data */
-- byte_stream_put16(&bs, 0x008a);
-- byte_stream_putle16(&bs, 0x001b); /* length */
-- byte_stream_putle16(&bs, 0x0009); /* version */
-- byte_stream_putle32(&bs, 0x00000000); /* plugin: none */
-- byte_stream_putle32(&bs, 0x00000000);
-- byte_stream_putle32(&bs, 0x00000000);
-- byte_stream_putle32(&bs, 0x00000000);
-- byte_stream_putle16(&bs, 0x0000); /* unknown */
-- byte_stream_putle32(&bs, 0x00000000); /* client capabilities flags */
-- byte_stream_put8(&bs, 0x00); /* unknown */
-- byte_stream_putle16(&bs, 0x0064); /* downcounter? */
-- byte_stream_putle16(&bs, 0x000e); /* length */
-- byte_stream_putle16(&bs, 0x0064); /* downcounter? */
-- byte_stream_putle32(&bs, 0x00000000); /* unknown */
-- byte_stream_putle32(&bs, 0x00000000);
-- byte_stream_putle32(&bs, 0x00000000);
-- byte_stream_put8(&bs, 0x1a); /* message type: plugin message descibed by text string */
-- byte_stream_put8(&bs, 0x00); /* message flags */
-- byte_stream_putle16(&bs, 0x0000); /* status code */
-- byte_stream_putle16(&bs, 0x0001); /* priority code */
-- byte_stream_putle16(&bs, 0x0000); /* text length */
--
-- byte_stream_put8(&bs, 0x3a); /* message dump */
-- byte_stream_put32(&bs, 0x00811a18);
-- byte_stream_put32(&bs, 0xbc0e6c18);
-- byte_stream_put32(&bs, 0x47a5916f);
-- byte_stream_put32(&bs, 0x18dcc76f);
-- byte_stream_put32(&bs, 0x1a010013);
-- byte_stream_put32(&bs, 0x00000041);
-- byte_stream_put32(&bs, 0x77617920);
-- byte_stream_put32(&bs, 0x53746174);
-- byte_stream_put32(&bs, 0x7573204d);
-- byte_stream_put32(&bs, 0x65737361);
-- byte_stream_put32(&bs, 0x67650100);
-- byte_stream_put32(&bs, 0x00000000);
-- byte_stream_put32(&bs, 0x00000000);
-- byte_stream_put32(&bs, 0x00000000);
-- byte_stream_put32(&bs, 0x00000015);
-- byte_stream_put32(&bs, 0x00000000);
-- byte_stream_put32(&bs, 0x0000000d);
-- byte_stream_put32(&bs, 0x00000074);
-- byte_stream_put32(&bs, 0x6578742f);
-- byte_stream_put32(&bs, 0x782d616f);
-- byte_stream_put32(&bs, 0x6c727466);
--
-- byte_stream_put16(&bs, 0x0003); /* server ACK requested */
-- byte_stream_put16(&bs, 0x0000);
--
-- info->uin = atoi(uin);
-- info->status_note_title = status_note_title;
--
-- memcpy(&info->icbm_cookie, cookie, 8);
--
-- od->icq_info = g_slist_prepend(od->icq_info, info);
--
-- flap_connection_send_snac_with_priority(od, conn, 0x0004, 0x0006, snacid, &bs, FALSE);
--
-- byte_stream_destroy(&bs);
-- }
--
-- g_free(uin);
--
-- } break;
--
-- } /* End switch statement */
--
-- if (!(snac->flags & 0x0001)) {
-- if (subtype != 0x0104)
-- oscar_user_info_display_icq(od, info);
--
-- if (info->uin && info->nick)
-- gotalias(od, info);
--
-- aim_icq_freeinfo(info);
-- od->icq_info = g_slist_remove(od->icq_info, info);
-- }
-- }
--
-- aim_tlvlist_free(tlvlist);
--
-- return 1;
--}
--
--static int
--snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- if (snac->subtype == 0x0001)
-- return error(od, snac, bs);
-- else if (snac->subtype == 0x0003)
-- return icqresponse(od, snac, bs);
--
-- return 0;
--}
--
--static void
--icq_shutdown(OscarData *od, aim_module_t *mod)
--{
-- GSList *cur;
-- for (cur = od->icq_info; cur; cur = cur->next)
-- aim_icq_freeinfo(cur->data);
-- g_slist_free(od->icq_info);
--}
--
--int
--icq_modfirst(OscarData *od, aim_module_t *mod)
--{
-- mod->family = SNAC_FAMILY_ICQ;
-- mod->version = 0x0001;
-- mod->toolid = 0x0110;
-- mod->toolversion = 0x047c;
-- mod->flags = 0;
-- strncpy(mod->name, "icq", sizeof(mod->name));
-- mod->snachandler = snachandler;
-- mod->shutdown = icq_shutdown;
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_locate.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_locate.c
---- pidgin-2.10.7/libpurple/protocols/oscar/family_locate.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_locate.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1557 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Family 0x0002 - Locate.
-- *
-- * The functions here are responsible for requesting and parsing information-
-- * gathering SNACs. Or something like that. This family contains the SNACs
-- * for getting and setting info, away messages, directory profile thingy, etc.
-- */
--
--#include "oscar.h"
--#ifdef _WIN32
--#include "win32dep.h"
--#endif
--
--/* Define to log unknown TLVs */
--/* #define LOG_UNKNOWN_TLV */
--
--/*
-- * Capability blocks.
-- *
-- * These are CLSIDs. They should actually be of the form:
-- *
-- * {0x0946134b, 0x4c7f, 0x11d1,
-- * {0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
-- *
-- * But, eh.
-- */
--static const struct {
-- guint64 flag;
-- guint8 data[16];
--} aim_caps[] = {
--
-- /*
-- * These are in ascending numerical order.
-- */
--
-- /* Client understands short caps, a UUID of the form
-- * 0946XXYY-4C7F-11D1-8222-444553540000 where XXYY is the short cap. */
-- {OSCAR_CAPABILITY_SHORTCAPS,
-- {0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_SECUREIM,
-- {0x09, 0x46, 0x00, 0x01, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- /* OSCAR_CAPABILITY_XHTML_IM */
-- {OSCAR_CAPABILITY_GENERICUNKNOWN,
-- {0x09, 0x46, 0x00, 0x02, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_VIDEO,
-- {0x09, 0x46, 0x01, 0x00, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- /* "Live Video" (SIP/RTC Video) support in Windows AIM 5.5.3501 and newer */
-- {OSCAR_CAPABILITY_LIVEVIDEO,
-- {0x09, 0x46, 0x01, 0x01, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- /* "Camera" support in Windows AIM 5.5.3501 and newer */
-- {OSCAR_CAPABILITY_CAMERA,
-- {0x09, 0x46, 0x01, 0x02, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- /* "Microphone" support in Windows AIM 5.5.3501 and newer */
-- /* OSCAR_CAPABILITY_MICROPHONE */
-- {OSCAR_CAPABILITY_GENERICUNKNOWN,
-- {0x09, 0x46, 0x01, 0x03, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- /* Supports RTC Audio */
-- /* OSCAR_CAPABILITY_RTCAUDIO */
-- {OSCAR_CAPABILITY_GENERICUNKNOWN,
-- {0x09, 0x46, 0x01, 0x04, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- /* In iChatAV (version numbers...?) */
-- {OSCAR_CAPABILITY_ICHATAV,
-- {0x09, 0x46, 0x01, 0x05, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x45, 0x53, 0x54, 0x00}},
--
-- /* Supports "new status message features" (Who advertises this one?) */
-- /* OSCAR_CAPABILITY_HOST_STATUS_TEXT_AWARE */
-- {OSCAR_CAPABILITY_GENERICUNKNOWN,
-- {0x09, 0x46, 0x01, 0x0a, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- /* Supports "see as I type" (Who advertises this one?) */
-- /* OSCAR_CAPABILITY_SEE_AS_I_TYPE */
-- {OSCAR_CAPABILITY_GENERICUNKNOWN,
-- {0x09, 0x46, 0x01, 0x0b, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- /* Client only asserts caps for services in which it is participating */
-- /* OSCAR_CAPABILITY_SMARTCAPS */
-- {OSCAR_CAPABILITY_GENERICUNKNOWN,
-- {0x09, 0x46, 0x01, 0xff, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_HIPTOP,
-- {0x09, 0x46, 0x13, 0x23, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_TALK,
-- {0x09, 0x46, 0x13, 0x41, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_SENDFILE,
-- {0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_ICQ_DIRECT,
-- {0x09, 0x46, 0x13, 0x44, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_DIRECTIM,
-- {0x09, 0x46, 0x13, 0x45, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_BUDDYICON,
-- {0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_ADDINS,
-- {0x09, 0x46, 0x13, 0x47, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_GETFILE,
-- {0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_ICQSERVERRELAY,
-- {0x09, 0x46, 0x13, 0x49, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- /*
-- * Indeed, there are two of these. The former appears to be correct,
-- * but in some versions of winaim, the second one is set. Either they
-- * forgot to fix endianness, or they made a typo. It really doesn't
-- * matter which.
-- */
-- {OSCAR_CAPABILITY_GAMES,
-- {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
-- {OSCAR_CAPABILITY_GAMES2,
-- {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x22, 0x82, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- /* New format of caps (xtraz icons) */
-- {OSCAR_CAPABILITY_NEWCAPS,
-- {0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- /* Support xtraz statuses */
-- {OSCAR_CAPABILITY_XTRAZ,
-- {0x1a, 0x09, 0x3c, 0x6c, 0xd7, 0xFD, 0x4e, 0xc5,
-- 0x9d, 0x51, 0xa6, 0x47, 0x4e, 0x34, 0xf5, 0xa0}},
--
-- {OSCAR_CAPABILITY_SENDBUDDYLIST,
-- {0x09, 0x46, 0x13, 0x4b, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- /*
-- * Setting this lets AIM users receive messages from ICQ users, and ICQ
-- * users receive messages from AIM users. It also lets ICQ users show
-- * up in buddy lists for AIM users, and AIM users show up in buddy lists
-- * for ICQ users. And ICQ privacy/invisibility acts like AIM privacy,
-- * in that if you add a user to your deny list, you will not be able to
-- * see them as online (previous you could still see them, but they
-- * couldn't see you.
-- */
-- {OSCAR_CAPABILITY_INTEROPERATE,
-- {0x09, 0x46, 0x13, 0x4d, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_UNICODE,
-- {0x09, 0x46, 0x13, 0x4e, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_GENERICUNKNOWN,
-- {0x09, 0x46, 0xf0, 0x03, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_ICHAT_SCREENSHARE,
-- {0x09, 0x46, 0xf0, 0x04, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_GENERICUNKNOWN,
-- {0x09, 0x46, 0xf0, 0x05, 0x4c, 0x7f, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_UNICODEOLD,
-- {0x2e, 0x7a, 0x64, 0x75, 0xfa, 0xdf, 0x4d, 0xc8,
-- 0x88, 0x6f, 0xea, 0x35, 0x95, 0xfd, 0xb6, 0xdf}},
--
-- {OSCAR_CAPABILITY_TYPING,
-- {0x56, 0x3f, 0xc8, 0x09, 0x0b, 0x6f, 0x41, 0xbd,
-- 0x9f, 0x79, 0x42, 0x26, 0x09, 0xdf, 0xa2, 0xf3}},
--
-- /*
-- * Chat is oddball.
-- */
-- {OSCAR_CAPABILITY_CHAT,
-- {0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1,
-- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
--
-- /* This is added by the servers and it only shows up for ourselves... */
-- {OSCAR_CAPABILITY_GENERICUNKNOWN,
-- {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34,
-- 0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x09}},
--
-- {OSCAR_CAPABILITY_ICQRTF,
-- {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34,
-- 0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x92}},
--
-- {OSCAR_CAPABILITY_APINFO,
-- {0xaa, 0x4a, 0x32, 0xb5, 0xf8, 0x84, 0x48, 0xc6,
-- 0xa3, 0xd7, 0x8c, 0x50, 0x97, 0x19, 0xfd, 0x5b}},
--
-- {OSCAR_CAPABILITY_TRILLIANCRYPT,
-- {0xf2, 0xe7, 0xc7, 0xf4, 0xfe, 0xad, 0x4d, 0xfb,
-- 0xb2, 0x35, 0x36, 0x79, 0x8b, 0xdf, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_EMPTY,
-- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
--
-- {OSCAR_CAPABILITY_HTML_MSGS,
-- {0x01, 0x38, 0xca, 0x7b, 0x76, 0x9a, 0x49, 0x15,
-- 0x88, 0xf2, 0x13, 0xfc, 0x00, 0x97, 0x9e, 0xa8}},
--
-- {OSCAR_CAPABILITY_LAST,
-- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
--};
--
--/* Keep this array synchronized with icq_purple_moods. */
--static const struct {
-- const char *mood;
-- guint8 data[16];
--} icq_custom_icons[] = {
--
-- {"thinking",
-- {0x3f, 0xb0, 0xbd, 0x36, 0xaf, 0x3b, 0x4a, 0x60,
-- 0x9e, 0xef, 0xcf, 0x19, 0x0f, 0x6a, 0x5a, 0x7f}},
--
-- {"busy",
-- {0x48, 0x8e, 0x14, 0x89, 0x8a, 0xca, 0x4a, 0x08,
-- 0x82, 0xaa, 0x77, 0xce, 0x7a, 0x16, 0x52, 0x08}},
--
-- {"shopping",
-- {0x63, 0x62, 0x73, 0x37, 0xa0, 0x3f, 0x49, 0xff,
-- 0x80, 0xe5, 0xf7, 0x09, 0xcd, 0xe0, 0xa4, 0xee}},
--
-- /* This was in the original patch, but isn't what the official client
-- * (ICQ 6) sets when you choose its typewriter icon. */
-- {"typing",
-- {0x63, 0x4f, 0x6b, 0xd8 ,0xad, 0xd2, 0x4a, 0xa1,
-- 0xaa, 0xb9, 0x11, 0x5b, 0xc2, 0x6d, 0x05, 0xa1}},
--
-- {"question",
-- {0x63, 0x14, 0x36, 0xff, 0x3f, 0x8a, 0x40, 0xd0,
-- 0xa5, 0xcb, 0x7b, 0x66, 0xe0, 0x51, 0xb3, 0x64}},
--
-- {"angry",
-- {0x01, 0xd8, 0xd7, 0xee, 0xac, 0x3b, 0x49, 0x2a,
-- 0xa5, 0x8d, 0xd3, 0xd8, 0x77, 0xe6, 0x6b, 0x92}},
--
-- {"plate",
-- {0xf8, 0xe8, 0xd7, 0xb2, 0x82, 0xc4, 0x41, 0x42,
-- 0x90, 0xf8, 0x10, 0xc6, 0xce, 0x0a, 0x89, 0xa6}},
--
-- {"cinema",
-- {0x10, 0x7a, 0x9a, 0x18, 0x12, 0x32, 0x4d, 0xa4,
-- 0xb6, 0xcd, 0x08, 0x79, 0xdb, 0x78, 0x0f, 0x09}},
--
-- {"sick",
-- {0x1f, 0x7a, 0x40, 0x71, 0xbf, 0x3b, 0x4e, 0x60,
-- 0xbc, 0x32, 0x4c, 0x57, 0x87, 0xb0, 0x4c, 0xf1}},
--
-- {"typing",
-- {0x2c, 0xe0, 0xe4, 0xe5, 0x7c, 0x64, 0x43, 0x70,
-- 0x9c, 0x3a, 0x7a, 0x1c, 0xe8, 0x78, 0xa7, 0xdc}},
--
-- {"suit",
-- {0xb7, 0x08, 0x67, 0xf5, 0x38, 0x25, 0x43, 0x27,
-- 0xa1, 0xff, 0xcf, 0x4c, 0xc1, 0x93, 0x97, 0x97}},
--
-- {"bathing",
-- {0x5a, 0x58, 0x1e, 0xa1, 0xe5, 0x80, 0x43, 0x0c,
-- 0xa0, 0x6f, 0x61, 0x22, 0x98, 0xb7, 0xe4, 0xc7}},
--
-- {"tv",
-- {0x80, 0x53, 0x7d, 0xe2, 0xa4, 0x67, 0x4a, 0x76,
-- 0xb3, 0x54, 0x6d, 0xfd, 0x07, 0x5f, 0x5e, 0xc6}},
--
-- {"excited",
-- {0x6f, 0x49, 0x30, 0x98, 0x4f, 0x7c, 0x4a, 0xff,
-- 0xa2, 0x76, 0x34, 0xa0, 0x3b, 0xce, 0xae, 0xa7}},
--
-- {"sleeping",
-- {0x78, 0x5e, 0x8c, 0x48, 0x40, 0xd3, 0x4c, 0x65,
-- 0x88, 0x6f, 0x04, 0xcf, 0x3f, 0x3f, 0x43, 0xdf}},
--
-- {"hiptop",
-- {0x10, 0x11, 0x17, 0xc9, 0xa3, 0xb0, 0x40, 0xf9,
-- 0x81, 0xac, 0x49, 0xe1, 0x59, 0xfb, 0xd5, 0xd4}},
--
-- {"in_love",
-- {0xdd, 0xcf, 0x0e, 0xa9, 0x71, 0x95, 0x40, 0x48,
-- 0xa9, 0xc6, 0x41, 0x32, 0x06, 0xd6, 0xf2, 0x80}},
--
-- {"sleepy",
-- {0x83, 0xc9, 0xb7, 0x8e, 0x77, 0xe7, 0x43, 0x78,
-- 0xb2, 0xc5, 0xfb, 0x6c, 0xfc, 0xc3, 0x5b, 0xec}},
--
-- {"meeting",
-- {0xf1, 0x8a, 0xb5, 0x2e, 0xdc, 0x57, 0x49, 0x1d,
-- 0x99, 0xdc, 0x64, 0x44, 0x50, 0x24, 0x57, 0xaf}},
--
-- {"phone",
-- {0x12, 0x92, 0xe5, 0x50, 0x1b, 0x64, 0x4f, 0x66,
-- 0xb2, 0x06, 0xb2, 0x9a, 0xf3, 0x78, 0xe4, 0x8d}},
--
-- {"surfing",
-- {0xa6, 0xed, 0x55, 0x7e, 0x6b, 0xf7, 0x44, 0xd4,
-- 0xa5, 0xd4, 0xd2, 0xe7, 0xd9, 0x5c, 0xe8, 0x1f}},
--
-- {"mobile",
-- {0x16, 0x0c, 0x60, 0xbb, 0xdd, 0x44, 0x43, 0xf3,
-- 0x91, 0x40, 0x05, 0x0f, 0x00, 0xe6, 0xc0, 0x09}},
--
-- {"search",
-- {0xd4, 0xe2, 0xb0, 0xba, 0x33, 0x4e, 0x4f, 0xa5,
-- 0x98, 0xd0, 0x11, 0x7d, 0xbf, 0x4d, 0x3c, 0xc8}},
--
-- {"party",
-- {0xe6, 0x01, 0xe4, 0x1c, 0x33, 0x73, 0x4b, 0xd1,
-- 0xbc, 0x06, 0x81, 0x1d, 0x6c, 0x32, 0x3d, 0x81}},
--
-- {"coffee",
-- {0x1b, 0x78, 0xae, 0x31, 0xfa, 0x0b, 0x4d, 0x38,
-- 0x93, 0xd1, 0x99, 0x7e, 0xee, 0xaf, 0xb2, 0x18}},
--
-- {"console",
-- {0xd4, 0xa6, 0x11, 0xd0, 0x8f, 0x01, 0x4e, 0xc0,
-- 0x92, 0x23, 0xc5, 0xb6, 0xbe, 0xc6, 0xcc, 0xf0}},
--
-- {"internet",
-- {0x12, 0xd0, 0x7e, 0x3e, 0xf8, 0x85, 0x48, 0x9e,
-- 0x8e, 0x97, 0xa7, 0x2a, 0x65, 0x51, 0xe5, 0x8d}},
--
-- {"cigarette",
-- {0x64, 0x43, 0xc6, 0xaf, 0x22, 0x60, 0x45, 0x17,
-- 0xb5, 0x8c, 0xd7, 0xdf, 0x8e, 0x29, 0x03, 0x52}},
--
-- {"writing",
-- {0x00, 0x72, 0xd9, 0x08, 0x4a, 0xd1, 0x43, 0xdd,
-- 0x91, 0x99, 0x6f, 0x02, 0x69, 0x66, 0x02, 0x6f}},
--
-- {"beer",
-- {0x8c, 0x50, 0xdb, 0xae, 0x81, 0xed, 0x47, 0x86,
-- 0xac, 0xca, 0x16, 0xcc, 0x32, 0x13, 0xc7, 0xb7}},
--
-- {"music",
-- {0x61, 0xbe, 0xe0, 0xdd, 0x8b, 0xdd, 0x47, 0x5d,
-- 0x8d, 0xee, 0x5f, 0x4b, 0xaa, 0xcf, 0x19, 0xa7}},
--
-- {"studying",
-- {0x60, 0x9d, 0x52, 0xf8, 0xa2, 0x9a, 0x49, 0xa6,
-- 0xb2, 0xa0, 0x25, 0x24, 0xc5, 0xe9, 0xd2, 0x60}},
--
-- {"working",
-- {0xba, 0x74, 0xdb, 0x3e, 0x9e, 0x24, 0x43, 0x4b,
-- 0x87, 0xb6, 0x2f, 0x6b, 0x8d, 0xfe, 0xe5, 0x0f}},
--
-- {"restroom",
-- {0x16, 0xf5, 0xb7, 0x6f, 0xa9, 0xd2, 0x40, 0x35,
-- 0x8c, 0xc5, 0xc0, 0x84, 0x70, 0x3c, 0x98, 0xfa}},
--
-- {NULL,
-- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}
--};
--
--/* Keep this array synchronized with icq_custom_icons. */
--static PurpleMood icq_purple_moods[] = {
-- {"thinking", N_("Thinking"), NULL},
-- {"busy", N_("Busy"), NULL},
-- {"shopping", N_("Shopping"), NULL},
-- /* This was in the original patch, but isn't what the official client
-- * (ICQ 6) sets when you choose its typewriter icon. */
-- {"typing", NULL, NULL},
-- {"question", N_("Questioning"), NULL},
-- {"angry", N_("Angry"), NULL},
-- {"plate", N_("Eating"), NULL},
-- {"cinema", N_("Watching a movie"), NULL},
-- {"sick", N_("Sick"), NULL},
-- {"typing", N_("Typing"), NULL},
-- {"suit", N_("At the office"), NULL},
-- {"bathing", N_("Taking a bath"), NULL},
-- {"tv", N_("Watching TV"), NULL},
-- {"excited", N_("Having fun"), NULL},
-- {"sleeping", N_("Sleeping"), NULL},
-- {"hiptop", N_("Using a PDA"), NULL},
-- {"in_love", N_("In love"), NULL},
-- /* Sleepy / Tired */
-- {"sleepy", N_("Sleepy"), NULL},
-- {"meeting", N_("Meeting friends"), NULL},
-- {"phone", N_("On the phone"), NULL},
-- {"surfing", N_("Surfing"), NULL},
-- /* "I am mobile." / "John is mobile." */
-- {"mobile", N_("Mobile"), NULL},
-- {"search", N_("Searching the web"), NULL},
-- {"party", N_("At a party"), NULL},
-- {"coffee", N_("Having Coffee"), NULL},
-- /* Playing video games */
-- {"console", N_("Gaming"), NULL},
-- {"internet", N_("Browsing the web"), NULL},
-- {"cigarette", N_("Smoking"), NULL},
-- {"writing", N_("Writing"), NULL},
-- /* Drinking [Alcohol] */
-- {"beer", N_("Drinking"), NULL},
-- {"music", N_("Listening to music"), NULL},
-- {"studying", N_("Studying"), NULL},
-- {"working", N_("Working"), NULL},
-- {"restroom", N_("In the restroom"), NULL},
-- /* Mark the last record. */
-- {NULL, NULL, NULL},
--};
--
--
--/*
-- * Add the userinfo to our linked list. If we already have userinfo
-- * for this buddy, then just overwrite parts of the old data.
-- *
-- * @param userinfo Contains the new information for the buddy.
-- */
--static void
--aim_locate_adduserinfo(OscarData *od, aim_userinfo_t *userinfo)
--{
-- aim_userinfo_t *cur;
--
-- cur = aim_locate_finduserinfo(od, userinfo->bn);
--
-- if (cur == NULL) {
-- cur = (aim_userinfo_t *)g_new0(aim_userinfo_t, 1);
-- cur->bn = g_strdup(userinfo->bn);
-- cur->next = od->locate.userinfo;
-- od->locate.userinfo = cur;
-- }
--
-- cur->warnlevel = userinfo->warnlevel;
-- cur->idletime = userinfo->idletime;
-- if (userinfo->flags != 0)
-- cur->flags = userinfo->flags;
-- if (userinfo->createtime != 0)
-- cur->createtime = userinfo->createtime;
-- if (userinfo->membersince != 0)
-- cur->membersince = userinfo->membersince;
-- if (userinfo->onlinesince != 0)
-- cur->onlinesince = userinfo->onlinesince;
-- if (userinfo->sessionlen != 0)
-- cur->sessionlen = userinfo->sessionlen;
-- if (userinfo->capabilities != 0)
-- cur->capabilities = userinfo->capabilities;
--
-- cur->present |= userinfo->present;
--
-- if (userinfo->iconcsumlen > 0) {
-- g_free(cur->iconcsum);
-- cur->iconcsum = (guint8 *)g_malloc(userinfo->iconcsumlen);
-- memcpy(cur->iconcsum, userinfo->iconcsum, userinfo->iconcsumlen);
-- cur->iconcsumlen = userinfo->iconcsumlen;
-- }
--
-- if (userinfo->info != NULL) {
-- g_free(cur->info);
-- g_free(cur->info_encoding);
-- if (userinfo->info_len > 0) {
-- cur->info = (char *)g_malloc(userinfo->info_len);
-- memcpy(cur->info, userinfo->info, userinfo->info_len);
-- } else
-- cur->info = NULL;
-- cur->info_encoding = g_strdup(userinfo->info_encoding);
-- cur->info_len = userinfo->info_len;
-- }
--
-- if (userinfo->status != NULL) {
-- g_free(cur->status);
-- g_free(cur->status_encoding);
-- if (userinfo->status_len > 0) {
-- cur->status = (char *)g_malloc(userinfo->status_len);
-- memcpy(cur->status, userinfo->status, userinfo->status_len);
-- } else
-- cur->status = NULL;
-- if (userinfo->status_encoding != NULL)
-- cur->status_encoding = g_strdup(userinfo->status_encoding);
-- else
-- cur->status_encoding = NULL;
-- cur->status_len = userinfo->status_len;
-- }
--
-- if (userinfo->itmsurl != NULL) {
-- g_free(cur->itmsurl);
-- g_free(cur->itmsurl_encoding);
-- if (userinfo->itmsurl_len > 0) {
-- cur->itmsurl = (char *)g_malloc(userinfo->itmsurl_len);
-- memcpy(cur->itmsurl, userinfo->itmsurl, userinfo->itmsurl_len);
-- } else
-- cur->itmsurl = NULL;
-- if (userinfo->itmsurl_encoding != NULL)
-- cur->itmsurl_encoding = g_strdup(userinfo->itmsurl_encoding);
-- else
-- cur->itmsurl_encoding = NULL;
-- cur->itmsurl_len = userinfo->itmsurl_len;
-- }
--
-- if (userinfo->away != NULL) {
-- g_free(cur->away);
-- g_free(cur->away_encoding);
-- if (userinfo->away_len > 0) {
-- cur->away = (char *)g_malloc(userinfo->away_len);
-- memcpy(cur->away, userinfo->away, userinfo->away_len);
-- } else
-- cur->away = NULL;
-- cur->away_encoding = g_strdup(userinfo->away_encoding);
-- cur->away_len = userinfo->away_len;
--
-- } else {
-- /*
-- * We don't have an away message specified in this user_info
-- * block, so clear any cached away message now.
-- */
-- if (cur->away) {
-- g_free(cur->away);
-- cur->away = NULL;
-- }
-- if (cur->away_encoding) {
-- g_free(cur->away_encoding);
-- cur->away_encoding = NULL;
-- }
-- cur->away_len = 0;
-- }
--}
--
--aim_userinfo_t *aim_locate_finduserinfo(OscarData *od, const char *bn) {
-- aim_userinfo_t *cur = NULL;
--
-- if (bn == NULL)
-- return NULL;
--
-- cur = od->locate.userinfo;
--
-- while (cur != NULL) {
-- if (oscar_util_name_compare(cur->bn, bn) == 0)
-- return cur;
-- cur = cur->next;
-- }
--
-- return NULL;
--}
--
--guint64
--aim_locate_getcaps(OscarData *od, ByteStream *bs, int len)
--{
-- guint64 flags = 0;
-- int offset;
--
-- for (offset = 0; byte_stream_bytes_left(bs) && (offset < len); offset += 0x10) {
-- guint8 *cap;
-- int i, identified;
--
-- cap = byte_stream_getraw(bs, 0x10);
--
-- for (i = 0, identified = 0; !(aim_caps[i].flag & OSCAR_CAPABILITY_LAST); i++) {
-- if (memcmp(&aim_caps[i].data, cap, 0x10) == 0) {
-- flags |= aim_caps[i].flag;
-- identified++;
-- break; /* should only match once... */
-- }
-- }
--
-- if (!identified)
-- purple_debug_misc("oscar", "unknown capability: {%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
-- cap[0], cap[1], cap[2], cap[3],
-- cap[4], cap[5],
-- cap[6], cap[7],
-- cap[8], cap[9],
-- cap[10], cap[11], cap[12], cap[13],
-- cap[14], cap[15]);
-- g_free(cap);
-- }
--
-- return flags;
--}
--
--static const char *
--aim_receive_custom_icon(OscarData *od, ByteStream *bs, int len)
--{
-- int offset;
-- const char *result = NULL;
--
-- for (offset = 0; byte_stream_bytes_left(bs) && (offset < len); offset += 0x10) {
-- /* check wheather this capability is a custom user icon */
-- guint8 *cap;
-- int i;
--
-- cap = byte_stream_getraw(bs, 0x10);
--
-- for (i = 0; icq_custom_icons[i].mood; i++) {
-- if (memcmp(&icq_custom_icons[i].data, cap, 0x10) == 0) {
-- purple_debug_misc("oscar", "Custom status icon: %s\n", icq_purple_moods[i].description);
-- result = icq_custom_icons[i].mood;
-- break; /* should only match once... */
-- }
-- }
-- g_free(cap);
-- }
--
-- return result;
--}
--
--guint64
--aim_locate_getcaps_short(OscarData *od, ByteStream *bs, int len)
--{
-- guint64 flags = 0;
-- int offset;
--
-- for (offset = 0; byte_stream_bytes_left(bs) && (offset < len); offset += 0x02) {
-- guint8 *cap;
-- int i, identified;
--
-- cap = byte_stream_getraw(bs, 0x02);
--
-- for (i = 0, identified = 0; !(aim_caps[i].flag & OSCAR_CAPABILITY_LAST); i++) {
-- if (memcmp(&aim_caps[i].data[2], cap, 0x02) == 0) {
-- flags |= aim_caps[i].flag;
-- identified++;
-- break; /* should only match once... */
-- }
-- }
--
-- if (!identified)
-- purple_debug_misc("oscar", "unknown short capability: {%02x%02x}\n", cap[0], cap[1]);
--
-- g_free(cap);
-- }
--
-- return flags;
--}
--
--int
--byte_stream_putcaps(ByteStream *bs, guint64 caps)
--{
-- int i;
--
-- if (!bs)
-- return -EINVAL;
--
-- for (i = 0; byte_stream_bytes_left(bs); i++) {
-- if (aim_caps[i].flag == OSCAR_CAPABILITY_LAST)
-- break;
--
-- if (caps & aim_caps[i].flag)
-- byte_stream_putraw(bs, aim_caps[i].data, 0x10);
-- }
-- return 0;
--}
--
--#ifdef LOG_UNKNOWN_TLV
--static void
--dumptlv(OscarData *od, guint16 type, ByteStream *bs, guint8 len)
--{
-- int i;
--
-- if (!od || !bs || !len)
-- return;
--
-- purple_debug_misc("oscar", "userinfo: type =0x%04x\n", type);
-- purple_debug_misc("oscar", "userinfo: length=0x%04x\n", len);
-- purple_debug_misc("oscar", "userinfo: value:\n");
--
-- for (i = 0; i < len; i++) {
-- if ((i % 8) == 0)
-- purple_debug_misc("oscar", "\nuserinfo: ");
-- purple_debug_misc("oscar", "0x%2x ", byte_stream_get8(bs));
-- }
--
-- purple_debug_misc("oscar", "\n");
--
-- return;
--}
--#endif
--
--void
--aim_info_free(aim_userinfo_t *info)
--{
-- g_free(info->bn);
-- g_free(info->iconcsum);
-- g_free(info->info);
-- g_free(info->info_encoding);
-- g_free(info->status);
-- g_free(info->status_encoding);
-- g_free(info->itmsurl);
-- g_free(info->itmsurl_encoding);
-- g_free(info->away);
-- g_free(info->away_encoding);
--}
--
--static const struct {
-- char *icqmood;
-- const char *mood;
--} icqmoods[] = {
-- {"icqmood0", "shopping"},
-- {"icqmood1", "bathing"},
-- {"icqmood2", "sleepy"},
-- {"icqmood3", "party"},
-- {"icqmood4", "beer"},
-- {"icqmood5", "thinking"},
-- {"icqmood6", "plate"},
-- {"icqmood7", "tv"},
-- {"icqmood8", "meeting"},
-- {"icqmood9", "coffee"},
-- {"icqmood10", "music"},
-- {"icqmood11", "suit"},
-- {"icqmood12", "cinema"},
-- {"icqmood13", "smile-big"},
-- {"icqmood14", "phone"},
-- {"icqmood15", "console"},
-- {"icqmood16", "studying"},
-- {"icqmood17", "sick"},
-- {"icqmood18", "sleeping"},
-- {"icqmood19", "surfing"},
-- {"icqmood20", "internet"},
-- {"icqmood21", "working"},
-- {"icqmood22", "typing"},
-- {"icqmood23", "angry"},
-- {NULL, 0}
--
--};
--
--/*
-- * AIM is fairly regular about providing user info. This is a generic
-- * routine to extract it in its standard form.
-- */
--int
--aim_info_extract(OscarData *od, ByteStream *bs, aim_userinfo_t *outinfo)
--{
-- int curtlv, tlvcnt;
-- guint8 bnlen;
--
-- if (!bs || !outinfo)
-- return -EINVAL;
--
-- /* Clear out old data first */
-- memset(outinfo, 0x00, sizeof(aim_userinfo_t));
--
-- /*
-- * Username. Stored as an unterminated string prepended with a
-- * byte containing its length.
-- */
-- bnlen = byte_stream_get8(bs);
-- outinfo->bn = byte_stream_getstr(bs, bnlen);
--
-- /*
-- * Warning Level. Stored as an unsigned short.
-- */
-- outinfo->warnlevel = byte_stream_get16(bs);
--
-- /*
-- * TLV Count. Unsigned short representing the number of
-- * Type-Length-Value triples that follow.
-- */
-- tlvcnt = byte_stream_get16(bs);
--
-- /*
-- * Parse out the Type-Length-Value triples as they're found.
-- */
-- for (curtlv = 0; curtlv < tlvcnt; curtlv++) {
-- guint16 type, length;
-- int endpos;
-- int curpos;
--
-- type = byte_stream_get16(bs);
-- length = byte_stream_get16(bs);
-- curpos = byte_stream_curpos(bs);
-- endpos = curpos + MIN(length, byte_stream_bytes_left(bs));
--
-- if (type == 0x0001) {
-- /*
-- * User flags
-- *
-- * Specified as any of the following ORed together:
-- * 0x0001 Unconfirmed account
-- * 0x0002 Unknown bit 2
-- * 0x0004 AOL Main Service user
-- * 0x0008 Unknown bit 4
-- * 0x0010 Free (AIM) user
-- * 0x0020 Away
-- * 0x0040 ICQ user (AIM bit also set)
-- * 0x0080 Mobile device
-- * 0x0400 Bot (like ActiveBuddy)
-- */
-- outinfo->flags = byte_stream_get16(bs);
-- outinfo->present |= AIM_USERINFO_PRESENT_FLAGS;
--
-- } else if (type == 0x0002) {
-- /*
-- * Account creation time
-- *
-- * The time/date that the user originally registered for
-- * the service, stored in time_t format.
-- *
-- * I'm not sure how this differs from type 5 ("member
-- * since").
-- *
-- * Note: This is the field formerly known as "member
-- * since". All these years and I finally found out
-- * that I got the name wrong.
-- */
-- outinfo->createtime = byte_stream_get32(bs);
-- outinfo->present |= AIM_USERINFO_PRESENT_CREATETIME;
--
-- } else if (type == 0x0003) {
-- /*
-- * On-Since date
-- *
-- * The time/date that the user started their current
-- * session, stored in time_t format.
-- */
-- outinfo->onlinesince = byte_stream_get32(bs);
-- outinfo->present |= AIM_USERINFO_PRESENT_ONLINESINCE;
--
-- } else if (type == 0x0004) {
-- /*
-- * Idle time
-- *
-- * Number of minutes since the user actively used the
-- * service.
-- *
-- * Note that the client tells the server when to start
-- * counting idle times, so this may or may not be
-- * related to reality.
-- */
-- outinfo->idletime = byte_stream_get16(bs);
-- outinfo->present |= AIM_USERINFO_PRESENT_IDLE;
--
-- } else if (type == 0x0005) {
-- /*
-- * Member since date
-- *
-- * The time/date that the user originally registered for
-- * the service, stored in time_t format.
-- *
-- * This is sometimes sent instead of type 2 ("account
-- * creation time"), particularly in the self-info.
-- * And particularly for ICQ?
-- */
-- outinfo->membersince = byte_stream_get32(bs);
-- outinfo->present |= AIM_USERINFO_PRESENT_MEMBERSINCE;
--
-- } else if (type == 0x0006) {
-- /*
-- * ICQ Online Status
-- *
-- * ICQ's Away/DND/etc "enriched" status. Some decoding
-- * of values done by Scott <darkagl@pcnet.com>
-- */
-- byte_stream_get16(bs);
-- outinfo->icqinfo.status = byte_stream_get16(bs);
-- outinfo->present |= AIM_USERINFO_PRESENT_ICQEXTSTATUS;
--
-- } else if (type == 0x0008) {
-- /*
-- * Client type, or some such.
-- */
--
-- } else if (type == 0x000a) {
-- /*
-- * ICQ User IP Address
-- *
-- * Ahh, the joy of ICQ security.
-- */
-- outinfo->icqinfo.ipaddr = byte_stream_get32(bs);
-- outinfo->present |= AIM_USERINFO_PRESENT_ICQIPADDR;
--
-- } else if (type == 0x000c) {
-- /*
-- * Random crap containing the IP address,
-- * apparently a port number, and some Other Stuff.
-- *
-- * Format is:
-- * 4 bytes - Our IP address, 0xc0 a8 01 2b for 192.168.1.43
-- */
-- byte_stream_getrawbuf(bs, outinfo->icqinfo.crap, 0x25);
-- outinfo->present |= AIM_USERINFO_PRESENT_ICQDATA;
--
-- } else if (type == 0x000d) {
-- PurpleAccount *account = purple_connection_get_account(od->gc);
-- const char *mood;
--
-- /*
-- * OSCAR Capability information
-- */
-- outinfo->capabilities |= aim_locate_getcaps(od, bs, length);
-- outinfo->present |= AIM_USERINFO_PRESENT_CAPABILITIES;
-- byte_stream_setpos(bs, curpos);
--
-- mood = aim_receive_custom_icon(od, bs, length);
-- if (mood)
-- purple_prpl_got_user_status(account, outinfo->bn, "mood",
-- PURPLE_MOOD_NAME, mood,
-- NULL);
-- else
-- purple_prpl_got_user_status_deactive(account, outinfo->bn, "mood");
--
-- } else if (type == 0x000e) {
-- /*
-- * AOL capability information
-- */
--
-- } else if ((type == 0x000f) || (type == 0x0010)) {
-- /*
-- * Type = 0x000f: Session Length. (AIM)
-- * Type = 0x0010: Session Length. (AOL)
-- *
-- * The duration, in seconds, of the user's current
-- * session.
-- *
-- * Which TLV type this comes in depends on the
-- * service the user is using (AIM or AOL).
-- */
-- outinfo->sessionlen = byte_stream_get32(bs);
-- outinfo->present |= AIM_USERINFO_PRESENT_SESSIONLEN;
--
-- } else if (type == 0x0014) {
-- /*
-- * My instance number.
-- */
-- guint8 instance_number;
-- instance_number = byte_stream_get8(bs);
--
-- } else if (type == 0x0019) {
-- /*
-- * OSCAR short capability information. A shortened
-- * form of the normal capabilities.
-- */
-- outinfo->capabilities |= aim_locate_getcaps_short(od, bs, length);
-- outinfo->present |= AIM_USERINFO_PRESENT_CAPABILITIES;
--
-- } else if (type == 0x001a) {
-- /*
-- * Type = 0x001a
-- *
-- * AOL short capability information. A shortened
-- * form of the normal capabilities.
-- */
--
-- } else if (type == 0x001b) {
-- /*
-- * Encryption certification MD5 checksum.
-- */
--
-- } else if (type == 0x001d) {
-- /*
-- * Buddy icon information and status/available messages.
-- *
-- * This almost seems like the AIM protocol guys gave
-- * the iChat guys a Type, and the iChat guys tried to
-- * cram as much cool shit into it as possible. Then
-- * the Windows AIM guys were like, "hey, that's
-- * pretty neat, let's copy those prawns."
-- *
-- * In that spirit, this can contain a custom message,
-- * kind of like an away message, but you're not away
-- * (it's called an "available" message). Or it can
-- * contain information about the buddy icon the user
-- * has stored on the server.
-- */
-- guint16 type2;
-- guint8 number2, length2;
-- int endpos2;
--
-- /*
-- * Continue looping as long as we're able to read type2,
-- * number2, and length2.
-- */
-- while (byte_stream_curpos(bs) + 4 <= endpos) {
-- type2 = byte_stream_get16(bs);
-- number2 = byte_stream_get8(bs);
-- length2 = byte_stream_get8(bs);
--
-- endpos2 = byte_stream_curpos(bs) + MIN(length2, byte_stream_bytes_left(bs));
--
-- switch (type2) {
-- case 0x0000: { /* This is an official buddy icon? */
-- /* This is always 5 bytes of "0x02 01 d2 04 72"? */
-- } break;
--
-- case 0x0001: { /* A buddy icon checksum */
-- if ((length2 > 0) && ((number2 == 0x00) || (number2 == 0x01))) {
-- g_free(outinfo->iconcsum);
-- outinfo->iconcsumtype = number2;
-- outinfo->iconcsum = byte_stream_getraw(bs, length2);
-- outinfo->iconcsumlen = length2;
-- }
-- } break;
--
-- case 0x0002: { /* A status/available message */
-- g_free(outinfo->status);
-- g_free(outinfo->status_encoding);
-- if (length2 >= 4) {
-- outinfo->status_len = byte_stream_get16(bs);
-- outinfo->status = byte_stream_getstr(bs, outinfo->status_len);
-- if (byte_stream_get16(bs) == 0x0001) { /* We have an encoding */
-- byte_stream_get16(bs);
-- outinfo->status_encoding = byte_stream_getstr(bs, byte_stream_get16(bs));
-- } else {
-- /* No explicit encoding, client should use UTF-8 */
-- outinfo->status_encoding = NULL;
-- }
-- } else {
-- byte_stream_advance(bs, length2);
-- outinfo->status_len = 0;
-- outinfo->status = g_strdup("");
-- outinfo->status_encoding = NULL;
-- }
-- } break;
--
-- case 0x0009: { /* An iTunes Music Store link */
-- g_free(outinfo->itmsurl);
-- g_free(outinfo->itmsurl_encoding);
-- if (length2 >= 4) {
-- outinfo->itmsurl_len = byte_stream_get16(bs);
-- outinfo->itmsurl = byte_stream_getstr(bs, outinfo->itmsurl_len);
-- if (byte_stream_get16(bs) == 0x0001) {
-- /* We have an encoding */
-- byte_stream_get16(bs);
-- outinfo->itmsurl_encoding = byte_stream_getstr(bs, byte_stream_get16(bs));
-- } else {
-- /* No explicit encoding, client should use UTF-8 */
-- outinfo->itmsurl_encoding = NULL;
-- }
-- } else {
-- byte_stream_advance(bs, length2);
-- outinfo->itmsurl_len = 0;
-- outinfo->itmsurl = g_strdup("");
-- outinfo->itmsurl_encoding = NULL;
-- }
-- } break;
--
-- case 0x000e: { /* ICQ mood */
-- PurpleAccount *account = purple_connection_get_account(od->gc);
-- char *icqmood;
-- gint32 i;
-- const char *mood = NULL;
--
-- icqmood = byte_stream_getstr(bs, length2);
--
-- /* icqmood = "" means X-Status
-- * with no mood icon. */
-- if (*icqmood) {
-- for (i = 0; icqmoods[i].icqmood; i++) {
-- if (!strcmp(icqmood, icqmoods[i].icqmood)) {
-- mood = icqmoods[i].mood;
-- break; /* should only match once... */
-- }
-- }
--
-- if (!mood)
-- purple_debug_warning("oscar", "Unknown icqmood: %s\n", icqmood);
-- }
-- g_free(icqmood);
--
-- if (mood)
-- purple_prpl_got_user_status(account, outinfo->bn, "mood",
-- PURPLE_MOOD_NAME, mood,
-- NULL);
-- else
-- purple_prpl_got_user_status_deactive(account, outinfo->bn, "mood");
-- } break;
-- }
--
-- /* Save ourselves. */
-- byte_stream_setpos(bs, endpos2);
-- }
--
-- } else if (type == 0x001e) {
-- /*
-- * Always four bytes, but it doesn't look like an int.
-- */
--
-- } else if (type == 0x001f) {
-- /*
-- * Upper bytes of user flags. Can be any size
-- *
-- * Seen on a buddy using DeadAIM. Data was 4 bytes:
-- * 0x00 00 00 10
-- */
--
-- } else if (type == 0x0023) {
-- /*
-- * Last Buddy Feed update time, in seconds since the epoch.
-- */
--
-- } else if (type == 0x0026) {
-- /*
-- * Time that the profile was set, in seconds since the epoch.
-- */
--
-- } else if (type == 0x0027) {
-- /*
-- * Time that the away message was set, in seconds since the epoch.
-- */
--
-- } else if (type == 0x002a) {
-- /*
-- * Country code based on GeoIP data.
-- */
--
-- } else {
--
-- /*
-- * Reaching here indicates that either AOL has
-- * added yet another TLV for us to deal with,
-- * or the parsing has gone Terribly Wrong.
-- *
-- * Either way, inform the owner and attempt
-- * recovery.
-- *
-- */
--#ifdef LOG_UNKNOWN_TLV
-- purple_debug_misc("oscar", "userinfo: **warning: unexpected TLV:\n");
-- purple_debug_misc("oscar", "userinfo: bn =%s\n", outinfo->bn);
-- dumptlv(od, type, bs, length);
--#endif
-- }
--
-- /* Save ourselves. */
-- byte_stream_setpos(bs, endpos);
-- }
--
-- aim_locate_adduserinfo(od, outinfo);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0001
-- */
--static int
--error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- aim_snac_t *snac2;
-- guint16 reason;
-- char *bn;
--
-- snac2 = aim_remsnac(od, snac->id);
-- if (!snac2) {
-- purple_debug_misc("oscar", "locate error: received response from unknown request!\n");
-- return 0;
-- }
--
-- if ((snac2->family != SNAC_FAMILY_LOCATE) && (snac2->type != 0x0015)) {
-- purple_debug_misc("oscar", "locate error: received response from invalid request! %d\n", snac2->family);
-- g_free(snac2->data);
-- g_free(snac2);
-- return 0;
-- }
--
-- bn = snac2->data;
-- if (!bn) {
-- purple_debug_misc("oscar", "locate error: received response from request without a buddy name!\n");
-- g_free(snac2);
-- return 0;
-- }
--
-- reason = byte_stream_get16(bs);
--
-- oscar_user_info_display_error(od, reason, bn);
--
-- g_free(snac2->data);
-- g_free(snac2);
--
-- return 1;
--}
--
--/*
-- * Subtype 0x0002
-- *
-- * Request Location services rights.
-- *
-- */
--int
--aim_locate_reqrights(OscarData *od)
--{
-- FlapConnection *conn;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
-- return -EINVAL;
--
-- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_REQRIGHTS);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0003
-- *
-- * Normally contains:
-- * t(0001) - short containing max profile length (value = 1024)
-- * t(0002) - short - unknown (value = 16) [max MIME type length?]
-- * t(0003) - short - unknown (value = 10)
-- * t(0004) - short - unknown (value = 2048) [ICQ only?]
-- */
--static int
--rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- GSList *tlvlist;
-- aim_rxcallback_t userfunc;
-- int ret = 0;
-- guint16 maxsiglen = 0;
--
-- tlvlist = aim_tlvlist_read(bs);
--
-- if (aim_tlv_gettlv(tlvlist, 0x0001, 1))
-- maxsiglen = aim_tlv_get16(tlvlist, 0x0001, 1);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, maxsiglen);
--
-- aim_tlvlist_free(tlvlist);
--
-- return ret;
--}
--
--/*
-- * Subtype 0x0004
-- *
-- * Gives BOS your profile.
-- *
-- * profile_encoding and awaymsg_encoding MUST be set if profile or
-- * away are set, respectively, and their value may or may not be
-- * restricted to a few choices. I am currently aware of:
-- *
-- * us-ascii Just that
-- * unicode-2-0 UTF-16BE
-- *
-- * profile_len and awaymsg_len MUST be set similarly, and they MUST
-- * be the length of their respective strings in bytes.
-- *
-- * To get the previous behavior of awaymsg == "" un-setting the away
-- * message, set awaymsg non-NULL and awaymsg_len to 0 (this is the
-- * obvious equivalent).
-- *
-- */
--int
--aim_locate_setprofile(OscarData *od,
-- const char *profile_encoding, const gchar *profile, const int profile_len,
-- const char *awaymsg_encoding, const gchar *awaymsg, const int awaymsg_len)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- GSList *tlvlist = NULL;
-- char *encoding;
-- static const char defencoding[] = {"text/aolrtf; charset=\"%s\""};
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
-- return -EINVAL;
--
-- if (!profile && !awaymsg)
-- return -EINVAL;
--
-- if ((profile && profile_encoding == NULL) || (awaymsg && awaymsg_len && awaymsg_encoding == NULL)) {
-- return -EINVAL;
-- }
--
-- /* Build the packet first to get real length */
-- if (profile) {
-- /* no + 1 here because of %s */
-- encoding = g_malloc(strlen(defencoding) + strlen(profile_encoding));
-- snprintf(encoding, strlen(defencoding) + strlen(profile_encoding), defencoding, profile_encoding);
-- aim_tlvlist_add_str(&tlvlist, 0x0001, encoding);
-- aim_tlvlist_add_raw(&tlvlist, 0x0002, profile_len, (const guchar *)profile);
-- g_free(encoding);
-- }
--
-- /*
-- * So here's how this works:
-- * - You are away when you have a non-zero-length type 4 TLV stored.
-- * - You become unaway when you clear the TLV with a zero-length
-- * type 4 TLV.
-- * - If you do not send the type 4 TLV, your status does not change
-- * (that is, if you were away, you'll remain away).
-- */
-- if (awaymsg) {
-- if (awaymsg_len) {
-- encoding = g_malloc(strlen(defencoding) + strlen(awaymsg_encoding));
-- snprintf(encoding, strlen(defencoding) + strlen(awaymsg_encoding), defencoding, awaymsg_encoding);
-- aim_tlvlist_add_str(&tlvlist, 0x0003, encoding);
-- aim_tlvlist_add_raw(&tlvlist, 0x0004, awaymsg_len, (const guchar *)awaymsg);
-- g_free(encoding);
-- } else
-- aim_tlvlist_add_noval(&tlvlist, 0x0004);
-- }
--
-- byte_stream_new(&bs, aim_tlvlist_size(tlvlist));
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0004, 0x0000, NULL, 0);
--
-- aim_tlvlist_write(&bs, &tlvlist);
-- aim_tlvlist_free(tlvlist);
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x0004, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0004 - Set your client's capabilities.
-- */
--int
--aim_locate_setcaps(OscarData *od, guint64 caps)
--{
-- FlapConnection *conn;
-- PurpleAccount *account = purple_connection_get_account(od->gc);
-- PurplePresence *presence = purple_account_get_presence(account);
-- PurpleStatus *status = purple_presence_get_status(presence, "mood");
-- const char *mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
-- ByteStream bs;
-- aim_snacid_t snacid;
-- GSList *tlvlist = NULL;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
-- return -EINVAL;
--
-- aim_tlvlist_add_caps(&tlvlist, 0x0005, caps, mood);
--
-- byte_stream_new(&bs, aim_tlvlist_size(tlvlist));
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0004, 0x0000, NULL, 0);
--
-- aim_tlvlist_write(&bs, &tlvlist);
-- aim_tlvlist_free(tlvlist);
--
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x0004, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/* Subtype 0x0006 */
--static int
--userinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_userinfo_t *userinfo, *userinfo2;
-- GSList *tlvlist;
-- aim_tlv_t *tlv = NULL;
--
-- userinfo = (aim_userinfo_t *)g_malloc(sizeof(aim_userinfo_t));
-- aim_info_extract(od, bs, userinfo);
-- tlvlist = aim_tlvlist_read(bs);
--
-- /* Profile will be 1 and 2 */
-- userinfo->info_encoding = aim_tlv_getstr(tlvlist, 0x0001, 1);
-- if ((tlv = aim_tlv_gettlv(tlvlist, 0x0002, 1))) {
-- userinfo->info = (char *)g_malloc(tlv->length);
-- memcpy(userinfo->info, tlv->value, tlv->length);
-- userinfo->info_len = tlv->length;
-- }
--
-- /* Away message will be 3 and 4 */
-- userinfo->away_encoding = aim_tlv_getstr(tlvlist, 0x0003, 1);
-- if ((tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {
-- userinfo->away = (char *)g_malloc(tlv->length);
-- memcpy(userinfo->away, tlv->value, tlv->length);
-- userinfo->away_len = tlv->length;
-- }
--
-- /* Caps will be 5 */
-- if ((tlv = aim_tlv_gettlv(tlvlist, 0x0005, 1))) {
-- ByteStream cbs;
-- PurpleAccount *account = purple_connection_get_account(od->gc);
-- const char *mood;
--
-- byte_stream_init(&cbs, tlv->value, tlv->length);
-- userinfo->capabilities = aim_locate_getcaps(od, &cbs, tlv->length);
-- byte_stream_rewind(&cbs);
-- userinfo->present = AIM_USERINFO_PRESENT_CAPABILITIES;
--
-- mood = aim_receive_custom_icon(od, &cbs, tlv->length);
-- if (mood)
-- purple_prpl_got_user_status(account, userinfo->bn, "mood",
-- PURPLE_MOOD_NAME, mood,
-- NULL);
-- else
-- purple_prpl_got_user_status_deactive(account, userinfo->bn, "mood");
-- }
-- aim_tlvlist_free(tlvlist);
--
-- aim_locate_adduserinfo(od, userinfo);
-- userinfo2 = aim_locate_finduserinfo(od, userinfo->bn);
-- aim_info_free(userinfo);
-- g_free(userinfo);
--
-- /* Show the info to the user */
-- oscar_user_info_display_aim(od, userinfo2);
--
-- return ret;
--}
--
--/*
-- * Subtype 0x0015 - Request the info of a user using the short method. This is
-- * what iChat uses. It normally is VERY leniently rate limited.
-- *
-- * @param bn The buddy name whose info you wish to request.
-- * @param flags The bitmask which specifies the type of info you wish to request.
-- * 0x00000001 - Info/profile.
-- * 0x00000002 - Away message.
-- * 0x00000004 - Capabilities.
-- * 0x00000008 - Certification.
-- * @return Return 0 if no errors, otherwise return the error number.
-- */
--int
--aim_locate_getinfoshort(OscarData *od, const char *bn, guint32 flags)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)) || !bn)
-- return -EINVAL;
--
-- byte_stream_new(&bs, 4 + 1 + strlen(bn));
-- byte_stream_put32(&bs, flags);
-- byte_stream_put8(&bs, strlen(bn));
-- byte_stream_putstr(&bs, bn);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0015, 0x0000, bn, strlen(bn)+1);
-- flap_connection_send_snac_with_priority(od, conn, SNAC_FAMILY_LOCATE, 0x0015, snacid, &bs, FALSE);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--static int
--snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- if (snac->subtype == 0x0001)
-- return error(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x0003)
-- return rights(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x0006)
-- return userinfo(od, conn, mod, frame, snac, bs);
--
-- return 0;
--}
--
--static void
--locate_shutdown(OscarData *od, aim_module_t *mod)
--{
-- aim_userinfo_t *del;
--
-- while (od->locate.userinfo) {
-- del = od->locate.userinfo;
-- od->locate.userinfo = od->locate.userinfo->next;
-- aim_info_free(del);
-- g_free(del);
-- }
--}
--
--int
--locate_modfirst(OscarData *od, aim_module_t *mod)
--{
-- mod->family = SNAC_FAMILY_LOCATE;
-- mod->version = 0x0001;
-- mod->toolid = 0x0110;
-- mod->toolversion = 0x0629;
-- mod->flags = 0;
-- strncpy(mod->name, "locate", sizeof(mod->name));
-- mod->snachandler = snachandler;
-- mod->shutdown = locate_shutdown;
--
-- return 0;
--}
--
--const char*
--icq_get_custom_icon_description(const char *mood)
--{
-- int i;
--
-- if (!(mood && *mood))
-- return NULL;
--
-- for (i = 0; icq_custom_icons[i].mood; i++) {
-- /* We check that description is not NULL to exclude
-- * duplicates, like the typing duplicate. */
-- if (icq_purple_moods[i].description &&
-- !strcmp(mood, icq_custom_icons[i].mood)) {
-- return icq_purple_moods[i].description;
-- }
-- }
--
-- return NULL;
--}
--
--guint8*
--icq_get_custom_icon_data(const char *mood)
--{
-- int i;
--
-- if (!(mood && *mood))
-- return NULL;
--
-- for (i = 0; icq_custom_icons[i].mood; i++) {
-- /* We check that description is not NULL to exclude
-- * duplicates, like the typing duplicate. */
-- if (icq_purple_moods[i].description &&
-- !strcmp(mood, icq_custom_icons[i].mood)) {
-- return (guint8 *)icq_custom_icons[i].data;
-- }
-- }
-- return NULL;
--}
--
--PurpleMood*
--icq_get_purple_moods(PurpleAccount *account)
--{
-- return icq_purple_moods;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_oservice.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_oservice.c
---- pidgin-2.10.7/libpurple/protocols/oscar/family_oservice.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_oservice.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1132 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Family 0x0001 - This is a very special group. All connections support
-- * this group, as it does some particularly good things (like rate limiting).
-- */
--
--#include "oscar.h"
--
--#include "cipher.h"
--
--/*
-- * Each time we make a FLAP connection to an oscar server the server gives
-- * us a list of rate classes. Each rate class has different properties for
-- * how frequently we can send SNACs in that rate class before we become
-- * throttled or disconnected.
-- *
-- * The server also gives us a list of every available SNAC and tells us which
-- * rate class it's in. There are a lot of different SNACs, so this list can be
-- * fairly large. One important characteristic of these rate classes is that
-- * currently (and since at least 2004) most SNACs are in the same rate class.
-- *
-- * One optimization we can do to save memory is to only keep track of SNACs
-- * that are in classes other than this default rate class. So if we try to
-- * look up a SNAC and it's not in our hash table then we can assume that it's
-- * in the default rate class.
-- */
--#define OSCAR_DEFAULT_RATECLASS 1
--
--/* Subtype 0x0002 - Client Online */
--void
--aim_srv_clientready(OscarData *od, FlapConnection *conn)
--{
-- ByteStream bs;
-- aim_snacid_t snacid;
-- GSList *cur;
--
-- byte_stream_new(&bs, 1142);
--
-- /*
-- * Send only the tool versions that the server cares about (that it
-- * marked as supporting in the server ready SNAC).
-- */
-- for (cur = conn->groups; cur != NULL; cur = cur->next)
-- {
-- aim_module_t *mod;
--
-- if ((mod = aim__findmodulebygroup(od, GPOINTER_TO_UINT(cur->data))))
-- {
-- byte_stream_put16(&bs, mod->family);
-- byte_stream_put16(&bs, mod->version);
-- byte_stream_put16(&bs, mod->toolid);
-- byte_stream_put16(&bs, mod->toolversion);
-- }
-- }
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0002, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0002, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--/*
-- * Subtype 0x0003 - Host Online
-- *
-- * See comments in conn.c about how the group associations are supposed
-- * to work, and how they really work.
-- *
-- * This info probably doesn't even need to make it to the client.
-- *
-- * We don't actually call the client here. This starts off the connection
-- * initialization routine required by all AIM connections. The next time
-- * the client is called is the CONNINITDONE callback, which should be
-- * shortly after the rate information is acknowledged.
-- *
-- */
--static int
--hostonline(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int group;
--
-- while (byte_stream_bytes_left(bs))
-- {
-- group = byte_stream_get16(bs);
-- conn->groups = g_slist_prepend(conn->groups, GUINT_TO_POINTER(group));
-- }
--
-- /*
-- * Next step is in the Host Versions handler.
-- *
-- * Note that we must send this before we request rates, since
-- * the format of the rate information depends on the versions we
-- * give it.
-- *
-- */
-- aim_srv_setversions(od, conn);
--
-- return 1;
--}
--
--/* Subtype 0x0004 - Service request */
--void
--aim_srv_requestnew(OscarData *od, guint16 serviceid)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- GSList *tlvlist = NULL;
--
-- conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS);
-- if(!conn)
-- return;
--
-- byte_stream_new(&bs, 6);
--
-- byte_stream_put16(&bs, serviceid);
--
-- if (od->use_ssl)
-- /* Request SSL Connection */
-- aim_tlvlist_add_noval(&tlvlist, 0x008c);
--
-- aim_tlvlist_write(&bs, &tlvlist);
-- aim_tlvlist_free(tlvlist);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0004, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0004, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--/*
-- * Join a room of name roomname. This is the first step to joining an
-- * already created room. It's basically a Service Request for
-- * family 0x000e, with a little added on to specify the exchange and room
-- * name.
-- */
--int
--aim_chat_join(OscarData *od, guint16 exchange, const char *roomname, guint16 instance)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- GSList *tlvlist = NULL;
-- struct chatsnacinfo csi;
--
-- conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS);
-- if (!conn || !roomname || roomname[0] == '\0')
-- return -EINVAL;
--
-- byte_stream_new(&bs, 506);
--
-- memset(&csi, 0, sizeof(csi));
-- csi.exchange = exchange;
-- g_strlcpy(csi.name, roomname, sizeof(csi.name));
-- csi.instance = instance;
--
-- /*
-- * Requesting service chat (0x000e)
-- */
-- byte_stream_put16(&bs, 0x000e);
--
-- aim_tlvlist_add_chatroom(&tlvlist, 0x0001, exchange, roomname, instance);
--
-- if (od->use_ssl)
-- /* Request SSL Connection */
-- aim_tlvlist_add_noval(&tlvlist, 0x008c);
--
-- aim_tlvlist_write(&bs, &tlvlist);
-- aim_tlvlist_free(tlvlist);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0004, 0x0000, &csi, sizeof(csi));
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0004, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/* Subtype 0x0005 - Redirect */
--static int
--redirect(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- struct aim_redirect_data redir;
-- aim_rxcallback_t userfunc;
-- GSList *tlvlist;
-- aim_snac_t *origsnac = NULL;
-- int ret = 0;
--
-- memset(&redir, 0, sizeof(redir));
--
-- tlvlist = aim_tlvlist_read(bs);
--
-- if (!aim_tlv_gettlv(tlvlist, 0x000d, 1) ||
-- !aim_tlv_gettlv(tlvlist, 0x0005, 1) ||
-- !aim_tlv_gettlv(tlvlist, 0x0006, 1)) {
-- aim_tlvlist_free(tlvlist);
-- return 0;
-- }
--
-- redir.group = aim_tlv_get16(tlvlist, 0x000d, 1);
-- redir.ip = aim_tlv_getstr(tlvlist, 0x0005, 1);
-- redir.cookielen = aim_tlv_gettlv(tlvlist, 0x0006, 1)->length;
-- redir.cookie = (guchar *)aim_tlv_getstr(tlvlist, 0x0006, 1);
-- redir.ssl_cert_cn = aim_tlv_getstr(tlvlist, 0x008d, 1);
-- redir.use_ssl = aim_tlv_get8(tlvlist, 0x008e, 1);
--
-- /* Fetch original SNAC so we can get csi if needed */
-- origsnac = aim_remsnac(od, snac->id);
--
-- if ((redir.group == SNAC_FAMILY_CHAT) && origsnac) {
-- struct chatsnacinfo *csi = (struct chatsnacinfo *)origsnac->data;
--
-- redir.chat.exchange = csi->exchange;
-- redir.chat.room = csi->name;
-- redir.chat.instance = csi->instance;
-- }
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, &redir);
--
-- g_free((void *)redir.ip);
-- g_free((void *)redir.cookie);
-- g_free((void *)redir.ssl_cert_cn);
--
-- if (origsnac)
-- g_free(origsnac->data);
-- g_free(origsnac);
--
-- aim_tlvlist_free(tlvlist);
--
-- return ret;
--}
--
--/* Subtype 0x0006 - Request Rate Information. */
--void
--aim_srv_reqrates(OscarData *od, FlapConnection *conn)
--{
-- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_OSERVICE, 0x0006);
--}
--
--/*
-- * OSCAR defines several 'rate classes'. Each class has separate
-- * rate limiting properties (limit level, alert level, disconnect
-- * level, etc), and a set of SNAC family/type pairs associated with
-- * it. The rate classes, their limiting properties, and the definitions
-- * of which SNACs belong to which class are defined in the
-- * Rate Response packet at login to each host.
-- *
-- * Logically, all rate offenses within one class count against further
-- * offenses for other SNACs in the same class (ie, sending messages
-- * too fast will limit the number of user info requests you can send,
-- * since those two SNACs are in the same rate class).
-- *
-- * Since the rate classes are defined dynamically at login, the values
-- * below may change. But they seem to be fairly constant.
-- *
-- * Currently, BOS defines five rate classes, with the commonly used
-- * members as follows...
-- *
-- * Rate class 0x0001:
-- * - Everything thats not in any of the other classes
-- *
-- * Rate class 0x0002:
-- * - Buddy list add/remove
-- * - Permit list add/remove
-- * - Deny list add/remove
-- *
-- * Rate class 0x0003:
-- * - User information requests
-- * - Outgoing ICBMs
-- *
-- * Rate class 0x0004:
-- * - A few unknowns: 2/9, 2/b, and f/2
-- *
-- * Rate class 0x0005:
-- * - Chat room create
-- * - Outgoing chat ICBMs
-- *
-- * The only other thing of note is that class 5 (chat) has slightly looser
-- * limiting properties than class 3 (normal messages). But thats just a
-- * small bit of trivia for you.
-- *
-- * The last thing that needs to be learned about the rate limiting
-- * system is how the actual numbers relate to the passing of time. This
-- * seems to be a big mystery.
-- *
-- * See joscar's javadoc for the RateClassInfo class for a great
-- * explanation. You might be able to find it at
-- * http://dscoder.com/RateClassInfo.html
-- */
--
--static struct rateclass *
--rateclass_find(GSList *rateclasses, guint16 id)
--{
-- GSList *tmp;
--
-- for (tmp = rateclasses; tmp != NULL; tmp = tmp->next)
-- {
-- struct rateclass *rateclass;
-- rateclass = tmp->data;
-- if (rateclass->classid == id)
-- return rateclass;
-- }
--
-- return NULL;
--}
--
--/* Subtype 0x0007 - Rate Parameters */
--static int
--rateresp(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- guint16 numclasses, i;
-- aim_rxcallback_t userfunc;
--
-- /*
-- * First are the parameters for each rate class.
-- */
-- numclasses = byte_stream_get16(bs);
-- for (i = 0; i < numclasses; i++)
-- {
-- struct rateclass *rateclass;
-- guint32 delta;
-- struct timeval now;
--
-- gettimeofday(&now, NULL);
-- rateclass = g_new(struct rateclass, 1);
--
-- rateclass->classid = byte_stream_get16(bs);
-- rateclass->windowsize = byte_stream_get32(bs);
-- rateclass->clear = byte_stream_get32(bs);
-- rateclass->alert = byte_stream_get32(bs);
-- rateclass->limit = byte_stream_get32(bs);
-- rateclass->disconnect = byte_stream_get32(bs);
-- rateclass->current = byte_stream_get32(bs);
-- rateclass->max = byte_stream_get32(bs);
-- if (mod->version >= 3) {
-- delta = byte_stream_get32(bs);
-- rateclass->dropping_snacs = byte_stream_get8(bs);
-- } else {
-- delta = 0;
-- rateclass->dropping_snacs = 0;
-- }
--
-- rateclass->last.tv_sec = now.tv_sec - delta / 1000;
-- rateclass->last.tv_usec = now.tv_usec - (delta % 1000) * 1000;
--
-- conn->rateclasses = g_slist_prepend(conn->rateclasses, rateclass);
--
-- if (rateclass->classid == OSCAR_DEFAULT_RATECLASS)
-- conn->default_rateclass = rateclass;
-- }
-- conn->rateclasses = g_slist_reverse(conn->rateclasses);
--
-- /*
-- * Then the members of each class.
-- */
-- for (i = 0; i < numclasses; i++)
-- {
-- guint16 classid, count;
-- struct rateclass *rateclass;
-- int j;
--
-- classid = byte_stream_get16(bs);
-- count = byte_stream_get16(bs);
--
-- if (classid == OSCAR_DEFAULT_RATECLASS) {
-- /*
-- * Don't bother adding these SNACs to the hash table. See the
-- * comment for OSCAR_DEFAULT_RATECLASS at the top of this file.
-- */
-- byte_stream_advance(bs, 4 * count);
-- continue;
-- }
--
-- rateclass = rateclass_find(conn->rateclasses, classid);
--
-- for (j = 0; j < count; j++)
-- {
-- guint16 group, subtype;
--
-- group = byte_stream_get16(bs);
-- subtype = byte_stream_get16(bs);
--
-- if (rateclass != NULL)
-- g_hash_table_insert(conn->rateclass_members,
-- GUINT_TO_POINTER((group << 16) + subtype),
-- rateclass);
-- }
-- }
--
-- /*
-- * We don't pass the rate information up to the client, as it really
-- * doesn't care. The information is stored in the connection, however
-- * so that we can do rate limiting management when sending SNACs.
-- */
--
-- /*
-- * Subscribe to rate change information for all rate classes.
-- */
-- aim_srv_rates_addparam(od, conn);
--
-- /*
-- * Finally, tell the client it's ready to go...
-- */
-- if ((userfunc = aim_callhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE)))
-- userfunc(od, conn, frame);
--
-- return 1;
--}
--
--/* Subtype 0x0008 - Add Rate Parameter */
--void
--aim_srv_rates_addparam(OscarData *od, FlapConnection *conn)
--{
-- ByteStream bs;
-- aim_snacid_t snacid;
-- GSList *tmp;
--
-- byte_stream_new(&bs, 502);
--
-- for (tmp = conn->rateclasses; tmp != NULL; tmp = tmp->next)
-- {
-- struct rateclass *rateclass;
-- rateclass = tmp->data;
-- byte_stream_put16(&bs, rateclass->classid);
-- }
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0008, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0008, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--/* Subtype 0x000a - Rate Change */
--static int
--ratechange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- guint16 code, classid;
-- struct rateclass *rateclass;
-- guint32 delta;
-- struct timeval now;
-- static const char *codes[5] = {
-- "invalid",
-- "change",
-- "warning",
-- "limit",
-- "limit cleared",
-- };
--
-- gettimeofday(&now, NULL);
-- code = byte_stream_get16(bs);
-- classid = byte_stream_get16(bs);
--
-- rateclass = rateclass_find(conn->rateclasses, classid);
-- if (rateclass == NULL)
-- /* This should never really happen */
-- return 0;
--
-- rateclass->windowsize = byte_stream_get32(bs);
-- rateclass->clear = byte_stream_get32(bs);
-- rateclass->alert = byte_stream_get32(bs);
-- rateclass->limit = byte_stream_get32(bs);
-- rateclass->disconnect = byte_stream_get32(bs);
-- rateclass->current = byte_stream_get32(bs);
-- rateclass->max = byte_stream_get32(bs);
-- if (mod->version >= 3) {
-- delta = byte_stream_get32(bs);
-- rateclass->dropping_snacs = byte_stream_get8(bs);
-- } else {
-- delta = 0;
-- rateclass->dropping_snacs = 0;
-- }
--
-- rateclass->last.tv_sec = now.tv_sec - delta / 1000;
-- rateclass->last.tv_usec = now.tv_usec - (delta % 1000) * 1000;
--
-- purple_debug_misc("oscar", "rate %s (param ID 0x%04hx): curavg = %u, "
-- "maxavg = %u, alert at %u, clear warning at %u, limit at %u, "
-- "disconnect at %u, delta is %u, dropping is %u (window size = %u)\n",
-- (code < 5) ? codes[code] : codes[0], rateclass->classid,
-- rateclass->current, rateclass->max, rateclass->alert,
-- rateclass->clear, rateclass->limit, rateclass->disconnect,
-- delta, rateclass->dropping_snacs, rateclass->windowsize);
--
-- if (code == AIM_RATE_CODE_LIMIT) {
-- purple_debug_warning("oscar", "The last action you attempted "
-- "could not be performed because you are over the rate "
-- "limit. Please wait 10 seconds and try again.\n");
-- }
--
-- return 1;
--}
--
--/*
-- * How Migrations work.
-- *
-- * The server sends a Server Pause message, which the client should respond to
-- * with a Server Pause Ack, which contains the families it needs on this
-- * connection. The server will send a Migration Notice with an IP address, and
-- * then disconnect. Next the client should open the connection and send the
-- * cookie. Repeat the normal login process and pretend this never happened.
-- *
-- * The Server Pause contains no data.
-- *
-- */
--
--/* Subtype 0x000b - Service Pause */
--static int
--serverpause(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame);
--
-- return ret;
--}
--
--/* Subtype 0x000d - Service Resume */
--static int
--serverresume(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame);
--
-- return ret;
--}
--
--/* Subtype 0x000e - Request self-info */
--void
--aim_srv_reqpersonalinfo(OscarData *od, FlapConnection *conn)
--{
-- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_OSERVICE, 0x000e);
--}
--
--/* Subtype 0x000f - Self User Info */
--static int
--selfinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- aim_userinfo_t userinfo;
--
-- aim_info_extract(od, bs, &userinfo);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, &userinfo);
--
-- aim_info_free(&userinfo);
--
-- return ret;
--}
--
--/* Subtype 0x0010 - Evil Notification */
--static int
--evilnotify(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- guint16 newevil;
-- aim_userinfo_t userinfo;
--
-- memset(&userinfo, 0, sizeof(aim_userinfo_t));
--
-- newevil = byte_stream_get16(bs);
--
-- if (byte_stream_bytes_left(bs))
-- aim_info_extract(od, bs, &userinfo);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, newevil, &userinfo);
--
-- aim_info_free(&userinfo);
--
-- return ret;
--}
--
--/*
-- * Subtype 0x0011 - Idle Notification
-- *
-- * Should set your current idle time in seconds. Note that this should
-- * never be called consecutively with a non-zero idle time. That makes
-- * OSCAR do funny things. Instead, just set it once you go idle, and then
-- * call it again with zero when you're back.
-- *
-- */
--void
--aim_srv_setidle(OscarData *od, guint32 idletime)
--{
-- FlapConnection *conn;
--
-- conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS);
-- if(!conn)
-- return;
--
-- aim_genericreq_l(od, conn, SNAC_FAMILY_OSERVICE, 0x0011, &idletime);
--}
--
--/*
-- * Subtype 0x0012 - Service Migrate
-- *
-- * This is the final SNAC sent on the original connection during a migration.
-- * It contains the IP and cookie used to connect to the new server, and
-- * optionally a list of the SNAC groups being migrated.
-- *
-- */
--static int
--migrate(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- aim_rxcallback_t userfunc;
-- int ret = 0;
-- guint16 groupcount, i;
-- GSList *tlvlist;
-- char *ip = NULL;
-- aim_tlv_t *cktlv;
--
-- /*
-- * Apparently there's some fun stuff that can happen right here. The
-- * migration can actually be quite selective about what groups it
-- * moves to the new server. When not all the groups for a connection
-- * are migrated, or they are all migrated but some groups are moved
-- * to a different server than others, it is called a bifurcated
-- * migration.
-- *
-- * Let's play dumb and not support that.
-- *
-- */
-- groupcount = byte_stream_get16(bs);
-- for (i = 0; i < groupcount; i++) {
-- guint16 group;
--
-- group = byte_stream_get16(bs);
--
-- purple_debug_misc("oscar", "bifurcated migration unsupported -- group 0x%04x\n", group);
-- }
--
-- tlvlist = aim_tlvlist_read(bs);
--
-- if (aim_tlv_gettlv(tlvlist, 0x0005, 1))
-- ip = aim_tlv_getstr(tlvlist, 0x0005, 1);
--
-- cktlv = aim_tlv_gettlv(tlvlist, 0x0006, 1);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, ip, cktlv ? cktlv->value : NULL);
--
-- aim_tlvlist_free(tlvlist);
-- g_free(ip);
--
-- return ret;
--}
--
--/* Subtype 0x0013 - Message of the Day */
--static int
--motd(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- aim_rxcallback_t userfunc;
-- char *msg = NULL;
-- int ret = 0;
-- GSList *tlvlist;
-- guint16 id;
--
-- /*
-- * Code.
-- *
-- * Valid values:
-- * 1 Mandatory upgrade
-- * 2 Advisory upgrade
-- * 3 System bulletin
-- * 4 Nothing's wrong ("top o the world" -- normal)
-- * 5 Lets-break-something.
-- *
-- */
-- id = byte_stream_get16(bs);
--
-- /*
-- * TLVs follow
-- */
-- tlvlist = aim_tlvlist_read(bs);
--
-- msg = aim_tlv_getstr(tlvlist, 0x000b, 1);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, id, msg);
--
-- g_free(msg);
--
-- aim_tlvlist_free(tlvlist);
--
-- return ret;
--}
--
--/*
-- * Subtype 0x0017 - Set client versions
-- *
-- * If you've seen the clientonline/clientready SNAC you're probably
-- * wondering what the point of this one is. And that point seems to be
-- * that the versions in the client online SNAC are sent too late for the
-- * server to be able to use them to change the protocol for the earlier
-- * login packets (client versions are sent right after Host Online is
-- * received, but client online versions aren't sent until quite a bit later).
-- * We can see them already making use of this by changing the format of
-- * the rate information based on what version of group 1 we advertise here.
-- *
-- */
--void
--aim_srv_setversions(OscarData *od, FlapConnection *conn)
--{
-- ByteStream bs;
-- aim_snacid_t snacid;
-- GSList *cur;
--
-- byte_stream_new(&bs, 1142);
--
-- /*
-- * Send only the versions that the server cares about (that it
-- * marked as supporting in the server ready SNAC).
-- */
-- for (cur = conn->groups; cur != NULL; cur = cur->next)
-- {
-- aim_module_t *mod;
--
-- if ((mod = aim__findmodulebygroup(od, GPOINTER_TO_UINT(cur->data))))
-- {
-- byte_stream_put16(&bs, mod->family);
-- byte_stream_put16(&bs, mod->version);
-- }
-- }
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0017, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0017, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--/* Subtype 0x0018 - Host versions */
--static int
--hostversions(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int vercount;
-- guint8 *versions;
--
-- /* This is frivolous. (Thank you SmarterChild.) */
-- vercount = byte_stream_bytes_left(bs)/4;
-- versions = byte_stream_getraw(bs, byte_stream_bytes_left(bs));
-- g_free(versions);
--
-- /*
-- * Now request rates.
-- */
-- aim_srv_reqrates(od, conn);
--
-- return 1;
--}
--
--/**
-- * Subtype 0x001e - Extended Status/Extra Info.
-- *
-- * These settings are transient, not server-stored (i.e. they only
-- * apply to this session, and must be re-set the next time you sign
-- * on).
-- *
-- * You can set your ICQ status (available, away, do not disturb,
-- * etc.), or whether your IP address should be hidden or not, or
-- * if your status is visible on ICQ web sites, and you can set
-- * your IP address info and what not.
-- *
-- * You can also set your "available" message. This is currently
-- * only supported by iChat, Purple and other 3rd party clients.
-- *
-- * These are the same TLVs seen in user info. You can
-- * also set 0x0008 and 0x000c.
-- */
--int
--aim_srv_setextrainfo(OscarData *od,
-- gboolean seticqstatus, guint32 icqstatus,
-- gboolean setstatusmsg, const char *statusmsg, const char *itmsurl)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
-- GSList *tlvlist = NULL;
--
-- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
-- return -EINVAL;
--
-- if (seticqstatus)
-- {
-- aim_tlvlist_add_32(&tlvlist, 0x0006, icqstatus |
-- AIM_ICQ_STATE_HIDEIP | AIM_ICQ_STATE_DIRECTREQUIREAUTH);
-- }
--
-- if (setstatusmsg)
-- {
-- size_t statusmsglen, itmsurllen;
-- ByteStream tmpbs;
--
-- statusmsglen = (statusmsg != NULL) ? strlen(statusmsg) : 0;
-- itmsurllen = (itmsurl != NULL) ? strlen(itmsurl) : 0;
--
-- byte_stream_new(&tmpbs, statusmsglen + 8 + itmsurllen + 8);
-- byte_stream_put_bart_asset_str(&tmpbs, 0x0002, statusmsg);
-- byte_stream_put_bart_asset_str(&tmpbs, 0x0009, itmsurl);
--
-- aim_tlvlist_add_raw(&tlvlist, 0x001d,
-- byte_stream_curpos(&tmpbs), tmpbs.data);
-- byte_stream_destroy(&tmpbs);
-- }
--
-- byte_stream_new(&bs, aim_tlvlist_size(tlvlist));
--
-- aim_tlvlist_write(&bs, &tlvlist);
-- aim_tlvlist_free(tlvlist);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x001e, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x001e, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/* Send dummy DC (direct connect) information to the server.
-- * Direct connect is ICQ's counterpart for AIM's DirectIM,
-- * as far as I can tell. Anyway, we don't support it;
-- * the reason to send this packet is that some clients
-- * (Miranda, QIP) won't send us channel 2 ICBM messages
-- * unless we specify DC version >= 8.
-- *
-- * See #12044 for more information.
-- */
--void
--aim_srv_set_dc_info(OscarData *od)
--{
-- ByteStream bs, tlv0c;
-- aim_snacid_t snacid;
-- GSList *tlvlist = NULL;
--
-- /* http://iserverd.khstu.ru/oscar/snac_01_1e.html has a nice analysis of what goes in 0xc tlv.
-- * Kopete sends a dummy DC info, too, so I just copied the values from them.
-- */
-- byte_stream_new(&tlv0c, 4*2 + 1 + 2 + 4*6 + 2);
-- byte_stream_put32(&tlv0c, 0x0);
-- byte_stream_put32(&tlv0c, 0x0);
-- byte_stream_put8(&tlv0c, 0x0); /* We don't support DC */
-- byte_stream_put16(&tlv0c, 8); /* DC version */
-- byte_stream_put32(&tlv0c, 0x0);
-- byte_stream_put32(&tlv0c, 0x50);
-- byte_stream_put32(&tlv0c, 0x3);
-- byte_stream_put32(&tlv0c, 0x0);
-- byte_stream_put32(&tlv0c, 0x0);
-- byte_stream_put32(&tlv0c, 0x0);
-- byte_stream_put16(&tlv0c, 0x0);
-- aim_tlvlist_add_raw(&tlvlist, 0x000c, byte_stream_curpos(&tlv0c), tlv0c.data);
-- byte_stream_destroy(&tlv0c);
--
-- byte_stream_new(&bs, aim_tlvlist_size(tlvlist));
-- aim_tlvlist_write(&bs, &tlvlist);
-- aim_tlvlist_free(tlvlist);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x001e, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, flap_connection_findbygroup(od, SNAC_FAMILY_ICBM), SNAC_FAMILY_OSERVICE, 0x001e, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--/**
-- * Starting this past week (26 Mar 2001, say), AOL has started sending
-- * this nice little extra SNAC. AFAIK, it has never been used until now.
-- *
-- * The request contains eight bytes. The first four are an offset, the
-- * second four are a length.
-- *
-- * The offset is an offset into aim.exe when it is mapped during execution
-- * on Win32. So far, AOL has only been requesting bytes in static regions
-- * of memory. (I won't put it past them to start requesting data in
-- * less static regions -- regions that are initialized at run time, but still
-- * before the client receives this request.)
-- *
-- * When the client receives the request, it adds it to the current ds
-- * (0x00400000) and dereferences it, copying the data into a buffer which
-- * it then runs directly through the MD5 hasher. The 16 byte output of
-- * the hash is then sent back to the server.
-- *
-- * If the client does not send any data back, or the data does not match
-- * the data that the specific client should have, the client will get the
-- * following message from "AOL Instant Messenger":
-- * "You have been disconnected from the AOL Instant Message Service (SM)
-- * for accessing the AOL network using unauthorized software. You can
-- * download a FREE, fully featured, and authorized client, here
-- * http://www.aol.com/aim/download2.html"
-- * The connection is then closed, receiving disconnect code 1, URL
-- * http://www.aim.aol.com/errors/USER_LOGGED_OFF_NEW_LOGIN.html.
-- *
-- * Note, however, that numerous inconsistencies can cause the above error,
-- * not just sending back a bad hash. Do not immediatly suspect this code
-- * if you get disconnected. AOL and the open/free software community have
-- * played this game for a couple years now, generating the above message
-- * on numerous ocassions.
-- *
-- * Anyway, neener. We win again.
-- *
-- */
--/* Subtype 0x001f - Client verification */
--static int
--memrequest(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- guint32 offset, len;
-- GSList *tlvlist;
-- char *modname;
--
-- offset = byte_stream_get32(bs);
-- len = byte_stream_get32(bs);
-- tlvlist = aim_tlvlist_read(bs);
--
-- modname = aim_tlv_getstr(tlvlist, 0x0001, 1);
--
-- purple_debug_info("oscar", "Got memory request for data at 0x%08x (%u bytes) of requested %s\n", offset, len, modname ? modname : "aim.exe");
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, offset, len, modname);
--
-- g_free(modname);
-- aim_tlvlist_free(tlvlist);
--
-- return ret;
--}
--
--/* Subtype 0x0020 - Client verification reply */
--int
--aim_sendmemblock(OscarData *od, FlapConnection *conn, guint32 offset, guint32 len, const guint8 *buf, guint8 flag)
--{
-- ByteStream bs;
-- aim_snacid_t snacid;
--
-- if (!od || !conn)
-- return -EINVAL;
--
-- byte_stream_new(&bs, 2+16);
--
-- byte_stream_put16(&bs, 0x0010); /* md5 is always 16 bytes */
--
-- if ((flag == AIM_SENDMEMBLOCK_FLAG_ISHASH) && buf && (len == 0x10)) { /* we're getting a hash */
--
-- byte_stream_putraw(&bs, buf, 0x10);
--
-- } else if (buf && (len > 0)) { /* use input buffer */
-- PurpleCipherContext *context;
-- guchar digest[16];
--
-- context = purple_cipher_context_new_by_name("md5", NULL);
-- purple_cipher_context_append(context, buf, len);
-- purple_cipher_context_digest(context, 16, digest, NULL);
-- purple_cipher_context_destroy(context);
--
-- byte_stream_putraw(&bs, digest, 0x10);
--
-- } else if (len == 0) { /* no length, just hash NULL (buf is optional) */
-- PurpleCipherContext *context;
-- guchar digest[16];
-- guint8 nil = '\0';
--
-- /*
-- * I'm not sure if we really need the empty append with the
-- * new MD5 functions, so I'll leave it in, just in case.
-- */
-- context = purple_cipher_context_new_by_name("md5", NULL);
-- purple_cipher_context_append(context, &nil, 0);
-- purple_cipher_context_digest(context, 16, digest, NULL);
-- purple_cipher_context_destroy(context);
--
-- byte_stream_putraw(&bs, digest, 0x10);
--
-- } else {
--
-- /*
-- * This data is correct for AIM 3.5.1670.
-- *
-- * Using these blocks is as close to "legal" as you can get
-- * without using an AIM binary.
-- *
-- */
-- if ((offset == 0x03ffffff) && (len == 0x03ffffff)) {
--
--#if 1 /* with "AnrbnrAqhfzcd" */
-- byte_stream_put32(&bs, 0x44a95d26);
-- byte_stream_put32(&bs, 0xd2490423);
-- byte_stream_put32(&bs, 0x93b8821f);
-- byte_stream_put32(&bs, 0x51c54b01);
--#else /* no filename */
-- byte_stream_put32(&bs, 0x1df8cbae);
-- byte_stream_put32(&bs, 0x5523b839);
-- byte_stream_put32(&bs, 0xa0e10db3);
-- byte_stream_put32(&bs, 0xa46d3b39);
--#endif
--
-- } else
-- purple_debug_warning("oscar", "sendmemblock: unknown hash request\n");
--
-- }
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0020, 0x0000, NULL, 0);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0020, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0021 - Receive our extended status
-- *
-- * This is used for iChat's "available" messages, and maybe ICQ extended
-- * status messages? It's also used to tell the client whether or not it
-- * needs to upload an SSI buddy icon... who engineers this stuff, anyway?
-- */
--static int
--aim_parse_extstatus(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- guint16 type = byte_stream_get16(bs);
-- if (type == 0x0000 || type == 0x0001) {
-- /* buddy icon checksum */
-- /* not sure what the difference between 1 and 0 is */
-- guint8 flags = byte_stream_get8(bs);
-- guint8 length = byte_stream_get8(bs);
-- guint8 *md5 = byte_stream_getraw(bs, length);
--
-- if ((flags == 0x00) || (flags == 0x41)) {
-- if (!flap_connection_getbytype(od, SNAC_FAMILY_BART) && !od->iconconnecting) {
-- od->iconconnecting = TRUE;
-- od->set_icon = TRUE;
-- aim_srv_requestnew(od, SNAC_FAMILY_BART);
-- } else {
-- PurpleAccount *account = purple_connection_get_account(od->gc);
-- PurpleStoredImage *img = purple_buddy_icons_find_account_icon(account);
-- if (img == NULL) {
-- aim_ssi_delicon(od);
-- } else {
--
-- purple_debug_info("oscar",
-- "Uploading icon to icon server\n");
-- aim_bart_upload(od, purple_imgstore_get_data(img),
-- purple_imgstore_get_size(img));
-- purple_imgstore_unref(img);
-- }
-- }
-- } else if (flags == 0x81) {
-- PurpleAccount *account = purple_connection_get_account(od->gc);
-- PurpleStoredImage *img = purple_buddy_icons_find_account_icon(account);
-- if (img == NULL)
-- aim_ssi_delicon(od);
-- else {
-- aim_ssi_seticon(od, md5, length);
-- purple_imgstore_unref(img);
-- }
-- }
--
-- g_free(md5);
-- }
--
-- return 0;
--}
--
--static int
--snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- if (snac->subtype == 0x0003)
-- return hostonline(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x0005)
-- return redirect(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x0007)
-- return rateresp(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x000a)
-- return ratechange(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x000b)
-- return serverpause(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x000d)
-- return serverresume(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x000f)
-- return selfinfo(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x0010)
-- return evilnotify(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x0012)
-- return migrate(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x0013)
-- return motd(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x0018)
-- return hostversions(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x001f)
-- return memrequest(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x0021)
-- return aim_parse_extstatus(od, conn, mod, frame, snac, bs);
--
-- return 0;
--}
--
--int service_modfirst(OscarData *od, aim_module_t *mod)
--{
-- mod->family = SNAC_FAMILY_OSERVICE;
-- mod->version = 0x0003;
-- mod->toolid = 0x0110;
-- mod->toolversion = 0x0629;
-- mod->flags = 0;
-- strncpy(mod->name, "oservice", sizeof(mod->name));
-- mod->snachandler = snachandler;
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_popup.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_popup.c
---- pidgin-2.10.7/libpurple/protocols/oscar/family_popup.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_popup.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,84 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Family 0x0008 - Popups.
-- *
-- * Popups are just what it sounds like. They're a way for the server to
-- * open up an informative box on the client's screen.
-- */
--
--#include <oscar.h>
--
--/*
-- * This is all there is to it.
-- *
-- * The message is probably HTML.
-- *
-- */
--static int
--parsepopup(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- aim_rxcallback_t userfunc;
-- GSList *tlvlist;
-- int ret = 0;
-- char *msg, *url;
-- guint16 width, height, delay;
--
-- tlvlist = aim_tlvlist_read(bs);
--
-- msg = aim_tlv_getstr(tlvlist, 0x0001, 1);
-- url = aim_tlv_getstr(tlvlist, 0x0002, 1);
-- width = aim_tlv_get16(tlvlist, 0x0003, 1);
-- height = aim_tlv_get16(tlvlist, 0x0004, 1);
-- delay = aim_tlv_get16(tlvlist, 0x0005, 1);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, msg, url, width, height, delay);
--
-- aim_tlvlist_free(tlvlist);
-- g_free(msg);
-- g_free(url);
--
-- return ret;
--}
--
--static int
--snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- if (snac->subtype == 0x0002)
-- return parsepopup(od, conn, mod, frame, snac, bs);
--
-- return 0;
--}
--
--int
--popups_modfirst(OscarData *od, aim_module_t *mod)
--{
-- mod->family = SNAC_FAMILY_POPUP;
-- mod->version = 0x0001;
-- mod->toolid = 0x0104;
-- mod->toolversion = 0x0001;
-- mod->flags = 0;
-- strncpy(mod->name, "popup", sizeof(mod->name));
-- mod->snachandler = snachandler;
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_stats.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_stats.c
---- pidgin-2.10.7/libpurple/protocols/oscar/family_stats.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_stats.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,64 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Family 0x000b - Statistics.
-- *
-- */
--
--#include <oscar.h>
--
--static int
--reportinterval(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- guint16 interval;
--
-- interval = byte_stream_get16(bs);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, interval);
--
-- return ret;
--}
--
--static int
--snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- if (snac->subtype == 0x0002)
-- return reportinterval(od, conn, mod, frame, snac, bs);
--
-- return 0;
--}
--
--int
--stats_modfirst(OscarData *od, aim_module_t *mod)
--{
-- mod->family = SNAC_FAMILY_STATS;
-- mod->version = 0x0001;
-- mod->toolid = 0x0104;
-- mod->toolversion = 0x0001;
-- mod->flags = 0;
-- strncpy(mod->name, "stats", sizeof(mod->name));
-- mod->snachandler = snachandler;
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_userlookup.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_userlookup.c
---- pidgin-2.10.7/libpurple/protocols/oscar/family_userlookup.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_userlookup.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,157 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Family 0x000a - User Search.
-- *
-- * TODO: Add aim_usersearch_name()
-- *
-- */
--
--#include "oscar.h"
--
--/*
-- * Subtype 0x0001
-- *
-- * XXX can this be integrated with the rest of the error handling?
-- */
--static int error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- aim_rxcallback_t userfunc;
-- aim_snac_t *snac2;
--
-- /* XXX the modules interface should have already retrieved this for us */
-- if (!(snac2 = aim_remsnac(od, snac->id))) {
-- purple_debug_misc("oscar", "search error: couldn't get a snac for 0x%08x\n", snac->id);
-- return 0;
-- }
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, snac2->data /* address */);
--
-- /* XXX freesnac()? */
-- if (snac2)
-- g_free(snac2->data);
-- g_free(snac2);
--
-- return ret;
--}
--
--/*
-- * Subtype 0x0002
-- *
-- */
--int aim_search_address(OscarData *od, const char *address)
--{
-- FlapConnection *conn;
-- ByteStream bs;
-- aim_snacid_t snacid;
--
-- conn = flap_connection_findbygroup(od, SNAC_FAMILY_USERLOOKUP);
--
-- if (!conn || !address)
-- return -EINVAL;
--
-- byte_stream_new(&bs, strlen(address));
--
-- byte_stream_putstr(&bs, address);
--
-- snacid = aim_cachesnac(od, SNAC_FAMILY_USERLOOKUP, 0x0002, 0x0000, address, strlen(address)+1);
-- flap_connection_send_snac(od, conn, SNAC_FAMILY_USERLOOKUP, 0x0002, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--
-- return 0;
--}
--
--/*
-- * Subtype 0x0003
-- *
-- */
--static int reply(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int j = 0, m, ret = 0;
-- GSList *tlvlist;
-- char *cur = NULL, *buf = NULL;
-- aim_rxcallback_t userfunc;
-- aim_snac_t *snac2;
-- const char *searchaddr = NULL;
--
-- if ((snac2 = aim_remsnac(od, snac->id)))
-- searchaddr = (const char *)snac2->data;
--
-- tlvlist = aim_tlvlist_read(bs);
-- m = aim_tlvlist_count(tlvlist);
--
-- /* XXX uhm.
-- * This is the only place that uses something other than 1 for the 3rd
-- * parameter to aim_tlv_gettlv_whatever().
-- */
-- while ((cur = aim_tlv_getstr(tlvlist, 0x0001, j+1)) && j < m)
-- {
-- buf = g_realloc(buf, (j+1) * (MAXSNLEN+1));
--
-- strncpy(&buf[j * (MAXSNLEN+1)], cur, MAXSNLEN);
-- g_free(cur);
--
-- j++;
-- }
-- g_free(cur);
--
-- aim_tlvlist_free(tlvlist);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, searchaddr, j, buf);
--
-- /* XXX freesnac()? */
-- if (snac2)
-- g_free(snac2->data);
-- g_free(snac2);
--
-- g_free(buf);
--
-- return ret;
--}
--
--static int
--snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- if (snac->subtype == 0x0001)
-- return error(od, conn, mod, frame, snac, bs);
-- else if (snac->subtype == 0x0003)
-- return reply(od, conn, mod, frame, snac, bs);
--
-- return 0;
--}
--
--int
--search_modfirst(OscarData *od, aim_module_t *mod)
--{
-- mod->family = SNAC_FAMILY_USERLOOKUP;
-- mod->version = 0x0001;
-- mod->toolid = 0x0110;
-- mod->toolversion = 0x0629;
-- mod->flags = 0;
-- strncpy(mod->name, "userlookup", sizeof(mod->name));
-- mod->snachandler = snachandler;
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/flap_connection.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/flap_connection.c
---- pidgin-2.10.7/libpurple/protocols/oscar/flap_connection.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/flap_connection.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1127 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--#include "oscar.h"
--
--#include "eventloop.h"
--#include "proxy.h"
--
--#ifndef _WIN32
--#include <netdb.h>
--#include <sys/socket.h>
--#include <netinet/in.h>
--#endif
--
--#ifdef _WIN32
--#include "win32dep.h"
--#endif
--
--/**
-- * This sends a channel 1 SNAC containing the FLAP version.
-- * The FLAP version is sent by itself at the beginning of every
-- * connection to a FLAP server. It is always the very first
-- * packet sent by both the server and the client after the SYN,
-- * SYN/ACK, ACK handshake.
-- */
--void
--flap_connection_send_version(OscarData *od, FlapConnection *conn)
--{
-- FlapFrame *frame;
--
-- frame = flap_frame_new(od, 0x01, 4);
-- byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */
-- flap_connection_send(conn, frame);
--}
--
--/**
-- * This sends a channel 1 FLAP containing the FLAP version and
-- * the authentication cookie. This is sent when connecting to
-- * any FLAP server after the initial connection to the auth
-- * server. It is always the very first packet sent by both the
-- * server and the client after the SYN, SYN/ACK, ACK handshake.
-- */
--void
--flap_connection_send_version_with_cookie(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy)
--{
-- FlapFrame *frame;
-- GSList *tlvlist = NULL;
--
-- frame = flap_frame_new(od, 0x01, 4 + 2 + 2 + length);
-- byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */
-- aim_tlvlist_add_raw(&tlvlist, 0x0006, length, chipsahoy);
-- aim_tlvlist_write(&frame->data, &tlvlist);
-- aim_tlvlist_free(tlvlist);
--
-- flap_connection_send(conn, frame);
--}
--
--void
--flap_connection_send_version_with_cookie_and_clientinfo(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy, ClientInfo *ci, gboolean allow_multiple_logins)
--{
-- FlapFrame *frame;
-- GSList *tlvlist = NULL;
--
-- frame = flap_frame_new(od, 0x01, 1152 + length);
--
-- byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */
-- aim_tlvlist_add_raw(&tlvlist, 0x0006, length, chipsahoy);
--
-- if (ci->clientstring != NULL)
-- aim_tlvlist_add_str(&tlvlist, 0x0003, ci->clientstring);
-- else {
-- gchar *clientstring = oscar_get_clientstring();
-- aim_tlvlist_add_str(&tlvlist, 0x0003, clientstring);
-- g_free(clientstring);
-- }
-- aim_tlvlist_add_16(&tlvlist, 0x0017, (guint16)ci->major);
-- aim_tlvlist_add_16(&tlvlist, 0x0018, (guint16)ci->minor);
-- aim_tlvlist_add_16(&tlvlist, 0x0019, (guint16)ci->point);
-- aim_tlvlist_add_16(&tlvlist, 0x001a, (guint16)ci->build);
-- aim_tlvlist_add_8(&tlvlist, 0x004a, (allow_multiple_logins ? 0x01 : 0x03));
--
-- aim_tlvlist_write(&frame->data, &tlvlist);
--
-- aim_tlvlist_free(tlvlist);
--
-- flap_connection_send(conn, frame);
--}
--
--static struct rateclass *
--flap_connection_get_rateclass(FlapConnection *conn, guint16 family, guint16 subtype)
--{
-- gconstpointer key;
-- gpointer rateclass;
--
-- key = GUINT_TO_POINTER((family << 16) + subtype);
-- rateclass = g_hash_table_lookup(conn->rateclass_members, key);
-- if (rateclass != NULL)
-- return rateclass;
--
-- return conn->default_rateclass;
--}
--
--/*
-- * Attempt to calculate what our new current average would be if we
-- * were to send a SNAC in this rateclass at the given time.
-- */
--static guint32
--rateclass_get_new_current(FlapConnection *conn, struct rateclass *rateclass, struct timeval *now)
--{
-- unsigned long timediff; /* In milliseconds */
-- guint32 current;
--
-- /* This formula is documented at http://dev.aol.com/aim/oscar/#RATELIMIT */
-- timediff = (now->tv_sec - rateclass->last.tv_sec) * 1000 + (now->tv_usec - rateclass->last.tv_usec) / 1000;
-- current = ((rateclass->current * (rateclass->windowsize - 1)) + timediff) / rateclass->windowsize;
--
-- return MIN(current, rateclass->max);
--}
--
--/*
-- * Attempt to send the contents of a given queue
-- *
-- * @return TRUE if the queue was completely emptied or was initially
-- * empty; FALSE if rate limiting prevented it from being
-- * emptied.
-- */
--static gboolean flap_connection_send_snac_queue(FlapConnection *conn, struct timeval now, GQueue *queue)
--{
-- while (!g_queue_is_empty(queue))
-- {
-- QueuedSnac *queued_snac;
-- struct rateclass *rateclass;
--
-- queued_snac = g_queue_peek_head(queue);
--
-- rateclass = flap_connection_get_rateclass(conn, queued_snac->family, queued_snac->subtype);
-- if (rateclass != NULL)
-- {
-- guint32 new_current;
--
-- new_current = rateclass_get_new_current(conn, rateclass, &now);
--
-- if (rateclass->dropping_snacs || new_current <= rateclass->alert)
-- /* Not ready to send this SNAC yet--keep waiting. */
-- return FALSE;
--
-- rateclass->current = new_current;
-- rateclass->last.tv_sec = now.tv_sec;
-- rateclass->last.tv_usec = now.tv_usec;
-- }
--
-- flap_connection_send(conn, queued_snac->frame);
-- g_free(queued_snac);
-- g_queue_pop_head(queue);
-- }
--
-- /* We emptied the queue */
-- return TRUE;
--}
--
--static gboolean flap_connection_send_queued(gpointer data)
--{
-- FlapConnection *conn;
-- struct timeval now;
--
-- conn = data;
-- gettimeofday(&now, NULL);
--
-- purple_debug_info("oscar", "Attempting to send %u queued SNACs and %u queued low-priority SNACs for %p\n",
-- (conn->queued_snacs ? conn->queued_snacs->length : 0),
-- (conn->queued_lowpriority_snacs ? conn->queued_lowpriority_snacs->length : 0),
-- conn);
-- if (!conn->queued_snacs || flap_connection_send_snac_queue(conn, now, conn->queued_snacs)) {
-- if (!conn->queued_lowpriority_snacs || flap_connection_send_snac_queue(conn, now, conn->queued_lowpriority_snacs)) {
-- /* Both queues emptied. */
-- conn->queued_timeout = 0;
-- return FALSE;
-- }
-- }
--
-- /* We couldn't send all our SNACs. Keep trying */
-- return TRUE;
--}
--
--/**
-- * This sends a channel 2 FLAP containing a SNAC. The SNAC family and
-- * subtype are looked up in the rate info for this connection, and if
-- * sending this SNAC will induce rate limiting then we delay sending
-- * of the SNAC by putting it into an outgoing holding queue.
-- *
-- * @param data The optional bytestream that makes up the data portion
-- * of this SNAC. For empty SNACs this should be NULL.
-- * @param high_priority If TRUE, the SNAC will be queued normally if
-- * needed. If FALSE, it will be queued separately, to be sent
-- * only if all high priority SNACs have been sent.
-- */
--void
--flap_connection_send_snac_with_priority(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, aim_snacid_t snacid, ByteStream *data, gboolean high_priority)
--{
-- FlapFrame *frame;
-- guint32 length;
-- gboolean enqueue = FALSE;
-- struct rateclass *rateclass;
--
-- length = data != NULL ? data->offset : 0;
--
-- frame = flap_frame_new(od, 0x02, 10 + length);
-- aim_putsnac(&frame->data, family, subtype, snacid);
--
-- if (length > 0)
-- {
-- byte_stream_rewind(data);
-- byte_stream_putbs(&frame->data, data, length);
-- }
--
-- if (conn->queued_timeout != 0)
-- enqueue = TRUE;
-- else if ((rateclass = flap_connection_get_rateclass(conn, family, subtype)) != NULL)
-- {
-- struct timeval now;
-- guint32 new_current;
--
-- gettimeofday(&now, NULL);
-- new_current = rateclass_get_new_current(conn, rateclass, &now);
--
-- if (rateclass->dropping_snacs || new_current <= rateclass->alert)
-- {
-- purple_debug_info("oscar", "Current rate for conn %p would be %u, but we alert at %u; enqueueing\n", conn, new_current, rateclass->alert);
--
-- enqueue = TRUE;
-- }
-- else
-- {
-- rateclass->current = new_current;
-- rateclass->last.tv_sec = now.tv_sec;
-- rateclass->last.tv_usec = now.tv_usec;
-- }
-- }
--
-- if (enqueue)
-- {
-- /* We've been sending too fast, so delay this message */
-- QueuedSnac *queued_snac;
--
-- queued_snac = g_new(QueuedSnac, 1);
-- queued_snac->family = family;
-- queued_snac->subtype = subtype;
-- queued_snac->frame = frame;
--
-- if (high_priority) {
-- if (!conn->queued_snacs)
-- conn->queued_snacs = g_queue_new();
-- g_queue_push_tail(conn->queued_snacs, queued_snac);
-- } else {
-- if (!conn->queued_lowpriority_snacs)
-- conn->queued_lowpriority_snacs = g_queue_new();
-- g_queue_push_tail(conn->queued_lowpriority_snacs, queued_snac);
-- }
--
-- if (conn->queued_timeout == 0)
-- conn->queued_timeout = purple_timeout_add(500, flap_connection_send_queued, conn);
--
-- return;
-- }
--
-- flap_connection_send(conn, frame);
--}
--
--void
--flap_connection_send_snac(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, aim_snacid_t snacid, ByteStream *data)
--{
-- flap_connection_send_snac_with_priority(od, conn, family, subtype, snacid, data, TRUE);
--}
--
--/**
-- * This sends an empty channel 4 FLAP. This is sent to signify
-- * that we're logging off. This shouldn't really be necessary--
-- * usually the AIM server will detect that the TCP connection has
-- * been destroyed--but it's good practice.
-- */
--static void
--flap_connection_send_close(OscarData *od, FlapConnection *conn)
--{
-- FlapFrame *frame;
--
-- frame = flap_frame_new(od, 0x04, 0);
-- flap_connection_send(conn, frame);
--}
--
--/**
-- * This sends an empty channel 5 FLAP. This is used as a keepalive
-- * packet in FLAP connections. WinAIM 4.x and higher send these
-- * _every minute_ to keep the connection alive.
-- */
--void
--flap_connection_send_keepalive(OscarData *od, FlapConnection *conn)
--{
-- FlapFrame *frame;
--
-- frame = flap_frame_new(od, 0x05, 0);
-- flap_connection_send(conn, frame);
--
-- /* clean out SNACs over 60sec old */
-- aim_cleansnacs(od, 60);
--}
--
--/**
-- * Allocate a new empty connection structure.
-- *
-- * @param od The oscar session associated with this connection.
-- * @param type Type of connection to create
-- *
-- * @return Returns the new connection structure.
-- */
--FlapConnection *
--flap_connection_new(OscarData *od, int type)
--{
-- FlapConnection *conn;
--
-- conn = g_new0(FlapConnection, 1);
-- conn->od = od;
-- conn->buffer_outgoing = purple_circ_buffer_new(0);
-- conn->fd = -1;
-- conn->subtype = -1;
-- conn->type = type;
-- conn->rateclass_members = g_hash_table_new(g_direct_hash, g_direct_equal);
--
-- od->oscar_connections = g_slist_prepend(od->oscar_connections, conn);
--
-- return conn;
--}
--
--/**
-- * Close (but not free) a connection.
-- *
-- * This cancels any currently pending connection attempt,
-- * closes any open fd and frees the auth cookie.
-- *
-- * @param conn The connection to close.
-- */
--void
--flap_connection_close(OscarData *od, FlapConnection *conn)
--{
-- if (conn->connect_data != NULL)
-- {
-- purple_proxy_connect_cancel(conn->connect_data);
-- conn->connect_data = NULL;
-- }
--
-- if (conn->gsc != NULL && conn->gsc->connect_data != NULL)
-- {
-- purple_ssl_close(conn->gsc);
-- conn->gsc = NULL;
-- }
--
-- if (conn->new_conn_data != NULL)
-- {
-- if (conn->type == SNAC_FAMILY_CHAT)
-- {
-- oscar_chat_destroy(conn->new_conn_data);
-- conn->new_conn_data = NULL;
-- }
-- }
--
-- if ((conn->fd >= 0 || conn->gsc != NULL)
-- && conn->type == SNAC_FAMILY_LOCATE)
-- flap_connection_send_close(od, conn);
--
-- if (conn->watcher_incoming != 0)
-- {
-- purple_input_remove(conn->watcher_incoming);
-- conn->watcher_incoming = 0;
-- }
--
-- if (conn->watcher_outgoing != 0)
-- {
-- purple_input_remove(conn->watcher_outgoing);
-- conn->watcher_outgoing = 0;
-- }
--
-- if (conn->fd >= 0)
-- {
-- close(conn->fd);
-- conn->fd = -1;
-- }
--
-- if (conn->gsc != NULL)
-- {
-- purple_ssl_close(conn->gsc);
-- conn->gsc = NULL;
-- }
--
-- g_free(conn->buffer_incoming.data.data);
-- conn->buffer_incoming.data.data = NULL;
--
-- purple_circ_buffer_destroy(conn->buffer_outgoing);
-- conn->buffer_outgoing = NULL;
--}
--
--/**
-- * Free a FlapFrame
-- *
-- * @param frame The frame to free.
-- */
--static void
--flap_frame_destroy(FlapFrame *frame)
--{
-- g_free(frame->data.data);
-- g_free(frame);
--}
--
--static gboolean
--flap_connection_destroy_cb(gpointer data)
--{
-- FlapConnection *conn;
-- OscarData *od;
-- PurpleAccount *account;
-- aim_rxcallback_t userfunc;
--
-- conn = data;
-- /* Explicitly added for debugging #5927. Don't re-order this, only
-- * consider removing it.
-- */
-- purple_debug_info("oscar", "Destroying FLAP connection %p\n", conn);
--
-- od = conn->od;
-- account = purple_connection_get_account(od->gc);
--
-- purple_debug_info("oscar", "Destroying oscar connection (%p) of "
-- "type 0x%04hx. Disconnect reason is %d\n", conn,
-- conn->type, conn->disconnect_reason);
--
-- od->oscar_connections = g_slist_remove(od->oscar_connections, conn);
--
-- if ((userfunc = aim_callhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR)))
-- userfunc(od, conn, NULL, conn->disconnect_code, conn->error_message);
--
-- /*
-- * TODO: If we don't have a SNAC_FAMILY_LOCATE connection then
-- * we should try to request one instead of disconnecting.
-- */
-- if (!account->disconnecting && ((od->oscar_connections == NULL)
-- || (!flap_connection_getbytype(od, SNAC_FAMILY_LOCATE))))
-- {
-- /* No more FLAP connections! Sign off this PurpleConnection! */
-- gchar *tmp;
-- PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
--
-- if (conn->disconnect_code == 0x0001) {
-- reason = PURPLE_CONNECTION_ERROR_NAME_IN_USE;
-- tmp = g_strdup(_("You have signed on from another location"));
-- if (!purple_account_get_remember_password(account))
-- purple_account_set_password(account, NULL);
-- } else if (conn->disconnect_reason == OSCAR_DISCONNECT_REMOTE_CLOSED)
-- tmp = g_strdup(_("Server closed the connection"));
-- else if (conn->disconnect_reason == OSCAR_DISCONNECT_LOST_CONNECTION)
-- tmp = g_strdup_printf(_("Lost connection with server: %s"),
-- conn->error_message);
-- else if (conn->disconnect_reason == OSCAR_DISCONNECT_INVALID_DATA)
-- tmp = g_strdup(_("Received invalid data on connection with server"));
-- else if (conn->disconnect_reason == OSCAR_DISCONNECT_COULD_NOT_CONNECT)
-- tmp = g_strdup_printf(_("Unable to connect: %s"),
-- conn->error_message);
-- else
-- /*
-- * We shouldn't print a message for some disconnect_reasons.
-- * Like OSCAR_DISCONNECT_LOCAL_CLOSED.
-- */
-- tmp = NULL;
--
-- if (tmp != NULL)
-- {
-- purple_connection_error_reason(od->gc, reason, tmp);
-- g_free(tmp);
-- }
-- }
--
-- flap_connection_close(od, conn);
--
-- g_free(conn->error_message);
-- g_free(conn->cookie);
--
-- /*
-- * Free conn->internal, if necessary
-- */
-- if (conn->type == SNAC_FAMILY_CHAT)
-- flap_connection_destroy_chat(od, conn);
--
-- g_slist_free(conn->groups);
-- while (conn->rateclasses != NULL)
-- {
-- g_free(conn->rateclasses->data);
-- conn->rateclasses = g_slist_delete_link(conn->rateclasses, conn->rateclasses);
-- }
--
-- g_hash_table_destroy(conn->rateclass_members);
--
-- if (conn->queued_snacs) {
-- while (!g_queue_is_empty(conn->queued_snacs))
-- {
-- QueuedSnac *queued_snac;
-- queued_snac = g_queue_pop_head(conn->queued_snacs);
-- flap_frame_destroy(queued_snac->frame);
-- g_free(queued_snac);
-- }
-- g_queue_free(conn->queued_snacs);
-- }
--
-- if (conn->queued_lowpriority_snacs) {
-- while (!g_queue_is_empty(conn->queued_lowpriority_snacs))
-- {
-- QueuedSnac *queued_snac;
-- queued_snac = g_queue_pop_head(conn->queued_lowpriority_snacs);
-- flap_frame_destroy(queued_snac->frame);
-- g_free(queued_snac);
-- }
-- g_queue_free(conn->queued_lowpriority_snacs);
-- }
--
-- if (conn->queued_timeout > 0)
-- purple_timeout_remove(conn->queued_timeout);
--
-- g_free(conn);
--
-- return FALSE;
--}
--
--/**
-- * See the comments for the parameters of
-- * flap_connection_schedule_destroy().
-- */
--void
--flap_connection_destroy(FlapConnection *conn, OscarDisconnectReason reason, const gchar *error_message)
--{
-- if (conn->destroy_timeout != 0)
-- purple_timeout_remove(conn->destroy_timeout);
-- conn->disconnect_reason = reason;
-- g_free(conn->error_message);
-- conn->error_message = g_strdup(error_message);
-- flap_connection_destroy_cb(conn);
--}
--
--/**
-- * Schedule Purple to destroy the given FlapConnection as soon as we
-- * return control back to the program's main loop. We must do this
-- * if we want to destroy the connection but we are still using it
-- * for some reason.
-- *
-- * @param reason The reason for the disconnection.
-- * @param error_message A brief error message that gives more detail
-- * regarding the reason for the disconnecting. This should
-- * be NULL for everything except OSCAR_DISCONNECT_LOST_CONNECTION,
-- * in which case it should contain the value of g_strerror(errno),
-- * and OSCAR_DISCONNECT_COULD_NOT_CONNECT, in which case it
-- * should contain the error_message passed back from the call
-- * to purple_proxy_connect().
-- */
--void
--flap_connection_schedule_destroy(FlapConnection *conn, OscarDisconnectReason reason, const gchar *error_message)
--{
-- if (conn->destroy_timeout != 0)
-- /* Already taken care of */
-- return;
--
-- purple_debug_info("oscar", "Scheduling destruction of FLAP "
-- "connection %p of type 0x%04hx\n", conn, conn->type);
-- conn->disconnect_reason = reason;
-- g_free(conn->error_message);
-- conn->error_message = g_strdup(error_message);
-- conn->destroy_timeout = purple_timeout_add(0, flap_connection_destroy_cb, conn);
--}
--
--/**
-- * In OSCAR, every connection has a set of SNAC groups associated
-- * with it. These are the groups that you can send over this connection
-- * without being guaranteed a "Not supported" SNAC error.
-- *
-- * The grand theory of things says that these associations transcend
-- * what libfaim calls "connection types" (conn->type). You can probably
-- * see the elegance here, but since I want to revel in it for a bit, you
-- * get to hear it all spelled out.
-- *
-- * So let us say that you have your core BOS connection running. One
-- * of your modules has just given you a SNAC of the group 0x0004 to send
-- * you. Maybe an IM destined for some twit in Greenland. So you start
-- * at the top of your connection list, looking for a connection that
-- * claims to support group 0x0004. You find one. Why, that neat BOS
-- * connection of yours can do that. So you send it on its way.
-- *
-- * Now, say, that fellow from Greenland has friends and they all want to
-- * meet up with you in a lame chat room. This has landed you a SNAC
-- * in the family 0x000e and you have to admit you're a bit lost. You've
-- * searched your connection list for someone who wants to make your life
-- * easy and deliver this SNAC for you, but there isn't one there.
-- *
-- * Here comes the good bit. Without even letting anyone know, particularly
-- * the module that decided to send this SNAC, and definitely not that twit
-- * in Greenland, you send out a service request. In this request, you have
-- * marked the need for a connection supporting group 0x000e. A few seconds
-- * later, you receive a service redirect with an IP address and a cookie in
-- * it. Great, you say. Now I have something to do. Off you go, making
-- * that connection. One of the first things you get from this new server
-- * is a message saying that indeed it does support the group you were looking
-- * for. So you continue and send rate confirmation and all that.
-- *
-- * Then you remember you had that SNAC to send, and now you have a means to
-- * do it, and you do, and everyone is happy. Except the Greenlander, who is
-- * still stuck in the bitter cold.
-- *
-- * Oh, and this is useful for building the Migration SNACs, too. In the
-- * future, this may help convince me to implement rate limit mitigation
-- * for real. We'll see.
-- *
-- * Just to make me look better, I'll say that I've known about this great
-- * scheme for quite some time now. But I still haven't convinced myself
-- * to make libfaim work that way. It would take a fair amount of effort,
-- * and probably some client API changes as well. (Whenever I don't want
-- * to do something, I just say it would change the client API. Then I
-- * instantly have a couple of supporters of not doing it.)
-- *
-- * Generally, addgroup is only called by the internal handling of the
-- * server ready SNAC. So if you want to do something before that, you'll
-- * have to be more creative. That is done rather early, though, so I don't
-- * think you have to worry about it. Unless you're me. I care deeply
-- * about such inane things.
-- *
-- */
--
--/**
-- * Find a FlapConnection that supports the given oscar
-- * family.
-- */
--FlapConnection *
--flap_connection_findbygroup(OscarData *od, guint16 group)
--{
-- GSList *cur;
--
-- for (cur = od->oscar_connections; cur != NULL; cur = cur->next)
-- {
-- FlapConnection *conn;
-- GSList *l;
--
-- conn = cur->data;
--
-- for (l = conn->groups; l != NULL; l = l->next)
-- {
-- if (GPOINTER_TO_UINT(l->data) == group)
-- return conn;
-- }
-- }
--
-- return NULL;
--}
--
--/**
-- * Locates a connection of the specified type in the
-- * specified session.
-- *
-- * TODO: Use flap_connection_findbygroup everywhere and get rid of this.
-- *
-- * @param od The session to search.
-- * @param type The type of connection to look for.
-- *
-- * @return Returns the first connection found of the given target type,
-- * or NULL if none could be found.
-- */
--FlapConnection *
--flap_connection_getbytype(OscarData *od, int type)
--{
-- GSList *cur;
--
-- for (cur = od->oscar_connections; cur != NULL; cur = cur->next)
-- {
-- FlapConnection *conn;
-- conn = cur->data;
-- if ((conn->type == type) && (conn->connected))
-- return conn;
-- }
--
-- return NULL;
--}
--
--FlapConnection *
--flap_connection_getbytype_all(OscarData *od, int type)
--{
-- GSList *cur;
--
-- for (cur = od->oscar_connections; cur; cur = cur->next)
-- {
-- FlapConnection *conn;
-- conn = cur->data;
-- if (conn->type == type)
-- return conn;
-- }
--
-- return NULL;
--}
--
--/**
-- * Allocate a new FLAP frame.
-- *
-- * @param channel The FLAP channel. This is almost always 2.
-- */
--FlapFrame *
--flap_frame_new(OscarData *od, guint16 channel, int datalen)
--{
-- FlapFrame *frame;
--
-- frame = g_new0(FlapFrame, 1);
-- frame->channel = channel;
--
-- if (datalen > 0)
-- byte_stream_new(&frame->data, datalen);
--
-- return frame;
--}
--
--static void
--parse_snac(OscarData *od, FlapConnection *conn, FlapFrame *frame)
--{
-- aim_module_t *cur;
-- aim_modsnac_t snac;
--
-- if (byte_stream_bytes_left(&frame->data) < 10)
-- return;
--
-- snac.family = byte_stream_get16(&frame->data);
-- snac.subtype = byte_stream_get16(&frame->data);
-- snac.flags = byte_stream_get16(&frame->data);
-- snac.id = byte_stream_get32(&frame->data);
--
-- /* SNAC flags are apparently uniform across all SNACs, so we handle them here */
-- if (snac.flags & 0x0001) {
-- /*
-- * This means the SNAC will be followed by another SNAC with
-- * related information. We don't need to do anything about
-- * this here.
-- */
-- }
-- if (snac.flags & 0x8000) {
-- /*
-- * This packet contains the version of the family that this SNAC is
-- * in. You get this when your SSI module is version 2 or higher.
-- * For now we have no need for this, but you could always save
-- * it as a part of aim_modnsac_t, or something. The format is...
-- * 2 byte length of total mini-header (which is 6 bytes), then TLV
-- * of type 0x0001, length 0x0002, value is the 2 byte version
-- * number
-- */
-- byte_stream_advance(&frame->data, byte_stream_get16(&frame->data));
-- }
--
-- for (cur = (aim_module_t *)od->modlistv; cur; cur = cur->next) {
--
-- if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) &&
-- (cur->family != snac.family))
-- continue;
--
-- if (cur->snachandler(od, conn, cur, frame, &snac, &frame->data))
-- return;
-- }
--}
--
--static void
--parse_fakesnac(OscarData *od, FlapConnection *conn, FlapFrame *frame, guint16 family, guint16 subtype)
--{
-- aim_module_t *cur;
-- aim_modsnac_t snac;
--
-- snac.family = family;
-- snac.subtype = subtype;
-- snac.flags = snac.id = 0;
--
-- for (cur = (aim_module_t *)od->modlistv; cur; cur = cur->next) {
--
-- if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) &&
-- (cur->family != snac.family))
-- continue;
--
-- if (cur->snachandler(od, conn, cur, frame, &snac, &frame->data))
-- return;
-- }
--}
--
--static void
--parse_flap_ch4(OscarData *od, FlapConnection *conn, FlapFrame *frame)
--{
-- GSList *tlvlist;
-- char *msg = NULL;
--
-- if (byte_stream_bytes_left(&frame->data) == 0) {
-- /* XXX should do something with this */
-- return;
-- }
--
-- /* An ICQ account is logging in */
-- if (conn->type == SNAC_FAMILY_AUTH)
-- {
-- parse_fakesnac(od, conn, frame, 0x0017, 0x0003);
-- return;
-- }
--
-- tlvlist = aim_tlvlist_read(&frame->data);
--
-- if (aim_tlv_gettlv(tlvlist, 0x0009, 1))
-- conn->disconnect_code = aim_tlv_get16(tlvlist, 0x0009, 1);
--
-- if (aim_tlv_gettlv(tlvlist, 0x000b, 1))
-- msg = aim_tlv_getstr(tlvlist, 0x000b, 1);
--
-- /*
-- * The server ended this FLAP connnection, so let's be nice and
-- * close the physical TCP connection
-- */
-- flap_connection_schedule_destroy(conn,
-- OSCAR_DISCONNECT_REMOTE_CLOSED, msg);
--
-- aim_tlvlist_free(tlvlist);
--
-- g_free(msg);
--}
--
--/**
-- * Takes a new incoming FLAP frame and sends it to the appropriate
-- * handler function to be parsed.
-- */
--static void
--parse_flap(OscarData *od, FlapConnection *conn, FlapFrame *frame)
--{
-- if (frame->channel == 0x01) {
-- guint32 flap_version = byte_stream_get32(&frame->data);
-- if (flap_version != 0x00000001)
-- {
-- /* Error! */
-- purple_debug_warning("oscar", "Expecting FLAP version "
-- "0x00000001 but received FLAP version %08x. Closing connection.\n",
-- flap_version);
-- flap_connection_schedule_destroy(conn,
-- OSCAR_DISCONNECT_INVALID_DATA, NULL);
-- }
-- else
-- conn->connected = TRUE;
--
-- } else if (frame->channel == 0x02) {
-- parse_snac(od, conn, frame);
--
-- } else if (frame->channel == 0x04) {
-- parse_flap_ch4(od, conn, frame);
--
-- } else if (frame->channel == 0x05) {
-- /* TODO: Reset our keepalive watchdog? */
--
-- }
--}
--
--/**
-- * Read in all available data on the socket for a given connection.
-- * All complete FLAPs handled immedate after they're received.
-- * Incomplete FLAP data is stored locally and appended to the next
-- * time this callback is triggered.
-- *
-- * This is called by flap_connection_recv_cb and
-- * flap_connection_recv_cb_ssl for unencrypted/encrypted connections.
-- */
--static void
--flap_connection_recv(FlapConnection *conn)
--{
-- gpointer buf;
-- gsize buflen;
-- gssize read;
--
-- /* Read data until we run out of data and break out of the loop */
-- while (TRUE)
-- {
-- /* Start reading a new FLAP */
-- if (conn->buffer_incoming.data.data == NULL)
-- {
-- buf = conn->header + conn->header_received;
-- buflen = 6 - conn->header_received;
--
-- /* Read the first 6 bytes (the FLAP header) */
-- if (conn->gsc)
-- read = purple_ssl_read(conn->gsc, buf, buflen);
-- else
-- read = recv(conn->fd, buf, buflen, 0);
--
-- /* Check if the FLAP server closed the connection */
-- if (read == 0)
-- {
-- flap_connection_schedule_destroy(conn,
-- OSCAR_DISCONNECT_REMOTE_CLOSED, NULL);
-- break;
-- }
--
-- /* If there was an error then close the connection */
-- if (read < 0)
-- {
-- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-- /* No worries */
-- break;
--
-- /* Error! */
-- flap_connection_schedule_destroy(conn,
-- OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno));
-- break;
-- }
-- conn->od->gc->last_received = time(NULL);
--
-- /* If we don't even have a complete FLAP header then do nothing */
-- conn->header_received += read;
-- if (conn->header_received < 6)
-- break;
--
-- /* All FLAP frames must start with the byte 0x2a */
-- if (aimutil_get8(&conn->header[0]) != 0x2a)
-- {
-- flap_connection_schedule_destroy(conn,
-- OSCAR_DISCONNECT_INVALID_DATA, NULL);
-- break;
-- }
--
-- /* Initialize a new temporary FlapFrame for incoming data */
-- conn->buffer_incoming.channel = aimutil_get8(&conn->header[1]);
-- conn->buffer_incoming.seqnum = aimutil_get16(&conn->header[2]);
-- conn->buffer_incoming.data.len = aimutil_get16(&conn->header[4]);
-- conn->buffer_incoming.data.data = g_new(guint8, conn->buffer_incoming.data.len);
-- conn->buffer_incoming.data.offset = 0;
-- }
--
-- buflen = conn->buffer_incoming.data.len - conn->buffer_incoming.data.offset;
-- if (buflen)
-- {
-- buf = &conn->buffer_incoming.data.data[conn->buffer_incoming.data.offset];
-- /* Read data into the temporary FlapFrame until it is complete */
-- if (conn->gsc)
-- read = purple_ssl_read(conn->gsc, buf, buflen);
-- else
-- read = recv(conn->fd, buf, buflen, 0);
--
-- /* Check if the FLAP server closed the connection */
-- if (read == 0)
-- {
-- flap_connection_schedule_destroy(conn,
-- OSCAR_DISCONNECT_REMOTE_CLOSED, NULL);
-- break;
-- }
--
-- if (read < 0)
-- {
-- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-- /* No worries */
-- break;
--
-- /* Error! */
-- flap_connection_schedule_destroy(conn,
-- OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno));
-- break;
-- }
--
-- conn->buffer_incoming.data.offset += read;
-- if (conn->buffer_incoming.data.offset < conn->buffer_incoming.data.len)
-- /* Waiting for more data to arrive */
-- break;
-- }
--
-- /* We have a complete FLAP! Handle it and continue reading */
-- byte_stream_rewind(&conn->buffer_incoming.data);
-- parse_flap(conn->od, conn, &conn->buffer_incoming);
-- conn->lastactivity = time(NULL);
--
-- g_free(conn->buffer_incoming.data.data);
-- conn->buffer_incoming.data.data = NULL;
--
-- conn->header_received = 0;
-- }
--}
--
--void
--flap_connection_recv_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- FlapConnection *conn = data;
--
-- flap_connection_recv(conn);
--}
--
--void
--flap_connection_recv_cb_ssl(gpointer data, PurpleSslConnection *gsc, PurpleInputCondition cond)
--{
-- FlapConnection *conn = data;
--
-- flap_connection_recv(conn);
--}
--
--/**
-- * @param source When this function is called as a callback source is
-- * set to the fd that triggered the callback. But this function
-- * is also called directly from flap_connection_send_byte_stream(),
-- * in which case source will be -1. So don't use source--use
-- * conn->gsc or conn->fd instead.
-- */
--static void
--send_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- FlapConnection *conn;
-- int writelen, ret;
--
-- conn = data;
-- writelen = purple_circ_buffer_get_max_read(conn->buffer_outgoing);
--
-- if (writelen == 0)
-- {
-- purple_input_remove(conn->watcher_outgoing);
-- conn->watcher_outgoing = 0;
-- return;
-- }
--
-- if (conn->gsc)
-- ret = purple_ssl_write(conn->gsc, conn->buffer_outgoing->outptr,
-- writelen);
-- else
-- ret = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0);
-- if (ret <= 0)
-- {
-- if (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
-- /* No worries */
-- return;
--
-- /* Error! */
-- purple_input_remove(conn->watcher_outgoing);
-- conn->watcher_outgoing = 0;
-- if (conn->gsc) {
-- purple_ssl_close(conn->gsc);
-- conn->gsc = NULL;
-- } else {
-- close(conn->fd);
-- conn->fd = -1;
-- }
-- flap_connection_schedule_destroy(conn,
-- OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno));
-- return;
-- }
--
-- purple_circ_buffer_mark_read(conn->buffer_outgoing, ret);
--}
--
--static void
--flap_connection_send_byte_stream(ByteStream *bs, FlapConnection *conn, size_t count)
--{
-- if (conn == NULL)
-- return;
--
-- /* Make sure we don't send past the end of the bs */
-- if (count > byte_stream_bytes_left(bs))
-- count = byte_stream_bytes_left(bs); /* truncate to remaining space */
--
-- if (count == 0)
-- return;
--
-- /* Add everything to our outgoing buffer */
-- purple_circ_buffer_append(conn->buffer_outgoing, bs->data, count);
--
-- /* If we haven't already started writing stuff, then start the cycle */
-- if (conn->watcher_outgoing == 0)
-- {
-- if (conn->gsc) {
-- conn->watcher_outgoing = purple_input_add(conn->gsc->fd,
-- PURPLE_INPUT_WRITE, send_cb, conn);
-- send_cb(conn, -1, 0);
-- } else if (conn->fd >= 0) {
-- conn->watcher_outgoing = purple_input_add(conn->fd,
-- PURPLE_INPUT_WRITE, send_cb, conn);
-- send_cb(conn, -1, 0);
-- }
-- }
--}
--
--static void
--sendframe_flap(FlapConnection *conn, FlapFrame *frame)
--{
-- ByteStream bs;
-- int payloadlen, bslen;
--
-- payloadlen = byte_stream_curpos(&frame->data);
--
-- byte_stream_new(&bs, 6 + payloadlen);
--
-- /* FLAP header */
-- byte_stream_put8(&bs, 0x2a);
-- byte_stream_put8(&bs, frame->channel);
-- byte_stream_put16(&bs, frame->seqnum);
-- byte_stream_put16(&bs, payloadlen);
--
-- /* Payload */
-- byte_stream_rewind(&frame->data);
-- byte_stream_putbs(&bs, &frame->data, payloadlen);
--
-- bslen = byte_stream_curpos(&bs);
-- byte_stream_rewind(&bs);
-- flap_connection_send_byte_stream(&bs, conn, bslen);
--
-- byte_stream_destroy(&bs);
--}
--
--void
--flap_connection_send(FlapConnection *conn, FlapFrame *frame)
--{
-- frame->seqnum = ++(conn->seqnum_out);
-- sendframe_flap(conn, frame);
-- flap_frame_destroy(frame);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/libaim.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/libaim.c
---- pidgin-2.10.7/libpurple/protocols/oscar/libaim.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/libaim.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,151 +0,0 @@
--/* purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--/* libaim is the AIM protocol plugin. It is linked against liboscar,
-- * which contains all the shared implementation code with libicq
-- */
--
--#include "oscarcommon.h"
--#include "oscar.h"
--
--static PurplePluginProtocolInfo prpl_info =
--{
-- OPT_PROTO_MAIL_CHECK | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE,
-- NULL, /* user_splits */
-- NULL, /* protocol_options */
-- {"gif,jpeg,bmp,ico", 0, 0, 64, 64, 7168, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
-- oscar_list_icon_aim, /* list_icon */
-- oscar_list_emblem, /* list_emblems */
-- oscar_status_text, /* status_text */
-- oscar_tooltip_text, /* tooltip_text */
-- oscar_status_types, /* status_types */
-- oscar_blist_node_menu, /* blist_node_menu */
-- oscar_chat_info, /* chat_info */
-- oscar_chat_info_defaults, /* chat_info_defaults */
-- oscar_login, /* login */
-- oscar_close, /* close */
-- oscar_send_im, /* send_im */
-- oscar_set_info, /* set_info */
-- oscar_send_typing, /* send_typing */
-- oscar_get_info, /* get_info */
-- oscar_set_status, /* set_status */
-- oscar_set_idle, /* set_idle */
-- oscar_change_passwd, /* change_passwd */
-- NULL, /* add_buddy */
-- NULL, /* add_buddies */
-- oscar_remove_buddy, /* remove_buddy */
-- NULL, /* remove_buddies */
-- oscar_add_permit, /* add_permit */
-- oscar_add_deny, /* add_deny */
-- oscar_rem_permit, /* rem_permit */
-- oscar_rem_deny, /* rem_deny */
-- oscar_set_aim_permdeny, /* set_permit_deny */
-- oscar_join_chat, /* join_chat */
-- NULL, /* reject_chat */
-- oscar_get_chat_name, /* get_chat_name */
-- oscar_chat_invite, /* chat_invite */
-- oscar_chat_leave, /* chat_leave */
-- NULL, /* chat_whisper */
-- oscar_send_chat, /* chat_send */
-- oscar_keepalive, /* keepalive */
-- NULL, /* register_user */
-- NULL, /* get_cb_info */
-- NULL, /* get_cb_away */
-- oscar_alias_buddy, /* alias_buddy */
-- oscar_move_buddy, /* group_buddy */
-- oscar_rename_group, /* rename_group */
-- NULL, /* buddy_free */
-- oscar_convo_closed, /* convo_closed */
-- oscar_normalize, /* normalize */
-- oscar_set_icon, /* set_buddy_icon */
-- oscar_remove_group, /* remove_group */
-- NULL, /* get_cb_real_name */
-- NULL, /* set_chat_topic */
-- NULL, /* find_blist_chat */
-- NULL, /* roomlist_get_list */
-- NULL, /* roomlist_cancel */
-- NULL, /* roomlist_expand_category */
-- oscar_can_receive_file, /* can_receive_file */
-- oscar_send_file, /* send_file */
-- oscar_new_xfer, /* new_xfer */
-- oscar_offline_message, /* offline_message */
-- NULL, /* 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 */
-- oscar_add_buddy, /* 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-aim", /**< id */
-- "AIM", /**< name */
-- DISPLAY_VERSION, /**< version */
-- /** summary */
-- N_("AIM Protocol Plugin"),
-- /** description */
-- N_("AIM Protocol Plugin"),
-- NULL, /**< author */
-- PURPLE_WEBSITE, /**< homepage */
--
-- NULL, /**< load */
-- NULL, /**< unload */
-- NULL, /**< destroy */
--
-- NULL, /**< ui_info */
-- &prpl_info, /**< extra_info */
-- NULL,
-- oscar_actions,
--
-- /* padding */
-- NULL,
-- NULL,
-- NULL,
-- NULL
--};
--
--static void
--init_plugin(PurplePlugin *plugin)
--{
-- oscar_init(plugin, FALSE);
--}
--
--PURPLE_INIT_PLUGIN(aim, init_plugin, info);
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/libicq.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/libicq.c
---- pidgin-2.10.7/libpurple/protocols/oscar/libicq.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/libicq.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,166 +0,0 @@
--/* purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--/* libicq is the ICQ protocol plugin. It is linked against liboscar,
-- * which contains all the shared implementation code with libaim
-- */
--
--
--#include "oscarcommon.h"
--
--static GHashTable *
--icq_get_account_text_table(PurpleAccount *account)
--{
-- GHashTable *table;
-- table = g_hash_table_new(g_str_hash, g_str_equal);
-- g_hash_table_insert(table, "login_label", (gpointer)_("ICQ UIN..."));
-- return table;
--}
--
--static PurplePluginProtocolInfo prpl_info =
--{
-- OPT_PROTO_MAIL_CHECK | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE,
-- NULL, /* user_splits */
-- NULL, /* protocol_options */
-- {"gif,jpeg,bmp,ico", 0, 0, 64, 64, 7168, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
-- oscar_list_icon_icq, /* list_icon */
-- oscar_list_emblem, /* list_emblems */
-- oscar_status_text, /* status_text */
-- oscar_tooltip_text, /* tooltip_text */
-- oscar_status_types, /* status_types */
-- oscar_blist_node_menu, /* blist_node_menu */
-- oscar_chat_info, /* chat_info */
-- oscar_chat_info_defaults, /* chat_info_defaults */
-- oscar_login, /* login */
-- oscar_close, /* close */
-- oscar_send_im, /* send_im */
-- oscar_set_info, /* set_info */
-- oscar_send_typing, /* send_typing */
-- oscar_get_info, /* get_info */
-- oscar_set_status, /* set_status */
-- oscar_set_idle, /* set_idle */
-- oscar_change_passwd, /* change_passwd */
-- NULL, /* add_buddy */
-- NULL, /* add_buddies */
-- oscar_remove_buddy, /* remove_buddy */
-- NULL, /* remove_buddies */
-- NULL, /* add_permit */
-- oscar_add_deny, /* add_deny */
-- NULL, /* rem_permit */
-- oscar_rem_deny, /* rem_deny */
-- NULL, /* set_permit_deny */
-- oscar_join_chat, /* join_chat */
-- NULL, /* reject_chat */
-- oscar_get_chat_name, /* get_chat_name */
-- oscar_chat_invite, /* chat_invite */
-- oscar_chat_leave, /* chat_leave */
-- NULL, /* chat_whisper */
-- oscar_send_chat, /* chat_send */
-- oscar_keepalive, /* keepalive */
-- NULL, /* register_user */
-- NULL, /* get_cb_info */
-- NULL, /* get_cb_away */
-- oscar_alias_buddy, /* alias_buddy */
-- oscar_move_buddy, /* group_buddy */
-- oscar_rename_group, /* rename_group */
-- NULL, /* buddy_free */
-- oscar_convo_closed, /* convo_closed */
-- oscar_normalize, /* normalize */
-- oscar_set_icon, /* set_buddy_icon */
-- oscar_remove_group, /* remove_group */
-- NULL, /* get_cb_real_name */
-- NULL, /* set_chat_topic */
-- NULL, /* find_blist_chat */
-- NULL, /* roomlist_get_list */
-- NULL, /* roomlist_cancel */
-- NULL, /* roomlist_expand_category */
-- oscar_can_receive_file, /* can_receive_file */
-- oscar_send_file, /* send_file */
-- oscar_new_xfer, /* new_xfer */
-- oscar_offline_message, /* offline_message */
-- NULL, /* whiteboard_prpl_ops */
-- NULL, /* send_raw */
-- NULL, /* roomlist_room_serialize */
-- NULL, /* unregister_user */
-- NULL, /* send_attention */
-- NULL, /* get_attention_types */
--
-- sizeof(PurplePluginProtocolInfo), /* struct_size */
-- icq_get_account_text_table, /* get_account_text_table */
-- NULL, /* initiate_media */
-- NULL, /* can_do_media */
-- oscar_get_purple_moods, /* get_moods */
-- NULL, /* set_public_alias */
-- NULL, /* get_public_alias */
-- oscar_add_buddy, /* 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-icq", /**< id */
-- "ICQ", /**< name */
-- DISPLAY_VERSION, /**< version */
-- /** summary */
-- N_("ICQ Protocol Plugin"),
-- /** description */
-- N_("ICQ Protocol Plugin"),
-- NULL, /**< author */
-- PURPLE_WEBSITE, /**< homepage */
--
-- NULL, /**< load */
-- NULL, /**< unload */
-- NULL, /**< destroy */
--
-- NULL, /**< ui_info */
-- &prpl_info, /**< extra_info */
-- NULL,
-- oscar_actions,
--
-- /* padding */
-- NULL,
-- NULL,
-- NULL,
-- NULL
--};
--
--static void
--init_plugin(PurplePlugin *plugin)
--{
-- PurpleAccountOption *option;
--
-- oscar_init(plugin, TRUE);
--
-- option = purple_account_option_string_new(_("Encoding"), "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--}
--
--PURPLE_INIT_PLUGIN(icq, init_plugin, info);
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/oscar/Makefile.am
---- pidgin-2.10.7/libpurple/protocols/oscar/Makefile.am 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/Makefile.am 1969-12-31 21:00:00.000000000 -0300
-@@ -1,81 +0,0 @@
--EXTRA_DIST = \
-- COPYING \
-- AUTHORS \
-- Makefile.mingw
--
--pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
--
--OSCARSOURCES = \
-- authorization.c \
-- bstream.c \
-- clientlogin.c \
-- encoding.c \
-- encoding.h \
-- family_admin.c \
-- family_alert.c \
-- family_auth.c \
-- family_bart.c \
-- family_bos.c \
-- family_buddy.c \
-- family_chat.c \
-- family_chatnav.c \
-- family_icq.c \
-- family_icbm.c \
-- family_locate.c \
-- family_oservice.c \
-- family_popup.c \
-- family_feedbag.c \
-- family_stats.c \
-- family_userlookup.c \
-- flap_connection.c \
-- misc.c \
-- msgcookie.c \
-- odc.c \
-- oft.c \
-- oscar.c \
-- oscar.h \
-- oscarcommon.h \
-- oscar_data.c \
-- peer.c \
-- peer.h \
-- peer_proxy.c \
-- rxhandlers.c \
-- snac.c \
-- snactypes.h \
-- tlv.c \
-- userinfo.c \
-- util.c \
-- visibility.c \
-- visibility.h
--
--AM_CFLAGS = $(st)
--
--libaim_la_LDFLAGS = -module -avoid-version
--libicq_la_LDFLAGS = -module -avoid-version
--if STATIC_OSCAR
--
--st = -DPURPLE_STATIC_PRPL
--noinst_LTLIBRARIES = liboscar.la
--liboscar_la_SOURCES = $(OSCARSOURCES) libaim.c libicq.c
--liboscar_la_CFLAGS = $(AM_CFLAGS)
--
--else
--
--st =
--pkg_LTLIBRARIES = liboscar.la libaim.la libicq.la
--liboscar_la_SOURCES = $(OSCARSOURCES)
--liboscar_la_LIBADD = $(GLIB_LIBS)
--
--libaim_la_SOURCES = libaim.c
--libaim_la_LIBADD = liboscar.la
--
--libicq_la_SOURCES = libicq.c
--libicq_la_LIBADD = liboscar.la
--
--endif
--
--AM_CPPFLAGS = \
-- -I$(top_srcdir)/libpurple \
-- -I$(top_builddir)/libpurple \
-- $(GLIB_CFLAGS) \
-- $(DEBUG_CFLAGS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/oscar/Makefile.in
---- pidgin-2.10.7/libpurple/protocols/oscar/Makefile.in 2013-02-11 07:17:21.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/Makefile.in 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1133 +0,0 @@
--# Makefile.in generated by automake 1.11.6 from Makefile.am.
--# @configure_input@
--
--# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
--# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
--# Foundation, Inc.
--# This Makefile.in is free software; the Free Software Foundation
--# gives unlimited permission to copy and/or distribute it,
--# with or without modifications, as long as this notice is preserved.
--
--# This program is distributed in the hope that it will be useful,
--# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
--# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
--# PARTICULAR PURPOSE.
--
--@SET_MAKE@
--
--VPATH = @srcdir@
--am__make_dryrun = \
-- { \
-- am__dry=no; \
-- case $$MAKEFLAGS in \
-- *\\[\ \ ]*) \
-- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
-- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
-- *) \
-- for am__flg in $$MAKEFLAGS; do \
-- case $$am__flg in \
-- *=*|--*) ;; \
-- *n*) am__dry=yes; break;; \
-- esac; \
-- done;; \
-- esac; \
-- test $$am__dry = yes; \
-- }
--pkgdatadir = $(datadir)/@PACKAGE@
--pkgincludedir = $(includedir)/@PACKAGE@
--pkglibdir = $(libdir)/@PACKAGE@
--pkglibexecdir = $(libexecdir)/@PACKAGE@
--am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
--install_sh_DATA = $(install_sh) -c -m 644
--install_sh_PROGRAM = $(install_sh) -c
--install_sh_SCRIPT = $(install_sh) -c
--INSTALL_HEADER = $(INSTALL_DATA)
--transform = $(program_transform_name)
--NORMAL_INSTALL = :
--PRE_INSTALL = :
--POST_INSTALL = :
--NORMAL_UNINSTALL = :
--PRE_UNINSTALL = :
--POST_UNINSTALL = :
--build_triplet = @build@
--host_triplet = @host@
--subdir = libpurple/protocols/oscar
--DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in AUTHORS \
-- COPYING
--ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
--am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
-- $(top_srcdir)/configure.ac
--am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-- $(ACLOCAL_M4)
--mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
--CONFIG_HEADER = $(top_builddir)/config.h
--CONFIG_CLEAN_FILES =
--CONFIG_CLEAN_VPATH_FILES =
--am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
--am__vpath_adj = case $$p in \
-- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
-- *) f=$$p;; \
-- esac;
--am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
--am__install_max = 40
--am__nobase_strip_setup = \
-- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
--am__nobase_strip = \
-- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
--am__nobase_list = $(am__nobase_strip_setup); \
-- for p in $$list; do echo "$$p $$p"; done | \
-- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
-- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
-- if (++n[$$2] == $(am__install_max)) \
-- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
-- END { for (dir in files) print dir, files[dir] }'
--am__base_list = \
-- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
-- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
--am__uninstall_files_from_dir = { \
-- test -z "$$files" \
-- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
-- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
-- $(am__cd) "$$dir" && rm -f $$files; }; \
-- }
--am__installdirs = "$(DESTDIR)$(pkgdir)"
--LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkg_LTLIBRARIES)
--@STATIC_OSCAR_FALSE@libaim_la_DEPENDENCIES = liboscar.la
--am__libaim_la_SOURCES_DIST = libaim.c
--@STATIC_OSCAR_FALSE@am_libaim_la_OBJECTS = libaim.lo
--libaim_la_OBJECTS = $(am_libaim_la_OBJECTS)
--AM_V_lt = $(am__v_lt_@AM_V@)
--am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
--am__v_lt_0 = --silent
--libaim_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-- $(libaim_la_LDFLAGS) $(LDFLAGS) -o $@
--@STATIC_OSCAR_FALSE@am_libaim_la_rpath = -rpath $(pkgdir)
--@STATIC_OSCAR_FALSE@libicq_la_DEPENDENCIES = liboscar.la
--am__libicq_la_SOURCES_DIST = libicq.c
--@STATIC_OSCAR_FALSE@am_libicq_la_OBJECTS = libicq.lo
--libicq_la_OBJECTS = $(am_libicq_la_OBJECTS)
--libicq_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-- $(libicq_la_LDFLAGS) $(LDFLAGS) -o $@
--@STATIC_OSCAR_FALSE@am_libicq_la_rpath = -rpath $(pkgdir)
--am__DEPENDENCIES_1 =
--@STATIC_OSCAR_FALSE@liboscar_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
--am__liboscar_la_SOURCES_DIST = authorization.c bstream.c clientlogin.c \
-- encoding.c encoding.h family_admin.c family_alert.c \
-- family_auth.c family_bart.c family_bos.c family_buddy.c \
-- family_chat.c family_chatnav.c family_icq.c family_icbm.c \
-- family_locate.c family_oservice.c family_popup.c \
-- family_feedbag.c family_stats.c family_userlookup.c \
-- flap_connection.c misc.c msgcookie.c odc.c oft.c oscar.c \
-- oscar.h oscarcommon.h oscar_data.c peer.c peer.h peer_proxy.c \
-- rxhandlers.c snac.c snactypes.h tlv.c userinfo.c util.c \
-- visibility.c visibility.h libaim.c libicq.c
--am__objects_1 = liboscar_la-authorization.lo liboscar_la-bstream.lo \
-- liboscar_la-clientlogin.lo liboscar_la-encoding.lo \
-- liboscar_la-family_admin.lo liboscar_la-family_alert.lo \
-- liboscar_la-family_auth.lo liboscar_la-family_bart.lo \
-- liboscar_la-family_bos.lo liboscar_la-family_buddy.lo \
-- liboscar_la-family_chat.lo liboscar_la-family_chatnav.lo \
-- liboscar_la-family_icq.lo liboscar_la-family_icbm.lo \
-- liboscar_la-family_locate.lo liboscar_la-family_oservice.lo \
-- liboscar_la-family_popup.lo liboscar_la-family_feedbag.lo \
-- liboscar_la-family_stats.lo liboscar_la-family_userlookup.lo \
-- liboscar_la-flap_connection.lo liboscar_la-misc.lo \
-- liboscar_la-msgcookie.lo liboscar_la-odc.lo liboscar_la-oft.lo \
-- liboscar_la-oscar.lo liboscar_la-oscar_data.lo \
-- liboscar_la-peer.lo liboscar_la-peer_proxy.lo \
-- liboscar_la-rxhandlers.lo liboscar_la-snac.lo \
-- liboscar_la-tlv.lo liboscar_la-userinfo.lo liboscar_la-util.lo \
-- liboscar_la-visibility.lo
--@STATIC_OSCAR_FALSE@am_liboscar_la_OBJECTS = $(am__objects_1)
--@STATIC_OSCAR_TRUE@am_liboscar_la_OBJECTS = $(am__objects_1) \
--@STATIC_OSCAR_TRUE@ liboscar_la-libaim.lo liboscar_la-libicq.lo
--liboscar_la_OBJECTS = $(am_liboscar_la_OBJECTS)
--liboscar_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(liboscar_la_CFLAGS) \
-- $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
--@STATIC_OSCAR_FALSE@am_liboscar_la_rpath = -rpath $(pkgdir)
--@STATIC_OSCAR_TRUE@am_liboscar_la_rpath =
--DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
--depcomp = $(SHELL) $(top_srcdir)/depcomp
--am__depfiles_maybe = depfiles
--am__mv = mv -f
--COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
--LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-- $(AM_CFLAGS) $(CFLAGS)
--AM_V_CC = $(am__v_CC_@AM_V@)
--am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
--am__v_CC_0 = @echo " CC " $@;
--AM_V_at = $(am__v_at_@AM_V@)
--am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
--am__v_at_0 = @
--CCLD = $(CC)
--LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-- $(AM_LDFLAGS) $(LDFLAGS) -o $@
--AM_V_CCLD = $(am__v_CCLD_@AM_V@)
--am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
--am__v_CCLD_0 = @echo " CCLD " $@;
--AM_V_GEN = $(am__v_GEN_@AM_V@)
--am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
--am__v_GEN_0 = @echo " GEN " $@;
--SOURCES = $(libaim_la_SOURCES) $(libicq_la_SOURCES) \
-- $(liboscar_la_SOURCES)
--DIST_SOURCES = $(am__libaim_la_SOURCES_DIST) \
-- $(am__libicq_la_SOURCES_DIST) $(am__liboscar_la_SOURCES_DIST)
--am__can_run_installinfo = \
-- case $$AM_UPDATE_INFO_DIR in \
-- n|no|NO) false;; \
-- *) (install-info --version) >/dev/null 2>&1;; \
-- esac
--ETAGS = etags
--CTAGS = ctags
--DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
--ACLOCAL = @ACLOCAL@
--ALLOCA = @ALLOCA@
--ALL_LINGUAS = @ALL_LINGUAS@
--AMTAR = @AMTAR@
--AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
--AR = @AR@
--AUTOCONF = @AUTOCONF@
--AUTOHEADER = @AUTOHEADER@
--AUTOMAKE = @AUTOMAKE@
--AVAHI_CFLAGS = @AVAHI_CFLAGS@
--AVAHI_LIBS = @AVAHI_LIBS@
--AWK = @AWK@
--CATALOGS = @CATALOGS@
--CATOBJEXT = @CATOBJEXT@
--CC = @CC@
--CCDEPMODE = @CCDEPMODE@
--CFLAGS = @CFLAGS@
--CHECK_CFLAGS = @CHECK_CFLAGS@
--CHECK_LIBS = @CHECK_LIBS@
--CPP = @CPP@
--CPPFLAGS = @CPPFLAGS@
--CYGPATH_W = @CYGPATH_W@
--DATADIRNAME = @DATADIRNAME@
--DBUS_CFLAGS = @DBUS_CFLAGS@
--DBUS_LIBS = @DBUS_LIBS@
--DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
--DEBUG_CFLAGS = @DEBUG_CFLAGS@
--DEFS = @DEFS@
--DEPDIR = @DEPDIR@
--DLLTOOL = @DLLTOOL@
--DOT = @DOT@
--DOXYGEN = @DOXYGEN@
--DSYMUTIL = @DSYMUTIL@
--DUMPBIN = @DUMPBIN@
--DYNALOADER_A = @DYNALOADER_A@
--DYNAMIC_PRPLS = @DYNAMIC_PRPLS@
--ECHO_C = @ECHO_C@
--ECHO_N = @ECHO_N@
--ECHO_T = @ECHO_T@
--EGREP = @EGREP@
--EVOLUTION_ADDRESSBOOK_CFLAGS = @EVOLUTION_ADDRESSBOOK_CFLAGS@
--EVOLUTION_ADDRESSBOOK_LIBS = @EVOLUTION_ADDRESSBOOK_LIBS@
--EXEEXT = @EXEEXT@
--FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
--FARSTREAM_LIBS = @FARSTREAM_LIBS@
--FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
--GCONFTOOL = @GCONFTOOL@
--GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
--GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
--GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
--GLIB_CFLAGS = @GLIB_CFLAGS@
--GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
--GLIB_LIBS = @GLIB_LIBS@
--GMOFILES = @GMOFILES@
--GMSGFMT = @GMSGFMT@
--GNT_CFLAGS = @GNT_CFLAGS@
--GNT_LIBS = @GNT_LIBS@
--GNT_LT_VERSION_INFO = @GNT_LT_VERSION_INFO@
--GNT_MAJOR_VERSION = @GNT_MAJOR_VERSION@
--GNT_MICRO_VERSION = @GNT_MICRO_VERSION@
--GNT_MINOR_VERSION = @GNT_MINOR_VERSION@
--GNT_VERSION = @GNT_VERSION@
--GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
--GNUTLS_LIBS = @GNUTLS_LIBS@
--GREP = @GREP@
--GSTINTERFACES_CFLAGS = @GSTINTERFACES_CFLAGS@
--GSTINTERFACES_LIBS = @GSTINTERFACES_LIBS@
--GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
--GSTREAMER_LIBS = @GSTREAMER_LIBS@
--GTKSPELL_CFLAGS = @GTKSPELL_CFLAGS@
--GTKSPELL_LIBS = @GTKSPELL_LIBS@
--GTK_CFLAGS = @GTK_CFLAGS@
--GTK_LIBS = @GTK_LIBS@
--IDN_CFLAGS = @IDN_CFLAGS@
--IDN_LIBS = @IDN_LIBS@
--INSTALL = @INSTALL@
--INSTALL_DATA = @INSTALL_DATA@
--INSTALL_PROGRAM = @INSTALL_PROGRAM@
--INSTALL_SCRIPT = @INSTALL_SCRIPT@
--INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
--INSTOBJEXT = @INSTOBJEXT@
--INTLLIBS = @INTLLIBS@
--INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
--INTLTOOL_MERGE = @INTLTOOL_MERGE@
--INTLTOOL_PERL = @INTLTOOL_PERL@
--INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
--INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
--INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
--INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
--INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
--KRB4_CFLAGS = @KRB4_CFLAGS@
--KRB4_LDFLAGS = @KRB4_LDFLAGS@
--KRB4_LIBS = @KRB4_LIBS@
--LD = @LD@
--LDADD = @LDADD@
--LDFLAGS = @LDFLAGS@
--LIBOBJS = @LIBOBJS@
--LIBPERL_A = @LIBPERL_A@
--LIBS = @LIBS@
--LIBTOOL = @LIBTOOL@
--LIBXML_CFLAGS = @LIBXML_CFLAGS@
--LIBXML_LIBS = @LIBXML_LIBS@
--LIPO = @LIPO@
--LN_S = @LN_S@
--LTLIBOBJS = @LTLIBOBJS@
--MAKEINFO = @MAKEINFO@
--MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
--MKDIR_P = @MKDIR_P@
--MKINSTALLDIRS = @MKINSTALLDIRS@
--MONO_CFLAGS = @MONO_CFLAGS@
--MONO_LIBS = @MONO_LIBS@
--MSGFMT = @MSGFMT@
--MSGFMT_OPTS = @MSGFMT_OPTS@
--MSGMERGE = @MSGMERGE@
--NETWORKMANAGER_CFLAGS = @NETWORKMANAGER_CFLAGS@
--NETWORKMANAGER_LIBS = @NETWORKMANAGER_LIBS@
--NM = @NM@
--NMEDIT = @NMEDIT@
--NSS_CFLAGS = @NSS_CFLAGS@
--NSS_LIBS = @NSS_LIBS@
--OBJDUMP = @OBJDUMP@
--OBJEXT = @OBJEXT@
--OTOOL = @OTOOL@
--OTOOL64 = @OTOOL64@
--PACKAGE = @PACKAGE@
--PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
--PACKAGE_NAME = @PACKAGE_NAME@
--PACKAGE_STRING = @PACKAGE_STRING@
--PACKAGE_TARNAME = @PACKAGE_TARNAME@
--PACKAGE_URL = @PACKAGE_URL@
--PACKAGE_VERSION = @PACKAGE_VERSION@
--PANGO_CFLAGS = @PANGO_CFLAGS@
--PANGO_LIBS = @PANGO_LIBS@
--PATH_SEPARATOR = @PATH_SEPARATOR@
--PERL = @PERL@
--PERL_CFLAGS = @PERL_CFLAGS@
--PERL_LIBS = @PERL_LIBS@
--PKG_CONFIG = @PKG_CONFIG@
--PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
--PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
--PLUGINS_DEFINE = @PLUGINS_DEFINE@
--POFILES = @POFILES@
--POSUB = @POSUB@
--PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
--PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
--PURPLE_LT_VERSION_INFO = @PURPLE_LT_VERSION_INFO@
--PURPLE_MAJOR_VERSION = @PURPLE_MAJOR_VERSION@
--PURPLE_MICRO_VERSION = @PURPLE_MICRO_VERSION@
--PURPLE_MINOR_VERSION = @PURPLE_MINOR_VERSION@
--PURPLE_VERSION = @PURPLE_VERSION@
--PYTHON = @PYTHON@
--PY_CFLAGS = @PY_CFLAGS@
--PY_LIBS = @PY_LIBS@
--RANLIB = @RANLIB@
--SASL_LIBS = @SASL_LIBS@
--SED = @SED@
--SET_MAKE = @SET_MAKE@
--SHELL = @SHELL@
--SILC_CFLAGS = @SILC_CFLAGS@
--SILC_LIBS = @SILC_LIBS@
--SM_LIBS = @SM_LIBS@
--SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
--SQLITE3_LIBS = @SQLITE3_LIBS@
--SSL_CERTIFICATES_DIR = @SSL_CERTIFICATES_DIR@
--STATIC_LINK_LIBS = @STATIC_LINK_LIBS@
--STATIC_PRPLS = @STATIC_PRPLS@
--STRIP = @STRIP@
--TCL_CFLAGS = @TCL_CFLAGS@
--TCL_LIBS = @TCL_LIBS@
--TK_LIBS = @TK_LIBS@
--USE_NLS = @USE_NLS@
--VERSION = @VERSION@
--X11_CFLAGS = @X11_CFLAGS@
--X11_LIBS = @X11_LIBS@
--XGETTEXT = @XGETTEXT@
--XMKMF = @XMKMF@
--XSLTPROC = @XSLTPROC@
--XSS_LIBS = @XSS_LIBS@
--X_CFLAGS = @X_CFLAGS@
--X_EXTRA_LIBS = @X_EXTRA_LIBS@
--X_LIBS = @X_LIBS@
--X_PRE_LIBS = @X_PRE_LIBS@
--ZEPHYR_CFLAGS = @ZEPHYR_CFLAGS@
--ZEPHYR_LDFLAGS = @ZEPHYR_LDFLAGS@
--ZEPHYR_LIBS = @ZEPHYR_LIBS@
--abs_builddir = @abs_builddir@
--abs_srcdir = @abs_srcdir@
--abs_top_builddir = @abs_top_builddir@
--abs_top_srcdir = @abs_top_srcdir@
--ac_ct_AR = @ac_ct_AR@
--ac_ct_CC = @ac_ct_CC@
--ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
--am__include = @am__include@
--am__leading_dot = @am__leading_dot@
--am__quote = @am__quote@
--am__tar = @am__tar@
--am__untar = @am__untar@
--bindir = @bindir@
--build = @build@
--build_alias = @build_alias@
--build_cpu = @build_cpu@
--build_os = @build_os@
--build_vendor = @build_vendor@
--builddir = @builddir@
--datadir = @datadir@
--datarootdir = @datarootdir@
--docdir = @docdir@
--dvidir = @dvidir@
--enable_dbus = @enable_dbus@
--enable_devhelp = @enable_devhelp@
--enable_dot = @enable_dot@
--enable_doxygen = @enable_doxygen@
--exec_prefix = @exec_prefix@
--host = @host@
--host_alias = @host_alias@
--host_cpu = @host_cpu@
--host_os = @host_os@
--host_vendor = @host_vendor@
--htmldir = @htmldir@
--includedir = @includedir@
--infodir = @infodir@
--install_sh = @install_sh@
--intltool__v_merge_options_ = @intltool__v_merge_options_@
--intltool__v_merge_options_0 = @intltool__v_merge_options_0@
--libdir = @libdir@
--libexecdir = @libexecdir@
--localedir = @localedir@
--localstatedir = @localstatedir@
--mandir = @mandir@
--mkdir_p = @mkdir_p@
--oldincludedir = @oldincludedir@
--pdfdir = @pdfdir@
--perlpath = @perlpath@
--pidginpath = @pidginpath@
--prefix = @prefix@
--program_transform_name = @program_transform_name@
--psdir = @psdir@
--sbindir = @sbindir@
--sedpath = @sedpath@
--sharedstatedir = @sharedstatedir@
--srcdir = @srcdir@
--sysconfdir = @sysconfdir@
--target_alias = @target_alias@
--top_build_prefix = @top_build_prefix@
--top_builddir = @top_builddir@
--top_srcdir = @top_srcdir@
--EXTRA_DIST = \
-- COPYING \
-- AUTHORS \
-- Makefile.mingw
--
--pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
--OSCARSOURCES = \
-- authorization.c \
-- bstream.c \
-- clientlogin.c \
-- encoding.c \
-- encoding.h \
-- family_admin.c \
-- family_alert.c \
-- family_auth.c \
-- family_bart.c \
-- family_bos.c \
-- family_buddy.c \
-- family_chat.c \
-- family_chatnav.c \
-- family_icq.c \
-- family_icbm.c \
-- family_locate.c \
-- family_oservice.c \
-- family_popup.c \
-- family_feedbag.c \
-- family_stats.c \
-- family_userlookup.c \
-- flap_connection.c \
-- misc.c \
-- msgcookie.c \
-- odc.c \
-- oft.c \
-- oscar.c \
-- oscar.h \
-- oscarcommon.h \
-- oscar_data.c \
-- peer.c \
-- peer.h \
-- peer_proxy.c \
-- rxhandlers.c \
-- snac.c \
-- snactypes.h \
-- tlv.c \
-- userinfo.c \
-- util.c \
-- visibility.c \
-- visibility.h
--
--AM_CFLAGS = $(st)
--libaim_la_LDFLAGS = -module -avoid-version
--libicq_la_LDFLAGS = -module -avoid-version
--@STATIC_OSCAR_FALSE@st =
--@STATIC_OSCAR_TRUE@st = -DPURPLE_STATIC_PRPL
--@STATIC_OSCAR_TRUE@noinst_LTLIBRARIES = liboscar.la
--@STATIC_OSCAR_FALSE@liboscar_la_SOURCES = $(OSCARSOURCES)
--@STATIC_OSCAR_TRUE@liboscar_la_SOURCES = $(OSCARSOURCES) libaim.c libicq.c
--@STATIC_OSCAR_TRUE@liboscar_la_CFLAGS = $(AM_CFLAGS)
--@STATIC_OSCAR_FALSE@pkg_LTLIBRARIES = liboscar.la libaim.la libicq.la
--@STATIC_OSCAR_FALSE@liboscar_la_LIBADD = $(GLIB_LIBS)
--@STATIC_OSCAR_FALSE@libaim_la_SOURCES = libaim.c
--@STATIC_OSCAR_FALSE@libaim_la_LIBADD = liboscar.la
--@STATIC_OSCAR_FALSE@libicq_la_SOURCES = libicq.c
--@STATIC_OSCAR_FALSE@libicq_la_LIBADD = liboscar.la
--AM_CPPFLAGS = \
-- -I$(top_srcdir)/libpurple \
-- -I$(top_builddir)/libpurple \
-- $(GLIB_CFLAGS) \
-- $(DEBUG_CFLAGS)
--
--all: all-am
--
--.SUFFIXES:
--.SUFFIXES: .c .lo .o .obj
--$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
-- @for dep in $?; do \
-- case '$(am__configure_deps)' in \
-- *$$dep*) \
-- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
-- && { if test -f $@; then exit 0; else break; fi; }; \
-- exit 1;; \
-- esac; \
-- done; \
-- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpurple/protocols/oscar/Makefile'; \
-- $(am__cd) $(top_srcdir) && \
-- $(AUTOMAKE) --gnu libpurple/protocols/oscar/Makefile
--.PRECIOUS: Makefile
--Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-- @case '$?' in \
-- *config.status*) \
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-- *) \
-- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-- esac;
--
--$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--
--$(top_srcdir)/configure: $(am__configure_deps)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--$(ACLOCAL_M4): $(am__aclocal_m4_deps)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--$(am__aclocal_m4_deps):
--
--clean-noinstLTLIBRARIES:
-- -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-- @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
-- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-- test "$$dir" != "$$p" || dir=.; \
-- echo "rm -f \"$${dir}/so_locations\""; \
-- rm -f "$${dir}/so_locations"; \
-- done
--install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES)
-- @$(NORMAL_INSTALL)
-- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
-- list2=; for p in $$list; do \
-- if test -f $$p; then \
-- list2="$$list2 $$p"; \
-- else :; fi; \
-- done; \
-- test -z "$$list2" || { \
-- echo " $(MKDIR_P) '$(DESTDIR)$(pkgdir)'"; \
-- $(MKDIR_P) "$(DESTDIR)$(pkgdir)" || exit 1; \
-- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgdir)'"; \
-- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgdir)"; \
-- }
--
--uninstall-pkgLTLIBRARIES:
-- @$(NORMAL_UNINSTALL)
-- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
-- for p in $$list; do \
-- $(am__strip_dir) \
-- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgdir)/$$f'"; \
-- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgdir)/$$f"; \
-- done
--
--clean-pkgLTLIBRARIES:
-- -test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES)
-- @list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
-- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-- test "$$dir" != "$$p" || dir=.; \
-- echo "rm -f \"$${dir}/so_locations\""; \
-- rm -f "$${dir}/so_locations"; \
-- done
--libaim.la: $(libaim_la_OBJECTS) $(libaim_la_DEPENDENCIES) $(EXTRA_libaim_la_DEPENDENCIES)
-- $(AM_V_CCLD)$(libaim_la_LINK) $(am_libaim_la_rpath) $(libaim_la_OBJECTS) $(libaim_la_LIBADD) $(LIBS)
--libicq.la: $(libicq_la_OBJECTS) $(libicq_la_DEPENDENCIES) $(EXTRA_libicq_la_DEPENDENCIES)
-- $(AM_V_CCLD)$(libicq_la_LINK) $(am_libicq_la_rpath) $(libicq_la_OBJECTS) $(libicq_la_LIBADD) $(LIBS)
--liboscar.la: $(liboscar_la_OBJECTS) $(liboscar_la_DEPENDENCIES) $(EXTRA_liboscar_la_DEPENDENCIES)
-- $(AM_V_CCLD)$(liboscar_la_LINK) $(am_liboscar_la_rpath) $(liboscar_la_OBJECTS) $(liboscar_la_LIBADD) $(LIBS)
--
--mostlyclean-compile:
-- -rm -f *.$(OBJEXT)
--
--distclean-compile:
-- -rm -f *.tab.c
--
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaim.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libicq.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-authorization.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-bstream.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-clientlogin.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-encoding.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_admin.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_alert.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_auth.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_bart.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_bos.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_buddy.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_chat.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_chatnav.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_feedbag.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_icbm.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_icq.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_locate.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_oservice.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_popup.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_stats.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_userlookup.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-flap_connection.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-libaim.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-libicq.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-misc.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-msgcookie.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-odc.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-oft.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-oscar.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-oscar_data.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-peer.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-peer_proxy.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-rxhandlers.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-snac.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-tlv.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-userinfo.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-util.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-visibility.Plo@am__quote@
--
--.c.o:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
--
--.c.obj:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
--
--.c.lo:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
--
--liboscar_la-authorization.lo: authorization.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-authorization.lo -MD -MP -MF $(DEPDIR)/liboscar_la-authorization.Tpo -c -o liboscar_la-authorization.lo `test -f 'authorization.c' || echo '$(srcdir)/'`authorization.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-authorization.Tpo $(DEPDIR)/liboscar_la-authorization.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='authorization.c' object='liboscar_la-authorization.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-authorization.lo `test -f 'authorization.c' || echo '$(srcdir)/'`authorization.c
--
--liboscar_la-bstream.lo: bstream.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-bstream.lo -MD -MP -MF $(DEPDIR)/liboscar_la-bstream.Tpo -c -o liboscar_la-bstream.lo `test -f 'bstream.c' || echo '$(srcdir)/'`bstream.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-bstream.Tpo $(DEPDIR)/liboscar_la-bstream.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bstream.c' object='liboscar_la-bstream.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-bstream.lo `test -f 'bstream.c' || echo '$(srcdir)/'`bstream.c
--
--liboscar_la-clientlogin.lo: clientlogin.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-clientlogin.lo -MD -MP -MF $(DEPDIR)/liboscar_la-clientlogin.Tpo -c -o liboscar_la-clientlogin.lo `test -f 'clientlogin.c' || echo '$(srcdir)/'`clientlogin.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-clientlogin.Tpo $(DEPDIR)/liboscar_la-clientlogin.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='clientlogin.c' object='liboscar_la-clientlogin.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-clientlogin.lo `test -f 'clientlogin.c' || echo '$(srcdir)/'`clientlogin.c
--
--liboscar_la-encoding.lo: encoding.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-encoding.lo -MD -MP -MF $(DEPDIR)/liboscar_la-encoding.Tpo -c -o liboscar_la-encoding.lo `test -f 'encoding.c' || echo '$(srcdir)/'`encoding.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-encoding.Tpo $(DEPDIR)/liboscar_la-encoding.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='encoding.c' object='liboscar_la-encoding.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-encoding.lo `test -f 'encoding.c' || echo '$(srcdir)/'`encoding.c
--
--liboscar_la-family_admin.lo: family_admin.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_admin.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_admin.Tpo -c -o liboscar_la-family_admin.lo `test -f 'family_admin.c' || echo '$(srcdir)/'`family_admin.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_admin.Tpo $(DEPDIR)/liboscar_la-family_admin.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_admin.c' object='liboscar_la-family_admin.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_admin.lo `test -f 'family_admin.c' || echo '$(srcdir)/'`family_admin.c
--
--liboscar_la-family_alert.lo: family_alert.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_alert.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_alert.Tpo -c -o liboscar_la-family_alert.lo `test -f 'family_alert.c' || echo '$(srcdir)/'`family_alert.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_alert.Tpo $(DEPDIR)/liboscar_la-family_alert.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_alert.c' object='liboscar_la-family_alert.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_alert.lo `test -f 'family_alert.c' || echo '$(srcdir)/'`family_alert.c
--
--liboscar_la-family_auth.lo: family_auth.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_auth.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_auth.Tpo -c -o liboscar_la-family_auth.lo `test -f 'family_auth.c' || echo '$(srcdir)/'`family_auth.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_auth.Tpo $(DEPDIR)/liboscar_la-family_auth.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_auth.c' object='liboscar_la-family_auth.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_auth.lo `test -f 'family_auth.c' || echo '$(srcdir)/'`family_auth.c
--
--liboscar_la-family_bart.lo: family_bart.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_bart.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_bart.Tpo -c -o liboscar_la-family_bart.lo `test -f 'family_bart.c' || echo '$(srcdir)/'`family_bart.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_bart.Tpo $(DEPDIR)/liboscar_la-family_bart.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_bart.c' object='liboscar_la-family_bart.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_bart.lo `test -f 'family_bart.c' || echo '$(srcdir)/'`family_bart.c
--
--liboscar_la-family_bos.lo: family_bos.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_bos.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_bos.Tpo -c -o liboscar_la-family_bos.lo `test -f 'family_bos.c' || echo '$(srcdir)/'`family_bos.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_bos.Tpo $(DEPDIR)/liboscar_la-family_bos.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_bos.c' object='liboscar_la-family_bos.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_bos.lo `test -f 'family_bos.c' || echo '$(srcdir)/'`family_bos.c
--
--liboscar_la-family_buddy.lo: family_buddy.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_buddy.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_buddy.Tpo -c -o liboscar_la-family_buddy.lo `test -f 'family_buddy.c' || echo '$(srcdir)/'`family_buddy.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_buddy.Tpo $(DEPDIR)/liboscar_la-family_buddy.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_buddy.c' object='liboscar_la-family_buddy.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_buddy.lo `test -f 'family_buddy.c' || echo '$(srcdir)/'`family_buddy.c
--
--liboscar_la-family_chat.lo: family_chat.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_chat.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_chat.Tpo -c -o liboscar_la-family_chat.lo `test -f 'family_chat.c' || echo '$(srcdir)/'`family_chat.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_chat.Tpo $(DEPDIR)/liboscar_la-family_chat.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_chat.c' object='liboscar_la-family_chat.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_chat.lo `test -f 'family_chat.c' || echo '$(srcdir)/'`family_chat.c
--
--liboscar_la-family_chatnav.lo: family_chatnav.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_chatnav.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_chatnav.Tpo -c -o liboscar_la-family_chatnav.lo `test -f 'family_chatnav.c' || echo '$(srcdir)/'`family_chatnav.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_chatnav.Tpo $(DEPDIR)/liboscar_la-family_chatnav.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_chatnav.c' object='liboscar_la-family_chatnav.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_chatnav.lo `test -f 'family_chatnav.c' || echo '$(srcdir)/'`family_chatnav.c
--
--liboscar_la-family_icq.lo: family_icq.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_icq.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_icq.Tpo -c -o liboscar_la-family_icq.lo `test -f 'family_icq.c' || echo '$(srcdir)/'`family_icq.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_icq.Tpo $(DEPDIR)/liboscar_la-family_icq.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_icq.c' object='liboscar_la-family_icq.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_icq.lo `test -f 'family_icq.c' || echo '$(srcdir)/'`family_icq.c
--
--liboscar_la-family_icbm.lo: family_icbm.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_icbm.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_icbm.Tpo -c -o liboscar_la-family_icbm.lo `test -f 'family_icbm.c' || echo '$(srcdir)/'`family_icbm.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_icbm.Tpo $(DEPDIR)/liboscar_la-family_icbm.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_icbm.c' object='liboscar_la-family_icbm.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_icbm.lo `test -f 'family_icbm.c' || echo '$(srcdir)/'`family_icbm.c
--
--liboscar_la-family_locate.lo: family_locate.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_locate.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_locate.Tpo -c -o liboscar_la-family_locate.lo `test -f 'family_locate.c' || echo '$(srcdir)/'`family_locate.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_locate.Tpo $(DEPDIR)/liboscar_la-family_locate.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_locate.c' object='liboscar_la-family_locate.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_locate.lo `test -f 'family_locate.c' || echo '$(srcdir)/'`family_locate.c
--
--liboscar_la-family_oservice.lo: family_oservice.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_oservice.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_oservice.Tpo -c -o liboscar_la-family_oservice.lo `test -f 'family_oservice.c' || echo '$(srcdir)/'`family_oservice.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_oservice.Tpo $(DEPDIR)/liboscar_la-family_oservice.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_oservice.c' object='liboscar_la-family_oservice.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_oservice.lo `test -f 'family_oservice.c' || echo '$(srcdir)/'`family_oservice.c
--
--liboscar_la-family_popup.lo: family_popup.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_popup.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_popup.Tpo -c -o liboscar_la-family_popup.lo `test -f 'family_popup.c' || echo '$(srcdir)/'`family_popup.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_popup.Tpo $(DEPDIR)/liboscar_la-family_popup.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_popup.c' object='liboscar_la-family_popup.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_popup.lo `test -f 'family_popup.c' || echo '$(srcdir)/'`family_popup.c
--
--liboscar_la-family_feedbag.lo: family_feedbag.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_feedbag.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_feedbag.Tpo -c -o liboscar_la-family_feedbag.lo `test -f 'family_feedbag.c' || echo '$(srcdir)/'`family_feedbag.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_feedbag.Tpo $(DEPDIR)/liboscar_la-family_feedbag.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_feedbag.c' object='liboscar_la-family_feedbag.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_feedbag.lo `test -f 'family_feedbag.c' || echo '$(srcdir)/'`family_feedbag.c
--
--liboscar_la-family_stats.lo: family_stats.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_stats.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_stats.Tpo -c -o liboscar_la-family_stats.lo `test -f 'family_stats.c' || echo '$(srcdir)/'`family_stats.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_stats.Tpo $(DEPDIR)/liboscar_la-family_stats.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_stats.c' object='liboscar_la-family_stats.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_stats.lo `test -f 'family_stats.c' || echo '$(srcdir)/'`family_stats.c
--
--liboscar_la-family_userlookup.lo: family_userlookup.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_userlookup.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_userlookup.Tpo -c -o liboscar_la-family_userlookup.lo `test -f 'family_userlookup.c' || echo '$(srcdir)/'`family_userlookup.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_userlookup.Tpo $(DEPDIR)/liboscar_la-family_userlookup.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_userlookup.c' object='liboscar_la-family_userlookup.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_userlookup.lo `test -f 'family_userlookup.c' || echo '$(srcdir)/'`family_userlookup.c
--
--liboscar_la-flap_connection.lo: flap_connection.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-flap_connection.lo -MD -MP -MF $(DEPDIR)/liboscar_la-flap_connection.Tpo -c -o liboscar_la-flap_connection.lo `test -f 'flap_connection.c' || echo '$(srcdir)/'`flap_connection.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-flap_connection.Tpo $(DEPDIR)/liboscar_la-flap_connection.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='flap_connection.c' object='liboscar_la-flap_connection.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-flap_connection.lo `test -f 'flap_connection.c' || echo '$(srcdir)/'`flap_connection.c
--
--liboscar_la-misc.lo: misc.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-misc.lo -MD -MP -MF $(DEPDIR)/liboscar_la-misc.Tpo -c -o liboscar_la-misc.lo `test -f 'misc.c' || echo '$(srcdir)/'`misc.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-misc.Tpo $(DEPDIR)/liboscar_la-misc.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='misc.c' object='liboscar_la-misc.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-misc.lo `test -f 'misc.c' || echo '$(srcdir)/'`misc.c
--
--liboscar_la-msgcookie.lo: msgcookie.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-msgcookie.lo -MD -MP -MF $(DEPDIR)/liboscar_la-msgcookie.Tpo -c -o liboscar_la-msgcookie.lo `test -f 'msgcookie.c' || echo '$(srcdir)/'`msgcookie.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-msgcookie.Tpo $(DEPDIR)/liboscar_la-msgcookie.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='msgcookie.c' object='liboscar_la-msgcookie.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-msgcookie.lo `test -f 'msgcookie.c' || echo '$(srcdir)/'`msgcookie.c
--
--liboscar_la-odc.lo: odc.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-odc.lo -MD -MP -MF $(DEPDIR)/liboscar_la-odc.Tpo -c -o liboscar_la-odc.lo `test -f 'odc.c' || echo '$(srcdir)/'`odc.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-odc.Tpo $(DEPDIR)/liboscar_la-odc.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='odc.c' object='liboscar_la-odc.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-odc.lo `test -f 'odc.c' || echo '$(srcdir)/'`odc.c
--
--liboscar_la-oft.lo: oft.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-oft.lo -MD -MP -MF $(DEPDIR)/liboscar_la-oft.Tpo -c -o liboscar_la-oft.lo `test -f 'oft.c' || echo '$(srcdir)/'`oft.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-oft.Tpo $(DEPDIR)/liboscar_la-oft.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oft.c' object='liboscar_la-oft.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-oft.lo `test -f 'oft.c' || echo '$(srcdir)/'`oft.c
--
--liboscar_la-oscar.lo: oscar.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-oscar.lo -MD -MP -MF $(DEPDIR)/liboscar_la-oscar.Tpo -c -o liboscar_la-oscar.lo `test -f 'oscar.c' || echo '$(srcdir)/'`oscar.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-oscar.Tpo $(DEPDIR)/liboscar_la-oscar.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oscar.c' object='liboscar_la-oscar.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-oscar.lo `test -f 'oscar.c' || echo '$(srcdir)/'`oscar.c
--
--liboscar_la-oscar_data.lo: oscar_data.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-oscar_data.lo -MD -MP -MF $(DEPDIR)/liboscar_la-oscar_data.Tpo -c -o liboscar_la-oscar_data.lo `test -f 'oscar_data.c' || echo '$(srcdir)/'`oscar_data.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-oscar_data.Tpo $(DEPDIR)/liboscar_la-oscar_data.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oscar_data.c' object='liboscar_la-oscar_data.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-oscar_data.lo `test -f 'oscar_data.c' || echo '$(srcdir)/'`oscar_data.c
--
--liboscar_la-peer.lo: peer.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-peer.lo -MD -MP -MF $(DEPDIR)/liboscar_la-peer.Tpo -c -o liboscar_la-peer.lo `test -f 'peer.c' || echo '$(srcdir)/'`peer.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-peer.Tpo $(DEPDIR)/liboscar_la-peer.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='peer.c' object='liboscar_la-peer.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-peer.lo `test -f 'peer.c' || echo '$(srcdir)/'`peer.c
--
--liboscar_la-peer_proxy.lo: peer_proxy.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-peer_proxy.lo -MD -MP -MF $(DEPDIR)/liboscar_la-peer_proxy.Tpo -c -o liboscar_la-peer_proxy.lo `test -f 'peer_proxy.c' || echo '$(srcdir)/'`peer_proxy.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-peer_proxy.Tpo $(DEPDIR)/liboscar_la-peer_proxy.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='peer_proxy.c' object='liboscar_la-peer_proxy.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-peer_proxy.lo `test -f 'peer_proxy.c' || echo '$(srcdir)/'`peer_proxy.c
--
--liboscar_la-rxhandlers.lo: rxhandlers.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-rxhandlers.lo -MD -MP -MF $(DEPDIR)/liboscar_la-rxhandlers.Tpo -c -o liboscar_la-rxhandlers.lo `test -f 'rxhandlers.c' || echo '$(srcdir)/'`rxhandlers.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-rxhandlers.Tpo $(DEPDIR)/liboscar_la-rxhandlers.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rxhandlers.c' object='liboscar_la-rxhandlers.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-rxhandlers.lo `test -f 'rxhandlers.c' || echo '$(srcdir)/'`rxhandlers.c
--
--liboscar_la-snac.lo: snac.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-snac.lo -MD -MP -MF $(DEPDIR)/liboscar_la-snac.Tpo -c -o liboscar_la-snac.lo `test -f 'snac.c' || echo '$(srcdir)/'`snac.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-snac.Tpo $(DEPDIR)/liboscar_la-snac.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='snac.c' object='liboscar_la-snac.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-snac.lo `test -f 'snac.c' || echo '$(srcdir)/'`snac.c
--
--liboscar_la-tlv.lo: tlv.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-tlv.lo -MD -MP -MF $(DEPDIR)/liboscar_la-tlv.Tpo -c -o liboscar_la-tlv.lo `test -f 'tlv.c' || echo '$(srcdir)/'`tlv.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-tlv.Tpo $(DEPDIR)/liboscar_la-tlv.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tlv.c' object='liboscar_la-tlv.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-tlv.lo `test -f 'tlv.c' || echo '$(srcdir)/'`tlv.c
--
--liboscar_la-userinfo.lo: userinfo.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-userinfo.lo -MD -MP -MF $(DEPDIR)/liboscar_la-userinfo.Tpo -c -o liboscar_la-userinfo.lo `test -f 'userinfo.c' || echo '$(srcdir)/'`userinfo.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-userinfo.Tpo $(DEPDIR)/liboscar_la-userinfo.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='userinfo.c' object='liboscar_la-userinfo.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-userinfo.lo `test -f 'userinfo.c' || echo '$(srcdir)/'`userinfo.c
--
--liboscar_la-util.lo: util.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-util.lo -MD -MP -MF $(DEPDIR)/liboscar_la-util.Tpo -c -o liboscar_la-util.lo `test -f 'util.c' || echo '$(srcdir)/'`util.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-util.Tpo $(DEPDIR)/liboscar_la-util.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='util.c' object='liboscar_la-util.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-util.lo `test -f 'util.c' || echo '$(srcdir)/'`util.c
--
--liboscar_la-visibility.lo: visibility.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-visibility.lo -MD -MP -MF $(DEPDIR)/liboscar_la-visibility.Tpo -c -o liboscar_la-visibility.lo `test -f 'visibility.c' || echo '$(srcdir)/'`visibility.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-visibility.Tpo $(DEPDIR)/liboscar_la-visibility.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='visibility.c' object='liboscar_la-visibility.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-visibility.lo `test -f 'visibility.c' || echo '$(srcdir)/'`visibility.c
--
--liboscar_la-libaim.lo: libaim.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-libaim.lo -MD -MP -MF $(DEPDIR)/liboscar_la-libaim.Tpo -c -o liboscar_la-libaim.lo `test -f 'libaim.c' || echo '$(srcdir)/'`libaim.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-libaim.Tpo $(DEPDIR)/liboscar_la-libaim.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libaim.c' object='liboscar_la-libaim.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-libaim.lo `test -f 'libaim.c' || echo '$(srcdir)/'`libaim.c
--
--liboscar_la-libicq.lo: libicq.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-libicq.lo -MD -MP -MF $(DEPDIR)/liboscar_la-libicq.Tpo -c -o liboscar_la-libicq.lo `test -f 'libicq.c' || echo '$(srcdir)/'`libicq.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-libicq.Tpo $(DEPDIR)/liboscar_la-libicq.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libicq.c' object='liboscar_la-libicq.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-libicq.lo `test -f 'libicq.c' || echo '$(srcdir)/'`libicq.c
--
--mostlyclean-libtool:
-- -rm -f *.lo
--
--clean-libtool:
-- -rm -rf .libs _libs
--
--ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- mkid -fID $$unique
--tags: TAGS
--
--TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
-- $(TAGS_FILES) $(LISP)
-- set x; \
-- here=`pwd`; \
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- shift; \
-- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-- test -n "$$unique" || unique=$$empty_fix; \
-- if test $$# -gt 0; then \
-- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-- "$$@" $$unique; \
-- else \
-- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-- $$unique; \
-- fi; \
-- fi
--ctags: CTAGS
--CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
-- $(TAGS_FILES) $(LISP)
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- test -z "$(CTAGS_ARGS)$$unique" \
-- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-- $$unique
--
--GTAGS:
-- here=`$(am__cd) $(top_builddir) && pwd` \
-- && $(am__cd) $(top_srcdir) \
-- && gtags -i $(GTAGS_ARGS) "$$here"
--
--distclean-tags:
-- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
--
--distdir: $(DISTFILES)
-- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-- list='$(DISTFILES)'; \
-- dist_files=`for file in $$list; do echo $$file; done | \
-- sed -e "s|^$$srcdirstrip/||;t" \
-- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-- case $$dist_files in \
-- */*) $(MKDIR_P) `echo "$$dist_files" | \
-- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-- sort -u` ;; \
-- esac; \
-- for file in $$dist_files; do \
-- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-- if test -d $$d/$$file; then \
-- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-- if test -d "$(distdir)/$$file"; then \
-- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-- fi; \
-- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-- fi; \
-- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-- else \
-- test -f "$(distdir)/$$file" \
-- || cp -p $$d/$$file "$(distdir)/$$file" \
-- || exit 1; \
-- fi; \
-- done
--check-am: all-am
--check: check-am
--all-am: Makefile $(LTLIBRARIES)
--installdirs:
-- for dir in "$(DESTDIR)$(pkgdir)"; do \
-- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
-- done
--install: install-am
--install-exec: install-exec-am
--install-data: install-data-am
--uninstall: uninstall-am
--
--install-am: all-am
-- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
--
--installcheck: installcheck-am
--install-strip:
-- if test -z '$(STRIP)'; then \
-- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-- install; \
-- else \
-- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-- fi
--mostlyclean-generic:
--
--clean-generic:
--
--distclean-generic:
-- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
--
--maintainer-clean-generic:
-- @echo "This command is intended for maintainers to use"
-- @echo "it deletes files that may require special tools to rebuild."
--clean: clean-am
--
--clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
-- clean-pkgLTLIBRARIES mostlyclean-am
--
--distclean: distclean-am
-- -rm -rf ./$(DEPDIR)
-- -rm -f Makefile
--distclean-am: clean-am distclean-compile distclean-generic \
-- distclean-tags
--
--dvi: dvi-am
--
--dvi-am:
--
--html: html-am
--
--html-am:
--
--info: info-am
--
--info-am:
--
--install-data-am: install-pkgLTLIBRARIES
--
--install-dvi: install-dvi-am
--
--install-dvi-am:
--
--install-exec-am:
--
--install-html: install-html-am
--
--install-html-am:
--
--install-info: install-info-am
--
--install-info-am:
--
--install-man:
--
--install-pdf: install-pdf-am
--
--install-pdf-am:
--
--install-ps: install-ps-am
--
--install-ps-am:
--
--installcheck-am:
--
--maintainer-clean: maintainer-clean-am
-- -rm -rf ./$(DEPDIR)
-- -rm -f Makefile
--maintainer-clean-am: distclean-am maintainer-clean-generic
--
--mostlyclean: mostlyclean-am
--
--mostlyclean-am: mostlyclean-compile mostlyclean-generic \
-- mostlyclean-libtool
--
--pdf: pdf-am
--
--pdf-am:
--
--ps: ps-am
--
--ps-am:
--
--uninstall-am: uninstall-pkgLTLIBRARIES
--
--.MAKE: install-am install-strip
--
--.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
-- clean-libtool clean-noinstLTLIBRARIES clean-pkgLTLIBRARIES \
-- ctags distclean distclean-compile distclean-generic \
-- distclean-libtool distclean-tags distdir dvi dvi-am html \
-- html-am info info-am install install-am install-data \
-- install-data-am install-dvi install-dvi-am install-exec \
-- install-exec-am install-html install-html-am install-info \
-- install-info-am install-man install-pdf install-pdf-am \
-- install-pkgLTLIBRARIES install-ps install-ps-am install-strip \
-- installcheck installcheck-am installdirs maintainer-clean \
-- maintainer-clean-generic mostlyclean mostlyclean-compile \
-- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-- tags uninstall uninstall-am uninstall-pkgLTLIBRARIES
--
--
--# Tell versions [3.59,3.63) of GNU make to not export all variables.
--# Otherwise a system limit (for SysV at least) may be exceeded.
--.NOEXPORT:
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/oscar/Makefile.mingw
---- pidgin-2.10.7/libpurple/protocols/oscar/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,129 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of liboscar
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = liboscar
--AIM_TARGET = libaim
--ICQ_TARGET = libicq
--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)
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP) \
-- -L.
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = \
-- authorization.c \
-- bstream.c \
-- clientlogin.c \
-- encoding.c \
-- family_admin.c \
-- family_alert.c \
-- family_auth.c \
-- family_bart.c \
-- family_bos.c \
-- family_buddy.c \
-- family_chat.c \
-- family_chatnav.c \
-- family_feedbag.c \
-- family_icbm.c \
-- family_icq.c \
-- family_locate.c \
-- family_oservice.c \
-- family_popup.c \
-- family_stats.c \
-- family_userlookup.c \
-- flap_connection.c \
-- misc.c \
-- msgcookie.c \
-- odc.c \
-- oft.c \
-- oscar.c \
-- oscar_data.c \
-- peer.c \
-- peer_proxy.c \
-- rxhandlers.c \
-- snac.c \
-- tlv.c \
-- userinfo.c \
-- util.c \
-- visibility.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--AIM_C_SRC = libaim.c
--AIM_OBJECTS = $(AIM_C_SRC:%.c=%.o)
--
--ICQ_C_SRC = libicq.c
--ICQ_OBJECTS = $(ICQ_C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lintl \
-- -lws2_32 \
-- -lpurple
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll $(AIM_TARGET).dll $(ICQ_TARGET).dll
--
--install: all $(DLL_INSTALL_DIR)
-- cp $(AIM_TARGET).dll $(ICQ_TARGET).dll $(DLL_INSTALL_DIR)
-- cp $(TARGET).dll $(PURPLE_INSTALL_DIR)
--
--$(OBJECTS): $(PURPLE_CONFIG_H)
--
--$(TARGET).dll.a $(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--out-implib,$(TARGET).dll.a -o $(TARGET).dll
--
--$(AIM_TARGET).dll: $(TARGET).dll.a $(AIM_OBJECTS)
-- $(CC) -shared $(AIM_OBJECTS) $(LIB_PATHS) $(LIBS) -loscar $(DLL_LD_FLAGS) -o $(AIM_TARGET).dll
--
--$(ICQ_TARGET).dll: $(TARGET).dll.a $(ICQ_OBJECTS)
-- $(CC) -shared $(ICQ_OBJECTS) $(LIB_PATHS) $(LIBS) -loscar $(DLL_LD_FLAGS) -o $(ICQ_TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -f $(OBJECTS) $(TARGET).dll $(TARGET).dll.a
-- rm -f $(AIM_OBJECTS) $(AIM_TARGET).dll
-- rm -f $(ICQ_OBJECTS) $(ICQ_TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/misc.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/misc.c
---- pidgin-2.10.7/libpurple/protocols/oscar/misc.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/misc.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,133 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Random stuff. Basically just a few functions for sending
-- * simple SNACs, and then the generic error handler.
-- */
--
--#include "oscar.h"
--
--/*
-- * Generic routine for sending commands.
-- *
-- * I know I can do this in a smarter way...but I'm not thinking straight
-- * right now...
-- *
-- * I had one big function that handled all three cases, but then it broke
-- * and I split it up into three. But then I fixed it. I just never went
-- * back to the single. I don't see any advantage to doing it either way.
-- *
-- */
--void
--aim_genericreq_n(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype)
--{
-- aim_snacid_t snacid = 0x00000000;
--
-- flap_connection_send_snac(od, conn, family, subtype, snacid, NULL);
--}
--
--void
--aim_genericreq_n_snacid(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype)
--{
-- aim_snacid_t snacid;
--
-- snacid = aim_cachesnac(od, family, subtype, 0x0000, NULL, 0);
--
-- flap_connection_send_snac(od, conn, family, subtype, snacid, NULL);
--}
--
--void
--aim_genericreq_l(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype, guint32 *longdata)
--{
-- ByteStream bs;
-- aim_snacid_t snacid;
--
-- if (!longdata)
-- {
-- aim_genericreq_n(od, conn, family, subtype);
-- return;
-- }
--
-- byte_stream_new(&bs, 4);
--
-- snacid = aim_cachesnac(od, family, subtype, 0x0000, NULL, 0);
--
-- byte_stream_put32(&bs, *longdata);
--
-- flap_connection_send_snac(od, conn, family, subtype, snacid, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--/*
-- * Should be generic enough to handle the errors for all groups.
-- *
-- */
--static int
--generror(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- int ret = 0;
-- int error = 0;
-- aim_rxcallback_t userfunc;
-- aim_snac_t *snac2;
--
-- snac2 = aim_remsnac(od, snac->id);
--
-- if (byte_stream_bytes_left(bs))
-- error = byte_stream_get16(bs);
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- ret = userfunc(od, conn, frame, error, snac2 ? snac2->data : NULL);
--
-- if (snac2) {
-- g_free(snac2->data);
-- g_free(snac2);
-- }
--
-- return ret;
--}
--
--static int
--snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
--{
-- if (snac->subtype == 0x0001)
-- return generror(od, conn, mod, frame, snac, bs);
-- else if ((snac->family == 0xffff) && (snac->subtype == 0xffff)) {
-- aim_rxcallback_t userfunc;
--
-- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
-- return userfunc(od, conn, frame);
-- }
--
-- return 0;
--}
--
--int
--misc_modfirst(OscarData *od, aim_module_t *mod)
--{
-- mod->family = 0xffff;
-- mod->version = 0x0000;
-- mod->flags = AIM_MODFLAG_MULTIFAMILY;
-- strncpy(mod->name, "misc", sizeof(mod->name));
-- mod->snachandler = snachandler;
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/msgcookie.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/msgcookie.c
---- pidgin-2.10.7/libpurple/protocols/oscar/msgcookie.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/msgcookie.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,179 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Cookie Caching stuff. Adam wrote this, apparently just some
-- * derivatives of n's SNAC work. I cleaned it up, added comments.
-- *
-- */
--
--/*
-- * I'm assuming that cookies are type-specific. that is, we can have
-- * "1234578" for type 1 and type 2 concurrently. if i'm wrong, then we
-- * lose some error checking. if we assume cookies are not type-specific and are
-- * wrong, we get quirky behavior when cookies step on each others' toes.
-- */
--
--#include "oscar.h"
--
--/**
-- * aim_cachecookie - appends a cookie to the cookie list
-- *
-- * if cookie->cookie for type cookie->type is found, updates the
-- * ->addtime of the found structure; otherwise adds the given cookie
-- * to the cache
-- *
-- * @param od session to add to
-- * @param cookie pointer to struct to append
-- * @return returns -1 on error, 0 on append, 1 on update. the cookie you pass
-- * in may be free'd, so don't count on its value after calling this!
-- */
--int aim_cachecookie(OscarData *od, IcbmCookie *cookie)
--{
-- IcbmCookie *newcook;
--
-- if (!od || !cookie)
-- return -EINVAL;
--
-- newcook = aim_checkcookie(od, cookie->cookie, cookie->type);
--
-- if (newcook == cookie) {
-- newcook->addtime = time(NULL);
-- return 1;
-- } else if (newcook)
-- aim_cookie_free(od, newcook);
--
-- cookie->addtime = time(NULL);
--
-- cookie->next = od->msgcookies;
-- od->msgcookies = cookie;
--
-- return 0;
--}
--
--/**
-- * aim_uncachecookie - grabs a cookie from the cookie cache (removes it from the list)
-- *
-- * takes a cookie string and a cookie type and finds the cookie struct associated with that duple, removing it from the cookie list ikn the process.
-- *
-- * @param od session to grab cookie from
-- * @param cookie cookie string to look for
-- * @param type cookie type to look for
-- * @return if found, returns the struct; if none found (or on error), returns NULL:
-- */
--IcbmCookie *aim_uncachecookie(OscarData *od, guint8 *cookie, int type)
--{
-- IcbmCookie *cur, **prev;
--
-- if (!cookie || !od->msgcookies)
-- return NULL;
--
-- for (prev = &od->msgcookies; (cur = *prev); ) {
-- if ((cur->type == type) &&
-- (memcmp(cur->cookie, cookie, 8) == 0)) {
-- *prev = cur->next;
-- return cur;
-- }
-- prev = &cur->next;
-- }
--
-- return NULL;
--}
--
--/**
-- * aim_mkcookie - generate an IcbmCookie *struct from a cookie string, a type, and a data pointer.
-- *
-- * @param c pointer to the cookie string array
-- * @param type cookie type to use
-- * @param data data to be cached with the cookie
-- * @return returns NULL on error, a pointer to the newly-allocated
-- * cookie on success.
-- */
--IcbmCookie *aim_mkcookie(guint8 *c, int type, void *data)
--{
-- IcbmCookie *cookie;
--
-- if (!c)
-- return NULL;
--
-- cookie = g_new0(IcbmCookie, 1);
--
-- cookie->data = data;
-- cookie->type = type;
-- memcpy(cookie->cookie, c, 8);
--
-- return cookie;
--}
--
--/**
-- * aim_checkcookie - check to see if a cookietuple has been cached
-- *
-- * @param od session to check for the cookie in
-- * @param cookie pointer to the cookie string array
-- * @param type type of the cookie to look for
-- * @return returns a pointer to the cookie struct (still in the list)
-- * on success; returns NULL on error/not found
-- */
--
--IcbmCookie *aim_checkcookie(OscarData *od, const guint8 *cookie, const int type)
--{
-- IcbmCookie *cur;
--
-- for (cur = od->msgcookies; cur; cur = cur->next) {
-- if ((cur->type == type) &&
-- (memcmp(cur->cookie, cookie, 8) == 0))
-- return cur;
-- }
--
-- return NULL;
--}
--
--/**
-- * aim_cookie_free - free an IcbmCookie struct
-- *
-- * this function removes the cookie *cookie from the list of cookies
-- * in od, and then frees all memory associated with it. including
-- * its data! if you want to use the private data after calling this,
-- * make sure you copy it first.
-- *
-- * @param od session to remove the cookie from
-- * @param cookie the address of a pointer to the cookie struct to remove
-- * @return returns -1 on error, 0 on success.
-- *
-- */
--int aim_cookie_free(OscarData *od, IcbmCookie *cookie)
--{
-- IcbmCookie *cur, **prev;
--
-- if (!od || !cookie)
-- return -EINVAL;
--
-- for (prev = &od->msgcookies; (cur = *prev); ) {
-- if (cur == cookie)
-- *prev = cur->next;
-- else
-- prev = &cur->next;
-- }
--
-- g_free(cookie->data);
-- g_free(cookie);
--
-- return 0;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/odc.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/odc.c
---- pidgin-2.10.7/libpurple/protocols/oscar/odc.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/odc.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,625 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/* From the oscar PRPL */
--#include "encoding.h"
--#include "oscar.h"
--#include "peer.h"
--
--/* From Purple */
--#include "conversation.h"
--#include "imgstore.h"
--#include "util.h"
--
--#define DIRECTIM_MAX_FILESIZE 52428800
--
--/**
-- * Free any ODC related data and print a message to the conversation
-- * window based on conn->disconnect_reason.
-- */
--void
--peer_odc_close(PeerConnection *conn)
--{
-- gchar *tmp;
--
-- if (conn->disconnect_reason == OSCAR_DISCONNECT_REMOTE_CLOSED)
-- tmp = g_strdup(_("The remote user has closed the connection."));
-- else if (conn->disconnect_reason == OSCAR_DISCONNECT_REMOTE_REFUSED)
-- tmp = g_strdup(_("The remote user has declined your request."));
-- else if (conn->disconnect_reason == OSCAR_DISCONNECT_LOST_CONNECTION)
-- tmp = g_strdup_printf(_("Lost connection with the remote user:<br>%s"),
-- conn->error_message);
-- else if (conn->disconnect_reason == OSCAR_DISCONNECT_INVALID_DATA)
-- tmp = g_strdup(_("Received invalid data on connection with remote user."));
-- else if (conn->disconnect_reason == OSCAR_DISCONNECT_COULD_NOT_CONNECT)
-- tmp = g_strdup(_("Unable to establish a connection with the remote user."));
-- else
-- /*
-- * We shouldn't print a message for some disconnect_reasons.
-- * Like OSCAR_DISCONNECT_LOCAL_CLOSED.
-- */
-- tmp = NULL;
--
-- if (tmp != NULL)
-- {
-- PurpleAccount *account;
-- PurpleConversation *conv;
--
-- account = purple_connection_get_account(conn->od->gc);
-- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn);
-- purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));
-- g_free(tmp);
-- }
--
-- if (conn->frame != NULL)
-- {
-- OdcFrame *frame;
-- frame = conn->frame;
-- g_free(frame->payload.data);
-- g_free(frame);
-- }
--}
--
--/**
-- * Write the given OdcFrame to a ByteStream and send it out
-- * on the established PeerConnection.
-- */
--static void
--peer_odc_send(PeerConnection *conn, OdcFrame *frame)
--{
-- PurpleAccount *account;
-- const char *username;
-- size_t length;
-- ByteStream bs;
--
-- purple_debug_info("oscar", "Outgoing ODC frame to %s with "
-- "type=0x%04x, flags=0x%04x, payload length=%" G_GSIZE_FORMAT "\n",
-- conn->bn, frame->type, frame->flags, frame->payload.len);
--
-- account = purple_connection_get_account(conn->od->gc);
-- username = purple_account_get_username(account);
-- memcpy(frame->bn, username, strlen(username));
-- memcpy(frame->cookie, conn->cookie, 8);
--
-- length = 76;
-- byte_stream_new(&bs, length + frame->payload.len);
-- byte_stream_putraw(&bs, conn->magic, 4);
-- byte_stream_put16(&bs, length);
-- byte_stream_put16(&bs, frame->type);
-- byte_stream_put16(&bs, frame->subtype);
-- byte_stream_put16(&bs, 0x0000);
-- byte_stream_putraw(&bs, frame->cookie, 8);
-- byte_stream_put16(&bs, 0x0000);
-- byte_stream_put16(&bs, 0x0000);
-- byte_stream_put16(&bs, 0x0000);
-- byte_stream_put16(&bs, 0x0000);
-- byte_stream_put32(&bs, frame->payload.len);
-- byte_stream_put16(&bs, frame->encoding);
-- byte_stream_put16(&bs, 0x0000);
-- byte_stream_put16(&bs, 0x0000);
-- byte_stream_put16(&bs, frame->flags);
-- byte_stream_put16(&bs, 0x0000);
-- byte_stream_put16(&bs, 0x0000);
-- byte_stream_putraw(&bs, frame->bn, 32);
-- byte_stream_putraw(&bs, frame->payload.data, frame->payload.len);
--
-- peer_connection_send(conn, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--/**
-- * Send a very basic ODC frame (which contains the cookie) so that the
-- * remote user can verify that we are the person they were expecting.
-- * If we made an outgoing connection to then remote user, then we send
-- * this immediately. If the remote user connected to us, then we wait
-- * for the other person to send this to us, then we send one to them.
-- */
--void
--peer_odc_send_cookie(PeerConnection *conn)
--{
-- OdcFrame frame;
--
-- memset(&frame, 0, sizeof(OdcFrame));
-- frame.type = 0x0001;
-- frame.subtype = 0x0006;
-- frame.flags = 0x0060; /* Maybe this means "we're sending the cookie"? */
--
-- peer_odc_send(conn, &frame);
--}
--
--/**
-- * Send client-to-client typing notification over an established direct connection.
-- */
--void
--peer_odc_send_typing(PeerConnection *conn, PurpleTypingState typing)
--{
-- OdcFrame frame;
--
-- memset(&frame, 0, sizeof(OdcFrame));
-- frame.type = 0x0001;
-- frame.subtype = 0x0006;
-- if (typing == PURPLE_TYPING)
-- frame.flags = 0x0002 | 0x0008;
-- else if (typing == PURPLE_TYPED)
-- frame.flags = 0x0002 | 0x0004;
-- else
-- frame.flags = 0x0002;
--
-- peer_odc_send(conn, &frame);
--}
--
--/**
-- * Send client-to-client IM over an established direct connection.
-- * To send a direct IM, call this just like you would aim_send_im.
-- *
-- * @param conn The already-connected ODC connection.
-- * @param msg Null-terminated string to send.
-- * @param len The length of the message to send, including binary data.
-- * @param encoding See the AIM_CHARSET_* defines in oscar.h
-- * @param autoreply TRUE if this is any auto-reply.
-- */
--void
--peer_odc_send_im(PeerConnection *conn, const char *msg, int len, int encoding, gboolean autoreply)
--{
-- OdcFrame frame;
--
-- g_return_if_fail(msg != NULL);
-- g_return_if_fail(len > 0);
--
-- memset(&frame, 0, sizeof(OdcFrame));
-- frame.type = 0x0001;
-- frame.subtype = 0x0006;
-- frame.payload.len = len;
-- frame.encoding = encoding;
-- frame.flags = autoreply;
-- byte_stream_new(&frame.payload, len);
-- byte_stream_putraw(&frame.payload, (guint8 *)msg, len);
--
-- peer_odc_send(conn, &frame);
--
-- g_free(frame.payload.data);
--}
--
--struct embedded_data
--{
-- size_t size;
-- const guint8 *data;
--};
--
--/**
-- * This is called after a direct IM has been received in its entirety. This
-- * function is passed a long chunk of data which contains the IM with any
-- * data chunks (images) appended to it.
-- *
-- * This function rips out all the data chunks and creates an imgstore for
-- * each one. In order to do this, it first goes through the IM and takes
-- * out all the IMG tags. When doing so, it rewrites the original IMG tag
-- * with one compatible with the imgstore Purple core code. For each one, we
-- * then read in chunks of data from the end of the message and actually
-- * create the img store using the given data.
-- *
-- * For somewhat easy reference, here's a sample message
-- * (with added whitespace):
-- *
-- * <HTML><BODY BGCOLOR="#ffffff">
-- * <FONT LANG="0">
-- * This is a really stupid picture:<BR>
-- * <IMG SRC="Sample.jpg" ID="1" WIDTH="283" HEIGHT="212" DATASIZE="9894"><BR>
-- * Yeah it is<BR>
-- * Here is another one:<BR>
-- * <IMG SRC="Soap Bubbles.bmp" ID="2" WIDTH="256" HEIGHT="256" DATASIZE="65978">
-- * </FONT>
-- * </BODY></HTML>
-- * <BINARY>
-- * <DATA ID="1" SIZE="9894">datadatadatadata</DATA>
-- * <DATA ID="2" SIZE="65978">datadatadatadata</DATA>
-- * </BINARY>
-- */
--static void
--peer_odc_handle_payload(PeerConnection *conn, const char *msg, size_t len, int encoding, gboolean autoreply)
--{
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- const char *msgend, *binary_start, *dataend;
-- const char *tmp, *start, *end, *idstr, *src, *sizestr;
-- GData *attributes;
-- GHashTable *embedded_datas;
-- struct embedded_data *embedded_data;
-- GSList *images;
-- gchar *utf8;
-- GString *newmsg;
-- PurpleMessageFlags imflags;
--
-- gc = conn->od->gc;
-- account = purple_connection_get_account(gc);
--
-- dataend = msg + len;
--
-- /*
-- * Create a hash table containing references to each embedded
-- * data chunk. The key is the "ID" and the value is an
-- * embedded_data struct.
-- */
-- embedded_datas = g_hash_table_new_full(g_direct_hash,
-- g_direct_equal, NULL, g_free);
--
-- /*
-- * Create an index of any binary chunks. If we run into any
-- * problems while parsing the binary data section then we stop
-- * parsing it, and the local user will see broken image icons.
-- */
-- /* TODO: Use a length argument when looking for the <binary> tag! */
-- binary_start = purple_strcasestr(msg, "<binary>");
-- if (binary_start == NULL)
-- msgend = dataend;
-- else
-- {
-- msgend = binary_start;
--
-- /* Move our pointer to immediately after the <binary> tag */
-- tmp = binary_start + 8;
--
-- /* The embedded binary markup has a mimimum length of 29 bytes */
-- /* TODO: Use a length argument when looking for the <data> tag! */
-- while ((tmp + 29 <= dataend) &&
-- purple_markup_find_tag("data", tmp, &start, &tmp, &attributes))
-- {
-- unsigned int id;
-- size_t size;
--
-- /* Move the binary pointer from ">" to the start of the data */
-- tmp++;
--
-- /* Get the ID */
-- idstr = g_datalist_get_data(&attributes, "id");
-- if (idstr == NULL)
-- {
-- g_datalist_clear(&attributes);
-- break;
-- }
-- id = atoi(idstr);
--
-- /* Get the size */
-- sizestr = g_datalist_get_data(&attributes, "size");
-- if (sizestr == NULL)
-- {
-- g_datalist_clear(&attributes);
-- break;
-- }
-- size = atol(sizestr);
--
-- g_datalist_clear(&attributes);
--
-- if ((size > 0) && (tmp + size > dataend))
-- break;
--
-- embedded_data = g_new(struct embedded_data, 1);
-- embedded_data->size = size;
-- embedded_data->data = (const guint8 *)tmp;
-- tmp += size;
--
-- /* Skip past the closing </data> tag */
-- if (g_ascii_strncasecmp(tmp, "</data>", 7))
-- {
-- g_free(embedded_data);
-- break;
-- }
-- tmp += 7;
--
-- g_hash_table_insert(embedded_datas,
-- GINT_TO_POINTER(id), embedded_data);
-- }
-- }
--
-- /*
-- * Loop through the message, replacing OSCAR img tags with the
-- * equivalent Purple img tag.
-- */
-- images = NULL;
-- newmsg = g_string_new("");
-- tmp = msg;
-- while (purple_markup_find_tag("img", tmp, &start, &end, &attributes))
-- {
-- int imgid = 0;
--
-- idstr = g_datalist_get_data(&attributes, "id");
-- src = g_datalist_get_data(&attributes, "src");
-- sizestr = g_datalist_get_data(&attributes, "datasize");
--
-- if ((idstr != NULL) && (src != NULL) && (sizestr!= NULL))
-- {
-- unsigned int id;
-- size_t size;
--
-- id = atoi(idstr);
-- size = atol(sizestr);
-- embedded_data = g_hash_table_lookup(embedded_datas,
-- GINT_TO_POINTER(id));
--
-- if ((embedded_data != NULL) && (embedded_data->size == size))
-- {
-- imgid = purple_imgstore_add_with_id(g_memdup(embedded_data->data, size), size, src);
--
-- /* Record the image number */
-- images = g_slist_append(images, GINT_TO_POINTER(imgid));
-- }
-- }
--
-- /* Delete the attribute list */
-- g_datalist_clear(&attributes);
--
-- /* Append the message up to the tag */
-- utf8 = oscar_decode_im(account, conn->bn, encoding, tmp, start - tmp);
-- if (utf8 != NULL) {
-- g_string_append(newmsg, utf8);
-- g_free(utf8);
-- }
--
-- if (imgid != 0)
-- {
-- /* Write the new image tag */
-- g_string_append_printf(newmsg, "<IMG ID=\"%d\">", imgid);
-- }
--
-- /* Continue from the end of the tag */
-- tmp = end + 1;
-- }
--
-- /* Append any remaining message data */
-- if (tmp <= msgend)
-- {
-- utf8 = oscar_decode_im(account, conn->bn, encoding, tmp, msgend - tmp);
-- if (utf8 != NULL) {
-- g_string_append(newmsg, utf8);
-- g_free(utf8);
-- }
-- }
--
-- /* Display the message we received */
-- imflags = 0;
-- if (images != NULL)
-- imflags |= PURPLE_MESSAGE_IMAGES;
-- if (autoreply)
-- imflags |= PURPLE_MESSAGE_AUTO_RESP;
-- serv_got_im(gc, conn->bn, newmsg->str, imflags, time(NULL));
-- g_string_free(newmsg, TRUE);
--
-- /* unref any images we allocated */
-- if (images)
-- {
-- GSList *l;
-- for (l = images; l != NULL; l = l->next)
-- purple_imgstore_unref_by_id(GPOINTER_TO_INT(l->data));
-- g_slist_free(images);
-- }
--
-- /* Delete our list of pointers to embedded images */
-- g_hash_table_destroy(embedded_datas);
--}
--
--/**
-- * This is a purple_input_add() watcher callback function for reading
-- * direct IM payload data. "Payload data" is always an IM and
-- * maybe some embedded images or files or something. The actual
-- * ODC frame is read using peer_connection_recv_cb(). We temporarily
-- * switch to this watcher callback ONLY to read the payload, and we
-- * switch back once we're done.
-- */
--static void
--peer_odc_recv_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- PeerConnection *conn;
-- OdcFrame *frame;
-- ByteStream *bs;
-- gssize read;
--
-- conn = data;
-- frame = conn->frame;
-- bs = &frame->payload;
--
-- /* Read data into the temporary buffer until it is complete */
-- read = recv(conn->fd,
-- &bs->data[bs->offset],
-- bs->len - bs->offset,
-- 0);
--
-- /* Check if the remote user closed the connection */
-- if (read == 0)
-- {
-- peer_connection_destroy(conn, OSCAR_DISCONNECT_REMOTE_CLOSED, NULL);
-- return;
-- }
--
-- if (read < 0)
-- {
-- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-- /* No worries */
-- return;
--
-- peer_connection_destroy(conn,
-- OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno));
-- return;
-- }
--
-- bs->offset += read;
-- if (bs->offset < bs->len)
-- /* Waiting for more data to arrive */
-- return;
--
-- /* We have a complete ODC/OFT frame! Handle it and continue reading */
-- byte_stream_rewind(bs);
-- peer_odc_handle_payload(conn, (const char *)bs->data,
-- bs->len, frame->encoding, frame->flags & 0x0001);
-- g_free(bs->data);
-- bs->data = NULL;
-- g_free(frame);
-- conn->frame = NULL;
--
-- purple_input_remove(conn->watcher_incoming);
-- conn->watcher_incoming = purple_input_add(conn->fd,
-- PURPLE_INPUT_READ, peer_connection_recv_cb, conn);
--}
--
--/**
-- * Handle an incoming OdcFrame. If there is a payload associated
-- * with this frame, then we remove the old watcher and add the
-- * ODC watcher to read in the payload.
-- */
--void
--peer_odc_recv_frame(PeerConnection *conn, ByteStream *bs)
--{
-- PurpleConnection *gc;
-- OdcFrame *frame;
--
-- gc = conn->od->gc;
--
-- frame = g_new0(OdcFrame, 1);
-- frame->type = byte_stream_get16(bs);
-- frame->subtype = byte_stream_get16(bs);
-- byte_stream_advance(bs, 2);
-- byte_stream_getrawbuf(bs, frame->cookie, 8);
-- byte_stream_advance(bs, 8);
-- frame->payload.len = byte_stream_get32(bs);
-- frame->encoding = byte_stream_get16(bs);
-- byte_stream_advance(bs, 4);
-- frame->flags = byte_stream_get16(bs);
-- byte_stream_advance(bs, 4);
-- byte_stream_getrawbuf(bs, frame->bn, 32);
--
-- purple_debug_info("oscar", "Incoming ODC frame from %s with "
-- "type=0x%04x, flags=0x%04x, payload length=%" G_GSIZE_FORMAT "\n",
-- frame->bn, frame->type, frame->flags, frame->payload.len);
--
-- if (!conn->ready)
-- {
-- /*
-- * We need to verify the cookie so that we know we are
-- * connected to our friend and not a malicious middle man.
-- */
--
-- PurpleAccount *account;
-- PurpleConversation *conv;
--
-- if (conn->flags & PEER_CONNECTION_FLAG_IS_INCOMING)
-- {
-- if (memcmp(conn->cookie, frame->cookie, 8))
-- {
-- /*
-- * Oh no! The user that connected to us did not send
-- * the correct cookie! They are not our friend. Go try
-- * to accept another connection?
-- */
-- purple_debug_info("oscar", "Received an incorrect cookie. "
-- "Closing connection.\n");
-- peer_connection_destroy(conn,
-- OSCAR_DISCONNECT_INVALID_DATA, NULL);
-- g_free(frame);
-- return;
-- }
--
-- /*
-- * Ok, we know they are legit. Now be courteous and
-- * send them our cookie. Note: This doesn't seem
-- * to be necessary, but it also doesn't seem to hurt.
-- */
-- peer_odc_send_cookie(conn);
-- }
--
-- conn->ready = TRUE;
--
-- /*
-- * If they connected to us then close the listener socket
-- * and send them our cookie.
-- */
-- if (conn->listenerfd != -1)
-- {
-- close(conn->listenerfd);
-- conn->listenerfd = -1;
-- }
--
-- /* Tell the local user that we are connected */
-- account = purple_connection_get_account(gc);
-- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn);
-- purple_conversation_write(conv, NULL, _("Direct IM established"),
-- PURPLE_MESSAGE_SYSTEM, time(NULL));
-- }
--
-- if ((frame->type != 0x0001) && (frame->subtype != 0x0006))
-- {
-- purple_debug_info("oscar", "Unknown ODC frame type 0x%04hx, "
-- "subtype 0x%04hx.\n", frame->type, frame->subtype);
-- g_free(frame);
-- return;
-- }
--
-- if (frame->flags & 0x0008)
-- {
-- /* I had to leave this. It's just too funny. It reminds me of my sister. */
-- purple_debug_info("oscar", "ohmigod! %s has started typing "
-- "(DirectIM). He's going to send you a message! "
-- "*squeal*\n", conn->bn);
-- serv_got_typing(gc, conn->bn, 0, PURPLE_TYPING);
-- }
-- else if (frame->flags & 0x0004)
-- {
-- serv_got_typing(gc, conn->bn, 0, PURPLE_TYPED);
-- }
-- else
-- {
-- serv_got_typing_stopped(gc, conn->bn);
-- }
--
-- if (frame->payload.len > 0)
-- {
-- if (frame->payload.len > DIRECTIM_MAX_FILESIZE)
-- {
-- gchar *tmp, *size1, *size2;
-- PurpleAccount *account;
-- PurpleConversation *conv;
--
-- size1 = purple_str_size_to_units(frame->payload.len);
-- size2 = purple_str_size_to_units(DIRECTIM_MAX_FILESIZE);
-- tmp = g_strdup_printf(_("%s tried to send you a %s file, but we only allow files up to %s over Direct IM. Try using file transfer instead.\n"), conn->bn, size1, size2);
-- g_free(size1);
-- g_free(size2);
--
-- account = purple_connection_get_account(conn->od->gc);
-- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn);
-- purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));
-- g_free(tmp);
--
-- peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);
-- g_free(frame);
-- return;
-- }
--
-- /* We have payload data! Switch to the ODC watcher to read it. */
-- frame->payload.data = g_new(guint8, frame->payload.len);
-- frame->payload.offset = 0;
-- conn->frame = frame;
-- purple_input_remove(conn->watcher_incoming);
-- conn->watcher_incoming = purple_input_add(conn->fd,
-- PURPLE_INPUT_READ, peer_odc_recv_cb, conn);
-- return;
-- }
--
-- g_free(frame);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/oft.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oft.c
---- pidgin-2.10.7/libpurple/protocols/oscar/oft.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oft.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,823 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * I feel like this is a good place to explain OFT, so I'm going to
-- * do just that. Each OFT packet has a header type. I guess this
-- * is pretty similar to the subtype of a SNAC packet. The type
-- * basically tells the other client the meaning of the OFT packet.
-- * There are two distinct types of file transfer, which I usually
-- * call "sendfile" and "getfile." Sendfile is when you send a file
-- * to another AIM user. Getfile is when you share a group of files,
-- * and other users request that you send them the files.
-- *
-- * A typical sendfile file transfer goes like this:
-- * 1) Sender sends a channel 2 ICBM telling the other user that
-- * we want to send them a file. At the same time, we open a
-- * listener socket (this should be done before sending the
-- * ICBM) on some port, and wait for them to connect to us.
-- * The ICBM we sent should contain our IP address and the port
-- * number that we're listening on.
-- * 2) The receiver connects to the sender on the given IP address
-- * and port. After the connection is established, the receiver
-- * sends an ICBM signifying that we are ready and waiting.
-- * 3) The sender sends an OFT PROMPT message over the OFT
-- * connection.
-- * 4) The receiver of the file sends back an exact copy of this
-- * OFT packet, except the cookie is filled in with the cookie
-- * from the ICBM. I think this might be an attempt to verify
-- * that the user that is connected is actually the guy that
-- * we sent the ICBM to. Oh, I've been calling this the ACK.
-- * 5) The sender starts sending raw data across the connection
-- * until the entire file has been sent.
-- * 6) The receiver knows the file is finished because the sender
-- * sent the file size in an earlier OFT packet. So then the
-- * receiver sends the DONE thingy (after filling in the
-- * "received" checksum and size) and closes the connection.
-- */
--
--#include "oscar.h"
--#include "peer.h"
--
--#include "util.h"
--
--#define CHECKSUM_BUFFER_SIZE 256 * 1024
--
--struct _ChecksumData
--{
-- PeerConnection *conn;
-- PurpleXfer *xfer;
-- GSourceFunc callback;
-- size_t size;
-- guint32 checksum;
-- size_t total;
-- FILE *file;
-- guint8 buffer[CHECKSUM_BUFFER_SIZE];
-- guint timer;
--};
--
--void
--peer_oft_checksum_destroy(ChecksumData *checksum_data)
--{
-- checksum_data->conn->checksum_data = NULL;
-- fclose(checksum_data->file);
-- if (checksum_data->timer > 0)
-- purple_timeout_remove(checksum_data->timer);
-- g_free(checksum_data);
--}
--
--/**
-- * Calculate oft checksum of buffer
-- *
-- * Prevcheck should be 0xFFFF0000 when starting a checksum of a file. The
-- * checksum is kind of a rolling checksum thing, so each time you get bytes
-- * of a file you just call this puppy and it updates the checksum. You can
-- * calculate the checksum of an entire file by calling this in a while or a
-- * for loop, or something.
-- *
-- * Thanks to Graham Booker for providing this improved checksum routine,
-- * which is simpler and should be more accurate than Josh Myer's original
-- * code. -- wtm
-- *
-- * This algorithm works every time I have tried it. The other fails
-- * sometimes. So, AOL who thought this up? It has got to be the weirdest
-- * checksum I have ever seen.
-- *
-- * @param buffer Buffer of data to checksum. Man I'd like to buff her...
-- * @param bufsize Size of buffer.
-- * @param prevchecksum Previous checksum.
-- * @param odd Whether an odd number of bytes have been processed before this call
-- */
--static guint32
--peer_oft_checksum_chunk(const guint8 *buffer, int bufferlen, guint32 prevchecksum, int odd)
--{
-- guint32 checksum, oldchecksum;
-- int i = 0;
-- unsigned short val;
--
-- checksum = (prevchecksum >> 16) & 0xffff;
-- if (odd)
-- {
-- /*
-- * This is one hell of a hack, but it should always work.
-- * Essentially, I am reindexing the array so that index 1
-- * is the first element. Since the odd and even bytes are
-- * detected by the index number.
-- */
-- i = 1;
-- bufferlen++;
-- buffer--;
-- }
-- for (; i < bufferlen; i++)
-- {
-- oldchecksum = checksum;
-- if (i & 1)
-- val = buffer[i];
-- else
-- val = buffer[i] << 8;
-- checksum -= val;
-- /*
-- * The following appears to be necessary.... It happens
-- * every once in a while and the checksum doesn't fail.
-- */
-- if (checksum > oldchecksum)
-- checksum--;
-- }
-- checksum = ((checksum & 0x0000ffff) + (checksum >> 16));
-- checksum = ((checksum & 0x0000ffff) + (checksum >> 16));
-- return checksum << 16;
--}
--
--static gboolean
--peer_oft_checksum_file_piece(gpointer data)
--{
-- ChecksumData *checksum_data;
-- gboolean repeat;
--
-- checksum_data = data;
-- repeat = FALSE;
--
-- if (checksum_data->total < checksum_data->size)
-- {
-- size_t bytes = MIN(CHECKSUM_BUFFER_SIZE,
-- checksum_data->size - checksum_data->total);
--
-- bytes = fread(checksum_data->buffer, 1, bytes, checksum_data->file);
-- if (bytes != 0)
-- {
-- checksum_data->checksum = peer_oft_checksum_chunk(checksum_data->buffer, bytes, checksum_data->checksum, checksum_data->total & 1);
-- checksum_data->total += bytes;
-- repeat = TRUE;
-- }
-- }
--
-- if (!repeat)
-- {
-- purple_debug_info("oscar", "Checksum of %s calculated\n",
-- purple_xfer_get_local_filename(checksum_data->xfer));
-- if (checksum_data->callback != NULL)
-- checksum_data->callback(checksum_data);
-- peer_oft_checksum_destroy(checksum_data);
-- }
--
-- return repeat;
--}
--
--/**
-- * Calculate oft checksum of a file in a series of calls to
-- * peer_oft_checksum_file_piece(). We do it this way because
-- * calculating the checksum on large files can take a long time,
-- * and we want to return control to the UI so that the application
-- * doesn't appear completely frozen.
-- *
-- * @param conn The connection used for this file transfer.
-- * @param xfer The file transfer needing this checksum.
-- * @param callback The function to call upon calculation of the checksum.
-- * @param size The maximum size to check.
-- */
--
--static void
--peer_oft_checksum_file(PeerConnection *conn, PurpleXfer *xfer, GSourceFunc callback, size_t size)
--{
-- ChecksumData *checksum_data;
--
-- purple_debug_info("oscar", "Calculating checksum of %s\n",
-- purple_xfer_get_local_filename(xfer));
--
-- checksum_data = g_malloc0(sizeof(ChecksumData));
-- checksum_data->conn = conn;
-- checksum_data->xfer = xfer;
-- checksum_data->callback = callback;
-- checksum_data->size = size;
-- checksum_data->checksum = 0xffff0000;
-- checksum_data->file = g_fopen(purple_xfer_get_local_filename(xfer), "rb");
--
-- if (checksum_data->file == NULL)
-- {
-- purple_debug_error("oscar", "Unable to open %s for checksumming: %s\n",
-- purple_xfer_get_local_filename(xfer), g_strerror(errno));
-- callback(checksum_data);
-- g_free(checksum_data);
-- }
-- else
-- {
-- checksum_data->timer = purple_timeout_add(10,
-- peer_oft_checksum_file_piece, checksum_data);
-- conn->checksum_data = checksum_data;
-- }
--}
--
--static void
--peer_oft_copy_xfer_data(PeerConnection *conn, OftFrame *frame)
--{
-- g_free(conn->xferdata.name);
--
-- memcpy(&(conn->xferdata), frame, sizeof(OftFrame));
-- conn->xferdata.name = g_memdup(frame->name, frame->name_length);
--}
--
--/**
-- * Free any OFT related data.
-- */
--void
--peer_oft_close(PeerConnection *conn)
--{
-- /*
-- * If cancelled by local user, and we're receiving a file, and
-- * we're not connected/ready then send an ICBM cancel message.
-- */
-- if ((purple_xfer_get_status(conn->xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL) &&
-- !conn->ready)
-- {
-- aim_im_sendch2_cancel(conn);
-- }
--
-- if (conn->sending_data_timer != 0)
-- {
-- purple_timeout_remove(conn->sending_data_timer);
-- conn->sending_data_timer = 0;
-- }
--}
--
--/**
-- * Write the given OftFrame to a ByteStream and send it out
-- * on the established PeerConnection.
-- */
--static void
--peer_oft_send(PeerConnection *conn, OftFrame *frame)
--{
-- size_t length;
-- ByteStream bs;
--
-- length = 192 + frame->name_length;
-- byte_stream_new(&bs, length);
-- byte_stream_putraw(&bs, conn->magic, 4);
-- byte_stream_put16(&bs, length);
-- byte_stream_put16(&bs, frame->type);
-- byte_stream_putraw(&bs, frame->cookie, 8);
-- byte_stream_put16(&bs, frame->encrypt);
-- byte_stream_put16(&bs, frame->compress);
-- byte_stream_put16(&bs, frame->totfiles);
-- byte_stream_put16(&bs, frame->filesleft);
-- byte_stream_put16(&bs, frame->totparts);
-- byte_stream_put16(&bs, frame->partsleft);
-- byte_stream_put32(&bs, frame->totsize);
-- byte_stream_put32(&bs, frame->size);
-- byte_stream_put32(&bs, frame->modtime);
-- byte_stream_put32(&bs, frame->checksum);
-- byte_stream_put32(&bs, frame->rfrcsum);
-- byte_stream_put32(&bs, frame->rfsize);
-- byte_stream_put32(&bs, frame->cretime);
-- byte_stream_put32(&bs, frame->rfcsum);
-- byte_stream_put32(&bs, frame->nrecvd);
-- byte_stream_put32(&bs, frame->recvcsum);
-- byte_stream_putraw(&bs, frame->idstring, 32);
-- byte_stream_put8(&bs, frame->flags);
-- byte_stream_put8(&bs, frame->lnameoffset);
-- byte_stream_put8(&bs, frame->lsizeoffset);
-- byte_stream_putraw(&bs, frame->dummy, 69);
-- byte_stream_putraw(&bs, frame->macfileinfo, 16);
-- byte_stream_put16(&bs, frame->nencode);
-- byte_stream_put16(&bs, frame->nlanguage);
-- /*
-- * The name can be more than 64 characters, but if it is less than
-- * 64 characters it is padded with NULLs.
-- */
-- byte_stream_putraw(&bs, frame->name, frame->name_length);
--
-- peer_connection_send(conn, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--void
--peer_oft_send_prompt(PeerConnection *conn)
--{
-- conn->xferdata.type = PEER_TYPE_PROMPT;
-- peer_oft_send(conn, &conn->xferdata);
--}
--
--static void
--peer_oft_send_ack(PeerConnection *conn)
--{
-- conn->xferdata.type = PEER_TYPE_ACK;
--
-- /* Fill in the cookie */
-- memcpy(conn->xferdata.cookie, conn->cookie, 8);
--
-- peer_oft_send(conn, &conn->xferdata);
--}
--
--static void
--peer_oft_send_resume_accept(PeerConnection *conn)
--{
-- conn->xferdata.type = PEER_TYPE_RESUMEACCEPT;
--
-- /* Fill in the cookie */
-- memcpy(conn->xferdata.cookie, conn->cookie, 8);
--
-- peer_oft_send(conn, &conn->xferdata);
--}
--
--static void
--peer_oft_send_done(PeerConnection *conn)
--{
-- conn->xferdata.type = PEER_TYPE_DONE;
-- conn->xferdata.rfrcsum = 0xffff0000;
-- conn->xferdata.nrecvd = purple_xfer_get_bytes_sent(conn->xfer);
-- peer_oft_send(conn, &conn->xferdata);
--}
--
--/**
-- * This function exists so that we don't remove the outgoing
-- * data watcher while we're still sending data. In most cases
-- * any data we're sending will be instantly wisked away to a TCP
-- * buffer maintained by our operating system... but we want to
-- * make sure the core doesn't start sending file data while
-- * we're still sending OFT frame data. That would be bad.
-- */
--static gboolean
--start_transfer_when_done_sending_data(gpointer data)
--{
-- PeerConnection *conn;
--
-- conn = data;
--
-- if (purple_circ_buffer_get_max_read(conn->buffer_outgoing) == 0)
-- {
-- conn->sending_data_timer = 0;
-- conn->xfer->fd = conn->fd;
-- conn->fd = -1;
-- purple_xfer_start(conn->xfer, conn->xfer->fd, NULL, 0);
-- return FALSE;
-- }
--
-- return TRUE;
--}
--
--/**
-- * This function is similar to the above function, except instead
-- * of starting the xfer it will destroy the connection. This is
-- * used when you want to send one final message across the peer
-- * connection, and then close everything.
-- */
--static gboolean
--destroy_connection_when_done_sending_data(gpointer data)
--{
-- PeerConnection *conn;
--
-- conn = data;
--
-- if (purple_circ_buffer_get_max_read(conn->buffer_outgoing) == 0)
-- {
-- conn->sending_data_timer = 0;
-- peer_connection_destroy(conn, conn->disconnect_reason, NULL);
-- return FALSE;
-- }
--
-- return TRUE;
--}
--
--/*
-- * This is called when a buddy sends us some file info. This happens when they
-- * are sending a file to you, and you have just established a connection to them.
-- * You should send them the exact same info except use the real cookie. We also
-- * get like totally ready to like, receive the file, kay?
-- */
--static void
--peer_oft_recv_frame_prompt(PeerConnection *conn, OftFrame *frame)
--{
-- /* Record the file information and send an ack */
-- peer_oft_copy_xfer_data(conn, frame);
-- peer_oft_send_ack(conn);
--
-- /* Remove our watchers and use the file transfer watchers in the core */
-- purple_input_remove(conn->watcher_incoming);
-- conn->watcher_incoming = 0;
-- conn->sending_data_timer = purple_timeout_add(100,
-- start_transfer_when_done_sending_data, conn);
--}
--
--/**
-- * We are sending a file to someone else. They have just acknowledged our
-- * prompt, so we want to start sending data like there's no tomorrow.
-- */
--static void
--peer_oft_recv_frame_ack(PeerConnection *conn, OftFrame *frame)
--{
-- if (memcmp(conn->cookie, frame->cookie, 8) != 0)
-- {
-- purple_debug_info("oscar", "Received an incorrect cookie. "
-- "Closing connection.\n");
-- peer_connection_destroy(conn, OSCAR_DISCONNECT_INVALID_DATA, NULL);
-- return;
-- }
--
-- /* Remove our watchers and use the file transfer watchers in the core */
-- purple_input_remove(conn->watcher_incoming);
-- conn->watcher_incoming = 0;
-- conn->sending_data_timer = purple_timeout_add(100,
-- start_transfer_when_done_sending_data, conn);
--}
--
--static gboolean
--peer_oft_recv_frame_resume_checksum_calculated_cb(gpointer data)
--{
-- ChecksumData *checksum_data;
-- PeerConnection *conn;
--
-- checksum_data = data;
-- conn = checksum_data->conn;
--
-- /* Check the checksums here. If not match, don't allow resume */
-- if (checksum_data->checksum != conn->xferdata.recvcsum || checksum_data->total != conn->xferdata.nrecvd)
-- {
-- /* Reset internal structure */
-- conn->xferdata.recvcsum = 0xffff0000;
-- conn->xferdata.rfrcsum = 0xffff0000;
-- conn->xferdata.nrecvd = 0;
-- }
-- else
-- /* Accept the change */
-- purple_xfer_set_bytes_sent(checksum_data->xfer, conn->xferdata.nrecvd);
--
-- peer_oft_send_resume_accept(conn);
--
-- return FALSE;
--}
--
--/**
-- * We are sending a file to someone else. They have just acknowledged our
-- * prompt and are asking to resume, so we accept their resume and await
-- * a resume ack.
-- */
--static void
--peer_oft_recv_frame_resume(PeerConnection *conn, OftFrame *frame)
--{
-- if (memcmp(conn->cookie, frame->cookie, 8) != 0)
-- {
-- purple_debug_info("oscar", "Received an incorrect cookie. "
-- "Closing connection.\n");
-- peer_connection_destroy(conn, OSCAR_DISCONNECT_INVALID_DATA, NULL);
-- return;
-- }
--
-- /* Copy resume data into internal structure */
-- conn->xferdata.recvcsum = frame->recvcsum;
-- conn->xferdata.rfrcsum = frame->rfrcsum;
-- conn->xferdata.nrecvd = frame->nrecvd;
--
-- peer_oft_checksum_file(conn, conn->xfer,
-- peer_oft_recv_frame_resume_checksum_calculated_cb,
-- frame->nrecvd);
--}
--
--/*
-- * We just sent a file to someone. They said they got it and everything,
-- * so we can close our direct connection and what not.
-- */
--static void
--peer_oft_recv_frame_done(PeerConnection *conn, OftFrame *frame)
--{
-- /*
-- * The core ft code sets the xfer to completed automatically if we've
-- * sent all bytes to the other user. But this function can be called
-- * even if we haven't sent all bytes to the other user (in the case
-- * where the user already has this file on their computer and the
-- * checksum matches).
-- */
-- if (!purple_xfer_is_completed(conn->xfer))
-- purple_xfer_set_completed(conn->xfer, TRUE);
--
-- purple_input_remove(conn->watcher_incoming);
-- conn->watcher_incoming = 0;
-- conn->xfer->fd = conn->fd;
-- conn->fd = -1;
-- conn->disconnect_reason = OSCAR_DISCONNECT_DONE;
-- peer_connection_schedule_destroy(conn, conn->disconnect_reason, NULL);
--}
--
--/**
-- * Handle an incoming OftFrame. If there is a payload associated
-- * with this frame, then we remove the old watcher and add the
-- * OFT watcher to read in the payload.
-- */
--void
--peer_oft_recv_frame(PeerConnection *conn, ByteStream *bs)
--{
-- OftFrame frame;
--
-- frame.type = byte_stream_get16(bs);
-- byte_stream_getrawbuf(bs, frame.cookie, 8);
-- frame.encrypt = byte_stream_get16(bs);
-- frame.compress = byte_stream_get16(bs);
-- frame.totfiles = byte_stream_get16(bs);
-- frame.filesleft = byte_stream_get16(bs);
-- frame.totparts = byte_stream_get16(bs);
-- frame.partsleft = byte_stream_get16(bs);
-- frame.totsize = byte_stream_get32(bs);
-- frame.size = byte_stream_get32(bs);
-- frame.modtime = byte_stream_get32(bs);
-- frame.checksum = byte_stream_get32(bs);
-- frame.rfrcsum = byte_stream_get32(bs);
-- frame.rfsize = byte_stream_get32(bs);
-- frame.cretime = byte_stream_get32(bs);
-- frame.rfcsum = byte_stream_get32(bs);
-- frame.nrecvd = byte_stream_get32(bs);
-- frame.recvcsum = byte_stream_get32(bs);
-- byte_stream_getrawbuf(bs, frame.idstring, 32);
-- frame.flags = byte_stream_get8(bs);
-- frame.lnameoffset = byte_stream_get8(bs);
-- frame.lsizeoffset = byte_stream_get8(bs);
-- byte_stream_getrawbuf(bs, frame.dummy, 69);
-- byte_stream_getrawbuf(bs, frame.macfileinfo, 16);
-- frame.nencode = byte_stream_get16(bs);
-- frame.nlanguage = byte_stream_get16(bs);
-- frame.name_length = bs->len - 186;
-- frame.name = byte_stream_getraw(bs, frame.name_length);
--
-- purple_debug_info("oscar", "Incoming OFT frame from %s with "
-- "type=0x%04x\n", conn->bn, frame.type);
--
-- /* TODOFT: peer_oft_dirconvert_fromstupid(frame->name); */
--
-- switch(frame.type)
-- {
-- case PEER_TYPE_PROMPT:
-- peer_oft_recv_frame_prompt(conn, &frame);
-- break;
-- case PEER_TYPE_ACK:
-- case PEER_TYPE_RESUMEACK:
-- peer_oft_recv_frame_ack(conn, &frame);
-- break;
-- case PEER_TYPE_RESUME:
-- peer_oft_recv_frame_resume(conn, &frame);
-- break;
-- case PEER_TYPE_DONE:
-- peer_oft_recv_frame_done(conn, &frame);
-- break;
-- default:
-- break;
-- }
--
-- g_free(frame.name);
--}
--
--/*******************************************************************/
--/* Begin PurpleXfer callbacks for use when receiving a file */
--/*******************************************************************/
--
--void
--peer_oft_recvcb_init(PurpleXfer *xfer)
--{
-- PeerConnection *conn;
--
-- conn = xfer->data;
-- conn->flags |= PEER_CONNECTION_FLAG_APPROVED;
-- peer_connection_trynext(conn);
--}
--
--void
--peer_oft_recvcb_end(PurpleXfer *xfer)
--{
-- PeerConnection *conn;
--
-- conn = xfer->data;
--
-- /* Tell the other person that we've received everything */
-- conn->fd = conn->xfer->fd;
-- conn->xfer->fd = -1;
-- peer_oft_send_done(conn);
--
-- conn->disconnect_reason = OSCAR_DISCONNECT_DONE;
-- conn->sending_data_timer = purple_timeout_add(100,
-- destroy_connection_when_done_sending_data, conn);
--}
--
--void
--peer_oft_recvcb_ack_recv(PurpleXfer *xfer, const guchar *buffer, size_t size)
--{
-- PeerConnection *conn;
--
-- /* Update our rolling checksum. Like Walmart, yo. */
-- conn = xfer->data;
-- conn->xferdata.recvcsum = peer_oft_checksum_chunk(buffer,
-- size, conn->xferdata.recvcsum, purple_xfer_get_bytes_sent(xfer) & 1);
--}
--
--/*******************************************************************/
--/* End PurpleXfer callbacks for use when receiving a file */
--/*******************************************************************/
--
--/*******************************************************************/
--/* Begin PurpleXfer callbacks for use when sending a file */
--/*******************************************************************/
--
--static gboolean
--peer_oft_checksum_calculated_cb(gpointer data)
--{
-- ChecksumData *checksum_data;
-- PeerConnection *conn;
--
-- checksum_data = data;
-- conn = checksum_data->conn;
--
-- conn->xferdata.checksum = checksum_data->checksum;
--
-- /* Start the connection process */
-- peer_connection_trynext(checksum_data->conn);
--
-- return FALSE;
--}
--
--void
--peer_oft_sendcb_init(PurpleXfer *xfer)
--{
-- PeerConnection *conn;
-- size_t size;
--
-- conn = xfer->data;
-- conn->flags |= PEER_CONNECTION_FLAG_APPROVED;
--
-- /* Make sure the file size can be represented in 32 bits */
-- size = purple_xfer_get_size(xfer);
-- if (size > G_MAXUINT32)
-- {
-- gchar *tmp, *size1, *size2;
-- size1 = purple_str_size_to_units(size);
-- size2 = purple_str_size_to_units(G_MAXUINT32);
-- tmp = g_strdup_printf(_("File %s is %s, which is larger than "
-- "the maximum size of %s."),
-- xfer->local_filename, size1, size2);
-- purple_xfer_error(purple_xfer_get_type(xfer),
-- purple_xfer_get_account(xfer), xfer->who, tmp);
-- g_free(size1);
-- g_free(size2);
-- g_free(tmp);
-- peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);
-- return;
-- }
--
-- /* Keep track of file transfer info */
-- conn->xferdata.totfiles = 1;
-- conn->xferdata.filesleft = 1;
-- conn->xferdata.totparts = 1;
-- conn->xferdata.partsleft = 1;
-- conn->xferdata.totsize = size;
-- conn->xferdata.size = size;
-- conn->xferdata.checksum = 0xffff0000;
-- conn->xferdata.rfrcsum = 0xffff0000;
-- conn->xferdata.rfcsum = 0xffff0000;
-- conn->xferdata.recvcsum = 0xffff0000;
-- strncpy((gchar *)conn->xferdata.idstring, "Cool FileXfer", 31);
-- conn->xferdata.modtime = 0;
-- conn->xferdata.cretime = 0;
-- xfer->filename = g_path_get_basename(xfer->local_filename);
-- conn->xferdata.name_length = MAX(64, strlen(xfer->filename) + 1);
-- conn->xferdata.name = (guchar *)g_strndup(xfer->filename, conn->xferdata.name_length - 1);
--
-- peer_oft_checksum_file(conn, xfer,
-- peer_oft_checksum_calculated_cb, G_MAXUINT32);
--}
--
--/*
-- * AIM file transfers aren't really meant to be thought
-- * of as a transferring just a single file. The rendezvous
-- * establishes a connection between two computers, and then
-- * those computers can use the same connection for transferring
-- * multiple files. So we don't want the Purple core up and closing
-- * the socket all willy-nilly. We want to do that in the oscar
-- * prpl, whenever one side or the other says they're finished
-- * using the connection. There might be a better way to intercept
-- * the socket from the core...
-- */
--void
--peer_oft_sendcb_ack(PurpleXfer *xfer, const guchar *buffer, size_t size)
--{
-- PeerConnection *conn;
--
-- conn = xfer->data;
--
-- /*
-- * If we're done sending, intercept the socket from the core ft code
-- * and wait for the other guy to send the "done" OFT packet.
-- */
-- if (purple_xfer_get_bytes_remaining(xfer) <= 0)
-- {
-- purple_input_remove(xfer->watcher);
-- conn->fd = xfer->fd;
-- xfer->fd = -1;
-- conn->watcher_incoming = purple_input_add(conn->fd,
-- PURPLE_INPUT_READ, peer_connection_recv_cb, conn);
-- }
--}
--
--/*******************************************************************/
--/* End PurpleXfer callbacks for use when sending a file */
--/*******************************************************************/
--
--/*******************************************************************/
--/* Begin PurpleXfer callbacks for use when sending and receiving */
--/*******************************************************************/
--
--void
--peer_oft_cb_generic_cancel(PurpleXfer *xfer)
--{
-- PeerConnection *conn;
--
-- conn = xfer->data;
--
-- if (conn == NULL)
-- return;
--
-- peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);
--}
--
--/*******************************************************************/
--/* End PurpleXfer callbacks for use when sending and receiving */
--/*******************************************************************/
--
--#ifdef TODOFT
--/*
-- * This little area in oscar.c is the nexus of file transfer code,
-- * so I wrote a little explanation of what happens. I am such a
-- * ninja.
-- *
-- * The series of events for a file send is:
-- * -Create xfer and call purple_xfer_request (this happens in oscar_ask_sendfile)
-- * -User chooses a file and oscar_xfer_init is called. It establishes a
-- * listening socket, then asks the remote user to connect to us (and
-- * gives them the file name, port, IP, etc.)
-- * -They connect to us and we send them an PEER_TYPE_PROMPT (this happens
-- * in peer_oft_recv_frame_established)
-- * -They send us an PEER_TYPE_ACK and then we start sending data
-- * -When we finish, they send us an PEER_TYPE_DONE and they close the
-- * connection.
-- * -We get drunk because file transfer kicks ass.
-- *
-- * The series of events for a file receive is:
-- * -Create xfer and call purple_xfer request (this happens in incomingim_chan2)
-- * -Purple user selects file to name and location to save file to and
-- * oscar_xfer_init is called
-- * -It connects to the remote user using the IP they gave us earlier
-- * -After connecting, they send us an PEER_TYPE_PROMPT. In reply, we send
-- * them an PEER_TYPE_ACK.
-- * -They begin to send us lots of raw data.
-- * -When they finish sending data we send an PEER_TYPE_DONE and then close
-- * the connection.
-- *
-- * Update August 2005:
-- * The series of events for transfers has been seriously complicated by the addition
-- * of transfer redirects and proxied connections. I could throw a whole lot of words
-- * at trying to explain things here, but it probably wouldn't do much good. To get
-- * a better idea of what happens, take a look at the diagrams and documentation
-- * from my Summer of Code project. -- Jonathan Clark
-- */
--
--/**
-- * Convert the directory separator from / (0x2f) to ^A (0x01)
-- *
-- * @param name The filename to convert.
-- */
--static void
--peer_oft_dirconvert_tostupid(char *name)
--{
-- while (name[0]) {
-- if (name[0] == 0x01)
-- name[0] = G_DIR_SEPARATOR;
-- name++;
-- }
--}
--
--/**
-- * Convert the directory separator from ^A (0x01) to / (0x2f)
-- *
-- * @param name The filename to convert.
-- */
--static void
--peer_oft_dirconvert_fromstupid(char *name)
--{
-- while (name[0]) {
-- if (name[0] == G_DIR_SEPARATOR)
-- name[0] = 0x01;
-- name++;
-- }
--}
--#endif
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/oscar.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oscar.c
---- pidgin-2.10.7/libpurple/protocols/oscar/oscar.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oscar.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,5818 +0,0 @@
--/*
-- * purple
-- *
-- * Some code copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
-- * Some code copyright (C) 1999-2001, Eric Warmenhoven
-- * Some code copyright (C) 2001-2003, Sean Egan
-- * Some code copyright (C) 2001-2007, Mark Doliner <thekingant@users.sourceforge.net>
-- * Some code copyright (C) 2005, Jonathan Clark <ardentlygnarly@users.sourceforge.net>
-- * Some code copyright (C) 2007, ComBOTS Product GmbH (htfv) <foss@combots.com>
-- * Some code copyright (C) 2008, Aman Gupta
-- *
-- * Most libfaim code copyright (C) 1998-2001 Adam Fritzler <afritz@auk.cx>
-- * Some libfaim code copyright (C) 2001-2004 Mark Doliner <thekingant@users.sourceforge.net>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include "internal.h"
--
--#include "account.h"
--#include "accountopt.h"
--#include "buddyicon.h"
--#include "cipher.h"
--#include "conversation.h"
--#include "core.h"
--#include "debug.h"
--#include "encoding.h"
--#include "imgstore.h"
--#include "network.h"
--#include "notify.h"
--#include "privacy.h"
--#include "prpl.h"
--#include "proxy.h"
--#include "request.h"
--#include "util.h"
--#include "version.h"
--#include "visibility.h"
--
--#include "oscarcommon.h"
--#include "oscar.h"
--#include "peer.h"
--
--#define AIMHASHDATA "http://pidgin.im/aim_data.php3"
--
--#define OSCAR_CONNECT_STEPS 6
--
--static guint64 purple_caps =
-- OSCAR_CAPABILITY_CHAT
-- | OSCAR_CAPABILITY_BUDDYICON
-- | OSCAR_CAPABILITY_DIRECTIM
-- | OSCAR_CAPABILITY_SENDFILE
-- | OSCAR_CAPABILITY_UNICODE
-- | OSCAR_CAPABILITY_INTEROPERATE
-- | OSCAR_CAPABILITY_SHORTCAPS
-- | OSCAR_CAPABILITY_TYPING
-- | OSCAR_CAPABILITY_ICQSERVERRELAY
-- | OSCAR_CAPABILITY_NEWCAPS
-- | OSCAR_CAPABILITY_XTRAZ
-- | OSCAR_CAPABILITY_HTML_MSGS;
--
--static guint8 features_aim[] = {0x01, 0x01, 0x01, 0x02};
--static guint8 features_icq[] = {0x01};
--
--struct create_room {
-- char *name;
-- int exchange;
--};
--
--struct oscar_ask_directim_data
--{
-- OscarData *od;
-- char *who;
--};
--
--/* All the libfaim->purple callback functions */
--
--/* Only used when connecting with the old-style BUCP login */
--static int purple_parse_auth_resp (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_parse_login (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_parse_auth_securid_request(OscarData *, FlapConnection *, FlapFrame *, ...);
--
--static int purple_handle_redirect (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_info_change (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_account_confirm (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_parse_oncoming (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_parse_offgoing (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_parse_incoming_im(OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_parse_misses (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_parse_clientauto (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_parse_motd (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_chatnav_info (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_conv_chat_join (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_conv_chat_leave (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_conv_chat_info_update (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_conv_chat_incoming_msg(OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_email_parseupdate(OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_icon_parseicon (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_parse_searcherror(OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_parse_searchreply(OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_bosrights (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_connerr (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_parse_mtn (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_parse_locaterights(OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_parse_buddyrights(OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_parse_genericerr (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_memrequest (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_selfinfo (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_popup (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_ssi_parseerr (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_ssi_parserights (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_ssi_parselist (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_ssi_parseack (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_ssi_parseaddmod (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_ssi_authgiven (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_ssi_authrequest (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_ssi_authreply (OscarData *, FlapConnection *, FlapFrame *, ...);
--static int purple_ssi_gotadded (OscarData *, FlapConnection *, FlapFrame *, ...);
--
--static void purple_icons_fetch(PurpleConnection *gc);
--
--void oscar_set_info(PurpleConnection *gc, const char *info);
--static void oscar_set_info_and_status(PurpleAccount *account, gboolean setinfo, const char *rawinfo, gboolean setstatus, PurpleStatus *status);
--static void oscar_set_extended_status(PurpleConnection *gc);
--static gboolean purple_ssi_rerequestdata(gpointer data);
--
--void oscar_free_name_data(struct name_data *data) {
-- g_free(data->name);
-- g_free(data->nick);
-- g_free(data);
--}
--
--#ifdef _WIN32
--const char *oscar_get_locale_charset(void) {
-- static const char *charset = NULL;
-- if (charset == NULL)
-- g_get_charset(&charset);
-- return charset;
--}
--#endif
--
--static char *oscar_icqstatus(int state) {
-- /* Make a cute little string that shows the status of the dude or dudet */
-- if (state & AIM_ICQ_STATE_CHAT)
-- return g_strdup(_("Free For Chat"));
-- else if (state & AIM_ICQ_STATE_DND)
-- return g_strdup(_("Do Not Disturb"));
-- else if (state & AIM_ICQ_STATE_OUT)
-- return g_strdup(_("Not Available"));
-- else if (state & AIM_ICQ_STATE_BUSY)
-- return g_strdup(_("Occupied"));
-- else if (state & AIM_ICQ_STATE_AWAY)
-- return g_strdup(_("Away"));
-- else if (state & AIM_ICQ_STATE_WEBAWARE)
-- return g_strdup(_("Web Aware"));
-- else if (state & AIM_ICQ_STATE_INVISIBLE)
-- return g_strdup(_("Invisible"));
-- else if (state & AIM_ICQ_STATE_EVIL)
-- return g_strdup(_("Evil"));
-- else if (state & AIM_ICQ_STATE_DEPRESSION)
-- return g_strdup(_("Depression"));
-- else if (state & AIM_ICQ_STATE_ATHOME)
-- return g_strdup(_("At home"));
-- else if (state & AIM_ICQ_STATE_ATWORK)
-- return g_strdup(_("At work"));
-- else if (state & AIM_ICQ_STATE_LUNCH)
-- return g_strdup(_("At lunch"));
-- else
-- return g_strdup(_("Online"));
--}
--
--static char *extract_name(const char *name) {
-- char *tmp, *x;
-- int i, j;
--
-- if (!name)
-- return NULL;
--
-- x = strchr(name, '-');
-- if (!x)
-- return NULL;
--
-- x = strchr(x + 1, '-');
-- if (!x)
-- return NULL;
--
-- tmp = g_strdup(++x);
--
-- for (i = 0, j = 0; x[i]; i++) {
-- char hex[3];
-- if (x[i] != '%') {
-- tmp[j++] = x[i];
-- continue;
-- }
-- strncpy(hex, x + ++i, 2);
-- hex[2] = 0;
-- i++;
-- tmp[j++] = strtol(hex, NULL, 16);
-- }
--
-- tmp[j] = 0;
-- return tmp;
--}
--
--static struct chat_connection *
--find_oscar_chat(PurpleConnection *gc, int id)
--{
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- GSList *cur;
-- struct chat_connection *cc;
--
-- for (cur = od->oscar_chats; cur != NULL; cur = cur->next)
-- {
-- cc = (struct chat_connection *)cur->data;
-- if (cc->id == id)
-- return cc;
-- }
--
-- return NULL;
--}
--
--static struct chat_connection *
--find_oscar_chat_by_conn(PurpleConnection *gc, FlapConnection *conn)
--{
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- GSList *cur;
-- struct chat_connection *cc;
--
-- for (cur = od->oscar_chats; cur != NULL; cur = cur->next)
-- {
-- cc = (struct chat_connection *)cur->data;
-- if (cc->conn == conn)
-- return cc;
-- }
--
-- return NULL;
--}
--
--static struct chat_connection *
--find_oscar_chat_by_conv(PurpleConnection *gc, PurpleConversation *conv)
--{
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- GSList *cur;
-- struct chat_connection *cc;
--
-- for (cur = od->oscar_chats; cur != NULL; cur = cur->next)
-- {
-- cc = (struct chat_connection *)cur->data;
-- if (cc->conv == conv)
-- return cc;
-- }
--
-- return NULL;
--}
--
--void
--oscar_chat_destroy(struct chat_connection *cc)
--{
-- g_free(cc->name);
-- g_free(cc->show);
-- g_free(cc);
--}
--
--static void
--oscar_chat_kill(PurpleConnection *gc, struct chat_connection *cc)
--{
-- OscarData *od = purple_connection_get_protocol_data(gc);
--
-- /* Notify the conversation window that we've left the chat */
-- serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(cc->conv)));
--
-- /* Destroy the chat_connection */
-- od->oscar_chats = g_slist_remove(od->oscar_chats, cc);
-- oscar_chat_destroy(cc);
--}
--
--/**
-- * This is called from the callback functions for establishing
-- * a TCP connection with an oscar host if an error occurred.
-- */
--static void
--connection_common_error_cb(FlapConnection *conn, const gchar *error_message)
--{
-- OscarData *od;
-- PurpleConnection *gc;
--
-- od = conn->od;
-- gc = od->gc;
--
-- purple_debug_error("oscar", "unable to connect to FLAP "
-- "server of type 0x%04hx\n", conn->type);
--
-- if (conn->type == SNAC_FAMILY_AUTH)
-- {
-- /* This only happens when connecting with the old-style BUCP login */
-- gchar *msg;
-- msg = g_strdup_printf(_("Unable to connect to authentication server: %s"),
-- error_message);
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
-- g_free(msg);
-- }
-- else if (conn->type == SNAC_FAMILY_LOCATE)
-- {
-- gchar *msg;
-- msg = g_strdup_printf(_("Unable to connect to BOS server: %s"),
-- error_message);
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
-- g_free(msg);
-- }
-- else
-- {
-- /* Maybe we should call this for BOS connections, too? */
-- flap_connection_schedule_destroy(conn,
-- OSCAR_DISCONNECT_COULD_NOT_CONNECT, error_message);
-- }
--}
--
--/**
-- * This is called from the callback functions for establishing
-- * a TCP connection with an oscar host. Depending on the type
-- * of host, we do a few different things here.
-- */
--static void
--connection_common_established_cb(FlapConnection *conn)
--{
-- OscarData *od;
-- PurpleConnection *gc;
-- PurpleAccount *account;
--
-- od = conn->od;
-- gc = od->gc;
-- account = purple_connection_get_account(gc);
--
-- purple_debug_info("oscar", "connected to FLAP server of type 0x%04hx\n",
-- conn->type);
--
-- if (conn->cookie == NULL)
-- flap_connection_send_version(od, conn);
-- else
-- {
-- if (purple_account_get_bool(account, "use_clientlogin", OSCAR_DEFAULT_USE_CLIENTLOGIN))
-- {
-- ClientInfo aiminfo = CLIENTINFO_PURPLE_AIM;
-- ClientInfo icqinfo = CLIENTINFO_PURPLE_ICQ;
-- flap_connection_send_version_with_cookie_and_clientinfo(od,
-- conn, conn->cookielen, conn->cookie,
-- od->icq ? &icqinfo : &aiminfo,
-- purple_account_get_bool(account, "allow_multiple_logins", OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS));
-- } else {
-- flap_connection_send_version_with_cookie(od, conn,
-- conn->cookielen, conn->cookie);
-- }
--
--
-- g_free(conn->cookie);
-- conn->cookie = NULL;
-- }
--
-- if (conn->type == SNAC_FAMILY_AUTH)
-- {
-- /* This only happens when connecting with the old-style BUCP login */
-- aim_request_login(od, conn, purple_account_get_username(account));
-- purple_debug_info("oscar", "Username sent, waiting for response\n");
-- purple_connection_update_progress(gc, _("Username sent"), 1, OSCAR_CONNECT_STEPS);
-- }
-- else if (conn->type == SNAC_FAMILY_LOCATE)
-- {
-- purple_connection_update_progress(gc, _("Connection established, cookie sent"), 4, OSCAR_CONNECT_STEPS);
-- }
-- else if (conn->type == SNAC_FAMILY_CHAT)
-- {
-- od->oscar_chats = g_slist_prepend(od->oscar_chats, conn->new_conn_data);
-- conn->new_conn_data = NULL;
-- }
--}
--
--static void
--connection_established_cb(gpointer data, gint source, const gchar *error_message)
--{
-- FlapConnection *conn;
--
-- conn = data;
--
-- conn->connect_data = NULL;
-- conn->fd = source;
--
-- if (source < 0)
-- {
-- connection_common_error_cb(conn, error_message);
-- return;
-- }
--
-- conn->watcher_incoming = purple_input_add(conn->fd,
-- PURPLE_INPUT_READ, flap_connection_recv_cb, conn);
-- connection_common_established_cb(conn);
--}
--
--static void
--ssl_connection_established_cb(gpointer data, PurpleSslConnection *gsc,
-- PurpleInputCondition cond)
--{
-- FlapConnection *conn;
--
-- conn = data;
--
-- purple_ssl_input_add(gsc, flap_connection_recv_cb_ssl, conn);
-- connection_common_established_cb(conn);
--}
--
--static void
--ssl_connection_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error,
-- gpointer data)
--{
-- FlapConnection *conn;
--
-- conn = data;
--
-- if (conn->watcher_outgoing)
-- {
-- purple_input_remove(conn->watcher_outgoing);
-- conn->watcher_outgoing = 0;
-- }
--
-- /* sslconn frees the connection on error */
-- conn->gsc = NULL;
--
-- connection_common_error_cb(conn, purple_ssl_strerror(error));
--}
--
--static void
--flap_connection_established_bos(OscarData *od, FlapConnection *conn)
--{
-- PurpleConnection *gc = od->gc;
--
-- aim_srv_reqpersonalinfo(od, conn);
--
-- purple_debug_info("oscar", "ssi: requesting rights and list\n");
-- aim_ssi_reqrights(od);
-- aim_ssi_reqdata(od);
-- if (od->getblisttimer > 0)
-- purple_timeout_remove(od->getblisttimer);
-- od->getblisttimer = purple_timeout_add_seconds(30, purple_ssi_rerequestdata, od);
--
-- aim_locate_reqrights(od);
-- aim_buddylist_reqrights(od, conn);
-- aim_im_reqparams(od);
-- aim_bos_reqrights(od, conn); /* TODO: Don't call this with ssi */
--
-- purple_connection_update_progress(gc, _("Finalizing connection"), 5, OSCAR_CONNECT_STEPS);
--}
--
--static void
--flap_connection_established_admin(OscarData *od, FlapConnection *conn)
--{
-- aim_srv_clientready(od, conn);
-- purple_debug_info("oscar", "connected to admin\n");
--
-- if (od->chpass) {
-- purple_debug_info("oscar", "changing password\n");
-- aim_admin_changepasswd(od, conn, od->newp, od->oldp);
-- g_free(od->oldp);
-- od->oldp = NULL;
-- g_free(od->newp);
-- od->newp = NULL;
-- od->chpass = FALSE;
-- }
-- if (od->setnick) {
-- purple_debug_info("oscar", "formatting username\n");
-- aim_admin_setnick(od, conn, od->newformatting);
-- g_free(od->newformatting);
-- od->newformatting = NULL;
-- od->setnick = FALSE;
-- }
-- if (od->conf) {
-- purple_debug_info("oscar", "confirming account\n");
-- aim_admin_reqconfirm(od, conn);
-- od->conf = FALSE;
-- }
-- if (od->reqemail) {
-- purple_debug_info("oscar", "requesting email address\n");
-- aim_admin_getinfo(od, conn, 0x0011);
-- od->reqemail = FALSE;
-- }
-- if (od->setemail) {
-- purple_debug_info("oscar", "setting email address\n");
-- aim_admin_setemail(od, conn, od->email);
-- g_free(od->email);
-- od->email = NULL;
-- od->setemail = FALSE;
-- }
--}
--
--static void
--flap_connection_established_chat(OscarData *od, FlapConnection *conn)
--{
-- PurpleConnection *gc = od->gc;
-- struct chat_connection *chatcon;
-- static int id = 1;
--
-- aim_srv_clientready(od, conn);
--
-- chatcon = find_oscar_chat_by_conn(gc, conn);
-- if (chatcon) {
-- chatcon->id = id;
-- chatcon->conv = serv_got_joined_chat(gc, id++, chatcon->show);
-- }
--}
--
--static void
--flap_connection_established_chatnav(OscarData *od, FlapConnection *conn)
--{
-- aim_srv_clientready(od, conn);
-- aim_chatnav_reqrights(od, conn);
--}
--
--static void
--flap_connection_established_alert(OscarData *od, FlapConnection *conn)
--{
-- aim_email_sendcookies(od);
-- aim_email_activate(od);
-- aim_srv_clientready(od, conn);
--}
--
--static void
--flap_connection_established_bart(OscarData *od, FlapConnection *conn)
--{
-- PurpleConnection *gc = od->gc;
--
-- aim_srv_clientready(od, conn);
--
-- od->iconconnecting = FALSE;
--
-- purple_icons_fetch(gc);
--}
--
--static int
--flap_connection_established(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
--{
-- purple_debug_info("oscar", "FLAP connection of type 0x%04hx is "
-- "now fully connected\n", conn->type);
-- if (conn->type == SNAC_FAMILY_LOCATE)
-- flap_connection_established_bos(od, conn);
-- else if (conn->type == SNAC_FAMILY_ADMIN)
-- flap_connection_established_admin(od, conn);
-- else if (conn->type == SNAC_FAMILY_CHAT)
-- flap_connection_established_chat(od, conn);
-- else if (conn->type == SNAC_FAMILY_CHATNAV)
-- flap_connection_established_chatnav(od, conn);
-- else if (conn->type == SNAC_FAMILY_ALERT)
-- flap_connection_established_alert(od, conn);
-- else if (conn->type == SNAC_FAMILY_BART)
-- flap_connection_established_bart(od, conn);
--
-- return 1;
--}
--
--static void
--idle_reporting_pref_cb(const char *name, PurplePrefType type,
-- gconstpointer value, gpointer data)
--{
-- PurpleConnection *gc;
-- OscarData *od;
-- gboolean report_idle;
-- guint32 presence;
--
-- gc = data;
-- od = purple_connection_get_protocol_data(gc);
-- report_idle = strcmp((const char *)value, "none") != 0;
-- presence = aim_ssi_getpresence(od->ssi.local);
--
-- if (report_idle)
-- aim_ssi_setpresence(od, presence | AIM_SSI_PRESENCE_FLAG_SHOWIDLE);
-- else
-- aim_ssi_setpresence(od, presence & ~AIM_SSI_PRESENCE_FLAG_SHOWIDLE);
--}
--
--/**
-- * Should probably make a "Use recent buddies group" account preference
-- * so that this option is surfaced to the user.
-- */
--static void
--recent_buddies_pref_cb(const char *name, PurplePrefType type,
-- gconstpointer value, gpointer data)
--{
-- PurpleConnection *gc;
-- OscarData *od;
-- guint32 presence;
--
-- gc = data;
-- od = purple_connection_get_protocol_data(gc);
-- presence = aim_ssi_getpresence(od->ssi.local);
--
-- if (value)
-- aim_ssi_setpresence(od, presence & ~AIM_SSI_PRESENCE_FLAG_NORECENTBUDDIES);
-- else
-- aim_ssi_setpresence(od, presence | AIM_SSI_PRESENCE_FLAG_NORECENTBUDDIES);
--}
--
--static const gchar *login_servers[] = {
-- AIM_DEFAULT_LOGIN_SERVER,
-- AIM_DEFAULT_SSL_LOGIN_SERVER,
-- ICQ_DEFAULT_LOGIN_SERVER,
-- ICQ_DEFAULT_SSL_LOGIN_SERVER,
--};
--
--static const gchar *
--get_login_server(gboolean is_icq, gboolean use_ssl)
--{
-- return login_servers[(is_icq ? 2 : 0) + (use_ssl ? 1 : 0)];
--}
--
--static gint
--compare_handlers(gconstpointer a, gconstpointer b)
--{
-- guint aa = GPOINTER_TO_UINT(a);
-- guint bb = GPOINTER_TO_UINT(b);
-- guint family1 = aa >> 16;
-- guint family2 = bb >> 16;
-- guint subtype1 = aa & 0xFFFF;
-- guint subtype2 = bb & 0xFFFF;
-- if (family1 != family2) {
-- return family1 - family2;
-- }
-- return subtype1 - subtype2;
--}
--
--#if !GLIB_CHECK_VERSION(2,14,0)
--static void hash_table_get_list_of_keys(gpointer key, gpointer value, gpointer user_data)
--{
-- GList **handlers = (GList **)user_data;
--
-- *handlers = g_list_prepend(*handlers, key);
--}
--#endif /* GLIB < 2.14.0 */
--
--void
--oscar_login(PurpleAccount *account)
--{
-- PurpleConnection *gc;
-- OscarData *od;
-- const gchar *encryption_type;
-- GList *handlers;
-- GList *sorted_handlers;
-- GList *cur;
-- GString *msg = g_string_new("");
--
-- gc = purple_account_get_connection(account);
-- od = oscar_data_new();
-- od->gc = gc;
-- purple_connection_set_protocol_data(gc, od);
--
-- oscar_data_addhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, purple_connerr, 0);
-- oscar_data_addhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, flap_connection_established, 0);
--
-- oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0003, purple_info_change, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0005, purple_info_change, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0007, purple_account_confirm, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_ALERT, 0x0001, purple_parse_genericerr, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_ALERT, SNAC_SUBTYPE_ALERT_MAILSTATUS, purple_email_parseupdate, 0);
--
-- /* These are only needed when connecting with the old-style BUCP login */
-- oscar_data_addhandler(od, SNAC_FAMILY_AUTH, 0x0003, purple_parse_auth_resp, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_AUTH, 0x0007, purple_parse_login, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_AUTH, SNAC_SUBTYPE_AUTH_SECURID_REQUEST, purple_parse_auth_securid_request, 0);
--
-- oscar_data_addhandler(od, SNAC_FAMILY_BART, SNAC_SUBTYPE_BART_RESPONSE, purple_icon_parseicon, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_BOS, 0x0001, purple_parse_genericerr, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_BOS, 0x0003, purple_bosrights, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, 0x0001, purple_parse_genericerr, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_RIGHTSINFO, purple_parse_buddyrights, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_ONCOMING, purple_parse_oncoming, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_OFFGOING, purple_parse_offgoing, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_CHAT, 0x0001, purple_parse_genericerr, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_USERJOIN, purple_conv_chat_join, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_USERLEAVE, purple_conv_chat_leave, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_ROOMINFOUPDATE, purple_conv_chat_info_update, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_INCOMINGMSG, purple_conv_chat_incoming_msg, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_CHATNAV, 0x0001, purple_parse_genericerr, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_CHATNAV, SNAC_SUBTYPE_CHATNAV_INFO, purple_chatnav_info, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_ERROR, purple_ssi_parseerr, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RIGHTSINFO, purple_ssi_parserights, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_LIST, purple_ssi_parselist, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SRVACK, purple_ssi_parseack, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_ADD, purple_ssi_parseaddmod, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_MOD, purple_ssi_parseaddmod, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RECVAUTH, purple_ssi_authgiven, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RECVAUTHREQ, purple_ssi_authrequest, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RECVAUTHREP, purple_ssi_authreply, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_ADDED, purple_ssi_gotadded, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_INCOMING, purple_parse_incoming_im, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_MISSEDCALL, purple_parse_misses, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_CLIENTAUTORESP, purple_parse_clientauto, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_MTN, purple_parse_mtn, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_RIGHTSINFO, purple_parse_locaterights, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x0001, purple_parse_genericerr, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x000f, purple_selfinfo, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x001f, purple_memrequest, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_REDIRECT, purple_handle_redirect, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_MOTD, purple_parse_motd, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_POPUP, 0x0002, purple_popup, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_USERLOOKUP, SNAC_SUBTYPE_USERLOOKUP_ERROR, purple_parse_searcherror, 0);
-- oscar_data_addhandler(od, SNAC_FAMILY_USERLOOKUP, 0x0003, purple_parse_searchreply, 0);
--
-- g_string_append(msg, "Registered handlers: ");
--#if GLIB_CHECK_VERSION(2,14,0)
-- handlers = g_hash_table_get_keys(od->handlerlist);
--#else
-- handlers = NULL;
-- g_hash_table_foreach(od->handlerlist, hash_table_get_list_of_keys, &handlers);
--#endif /* GLIB < 2.14.0 */
-- sorted_handlers = g_list_sort(g_list_copy(handlers), compare_handlers);
-- for (cur = sorted_handlers; cur; cur = cur->next) {
-- guint x = GPOINTER_TO_UINT(cur->data);
-- g_string_append_printf(msg, "%04x/%04x, ", x >> 16, x & 0xFFFF);
-- }
-- g_list_free(sorted_handlers);
-- g_list_free(handlers);
-- purple_debug_misc("oscar", "%s\n", msg->str);
-- g_string_free(msg, TRUE);
--
-- purple_debug_misc("oscar", "oscar_login: gc = %p\n", gc);
--
-- if (!oscar_util_valid_name(purple_account_get_username(account))) {
-- gchar *buf;
-- buf = g_strdup_printf(_("Unable to sign on as %s because the username is invalid. Usernames must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), purple_account_get_username(account));
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, buf);
-- g_free(buf);
-- return;
-- }
--
-- gc->flags |= PURPLE_CONNECTION_HTML;
-- if (g_str_equal(purple_account_get_protocol_id(account), "prpl-icq")) {
-- od->icq = TRUE;
-- } else {
-- gc->flags |= PURPLE_CONNECTION_AUTO_RESP;
-- }
--
-- /* Set this flag based on the protocol_id rather than the username,
-- because that is what's tied to the get_moods prpl callback. */
-- if (g_str_equal(purple_account_get_protocol_id(account), "prpl-icq"))
-- gc->flags |= PURPLE_CONNECTION_SUPPORT_MOODS;
--
-- od->default_port = purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT);
--
-- encryption_type = purple_account_get_string(account, "encryption", OSCAR_DEFAULT_ENCRYPTION);
-- if (!purple_ssl_is_supported() && strcmp(encryption_type, OSCAR_REQUIRE_ENCRYPTION) == 0) {
-- purple_connection_error_reason(
-- gc,
-- PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
-- _("You required encryption in your account settings, but encryption is not supported by your system."));
-- return;
-- }
-- od->use_ssl = purple_ssl_is_supported() && strcmp(encryption_type, OSCAR_NO_ENCRYPTION) != 0;
--
-- /* Connect to core Purple signals */
-- purple_prefs_connect_callback(gc, "/purple/away/idle_reporting", idle_reporting_pref_cb, gc);
-- purple_prefs_connect_callback(gc, "/plugins/prpl/oscar/recent_buddies", recent_buddies_pref_cb, gc);
--
-- /*
-- * On 2008-03-05 AOL released some documentation on the OSCAR protocol
-- * which includes a new login method called clientLogin. It is similar
-- * (though not the same?) as what the AIM 6.0 series uses to
-- * authenticate.
-- *
-- * AIM 5.9 and lower use an MD5-based login procedure called "BUCP".
-- * This authentication method is used for both ICQ and AIM when
-- * clientLogin is not enabled.
-- */
-- if (purple_account_get_bool(account, "use_clientlogin", OSCAR_DEFAULT_USE_CLIENTLOGIN)) {
-- send_client_login(od, purple_account_get_username(account));
-- } else {
-- FlapConnection *newconn;
-- const char *server;
--
-- newconn = flap_connection_new(od, SNAC_FAMILY_AUTH);
--
-- if (od->use_ssl) {
-- server = purple_account_get_string(account, "server", get_login_server(od->icq, TRUE));
--
-- /*
-- * If the account's server is what the oscar prpl has offered as
-- * the default login server through the vast eons (all two of
-- * said default options, AFAIK) and the user wants SSL, we'll
-- * do what we know is best for them and change the setting out
-- * from under them to the SSL login server.
-- */
-- if (!strcmp(server, get_login_server(od->icq, FALSE)) || !strcmp(server, AIM_ALT_LOGIN_SERVER)) {
-- purple_debug_info("oscar", "Account uses SSL, so changing server to default SSL server\n");
-- purple_account_set_string(account, "server", get_login_server(od->icq, TRUE));
-- server = get_login_server(od->icq, TRUE);
-- }
--
-- newconn->gsc = purple_ssl_connect(account, server,
-- purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT),
-- ssl_connection_established_cb, ssl_connection_error_cb, newconn);
-- } else {
-- server = purple_account_get_string(account, "server", get_login_server(od->icq, FALSE));
--
-- /*
-- * See the comment above. We do the reverse here. If they don't want
-- * SSL but their server is set to OSCAR_DEFAULT_SSL_LOGIN_SERVER,
-- * set it back to the default.
-- */
-- if (!strcmp(server, get_login_server(od->icq, TRUE))) {
-- purple_debug_info("oscar", "Account does not use SSL, so changing server back to non-SSL\n");
-- purple_account_set_string(account, "server", get_login_server(od->icq, FALSE));
-- server = get_login_server(od->icq, FALSE);
-- }
--
-- newconn->connect_data = purple_proxy_connect(NULL, account, server,
-- purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT),
-- connection_established_cb, newconn);
-- }
--
-- if (newconn->gsc == NULL && newconn->connect_data == NULL) {
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Unable to connect"));
-- return;
-- }
-- }
--
-- purple_connection_update_progress(gc, _("Connecting"), 0, OSCAR_CONNECT_STEPS);
--}
--
--void
--oscar_close(PurpleConnection *gc)
--{
-- OscarData *od;
--
-- od = purple_connection_get_protocol_data(gc);
--
-- while (od->oscar_chats)
-- {
-- struct chat_connection *cc = od->oscar_chats->data;
-- od->oscar_chats = g_slist_remove(od->oscar_chats, cc);
-- oscar_chat_destroy(cc);
-- }
-- while (od->create_rooms)
-- {
-- struct create_room *cr = od->create_rooms->data;
-- g_free(cr->name);
-- od->create_rooms = g_slist_remove(od->create_rooms, cr);
-- g_free(cr);
-- }
-- oscar_data_destroy(od);
-- purple_connection_set_protocol_data(gc, NULL);
--
-- purple_prefs_disconnect_by_handle(gc);
--
-- purple_debug_info("oscar", "Signed off.\n");
--}
--
--/* XXX - Should use purple_util_fetch_url for the below stuff */
--struct pieceofcrap {
-- PurpleConnection *gc;
-- unsigned long offset;
-- unsigned long len;
-- char *modname;
-- int fd;
-- FlapConnection *conn;
-- unsigned int inpa;
--};
--
--static void damn_you(gpointer data, gint source, PurpleInputCondition c)
--{
-- struct pieceofcrap *pos = data;
-- OscarData *od = purple_connection_get_protocol_data(pos->gc);
-- char in = '\0';
-- int x = 0;
-- unsigned char m[17];
-- GString *msg;
--
-- while (read(pos->fd, &in, 1) == 1) {
-- if (in == '\n')
-- x++;
-- else if (in != '\r')
-- x = 0;
-- if (x == 2)
-- break;
-- in = '\0';
-- }
-- if (in != '\n') {
-- char buf[256];
-- g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly. "
-- "If so, check %s for updates."),
-- oscar_get_ui_info_string("website", PURPLE_WEBSITE));
-- purple_notify_warning(pos->gc, NULL,
-- _("Unable to get a valid AIM login hash."),
-- buf);
-- purple_input_remove(pos->inpa);
-- close(pos->fd);
-- g_free(pos);
-- return;
-- }
-- if (read(pos->fd, m, 16) != 16)
-- {
-- purple_debug_warning("oscar", "Could not read full AIM login hash "
-- "from " AIMHASHDATA "--that's bad.\n");
-- }
-- m[16] = '\0';
--
-- msg = g_string_new("Sending hash: ");
-- for (x = 0; x < 16; x++)
-- g_string_append_printf(msg, "%02hhx ", (unsigned char)m[x]);
-- g_string_append(msg, "\n");
-- purple_debug_misc("oscar", "%s", msg->str);
-- g_string_free(msg, TRUE);
--
-- purple_input_remove(pos->inpa);
-- close(pos->fd);
-- aim_sendmemblock(od, pos->conn, 0, 16, m, AIM_SENDMEMBLOCK_FLAG_ISHASH);
-- g_free(pos);
--}
--
--static void
--straight_to_hell(gpointer data, gint source, const gchar *error_message)
--{
-- struct pieceofcrap *pos = data;
-- gchar *buf;
-- gssize result;
--
-- pos->fd = source;
--
-- if (source < 0) {
-- buf = g_strdup_printf(_("You may be disconnected shortly. "
-- "If so, check %s for updates."),
-- oscar_get_ui_info_string("website", PURPLE_WEBSITE));
-- purple_notify_warning(pos->gc, NULL,
-- _("Unable to get a valid AIM login hash."),
-- buf);
-- g_free(buf);
-- g_free(pos->modname);
-- g_free(pos);
-- return;
-- }
--
-- buf = g_strdup_printf("GET " AIMHASHDATA "?offset=%ld&len=%ld&modname=%s HTTP/1.0\n\n",
-- pos->offset, pos->len, pos->modname ? pos->modname : "");
-- result = send(pos->fd, buf, strlen(buf), 0);
-- if (result != strlen(buf)) {
-- if (result < 0)
-- purple_debug_error("oscar", "Error writing %" G_GSIZE_FORMAT
-- " bytes to fetch AIM hash data: %s\n",
-- strlen(buf), g_strerror(errno));
-- else
-- purple_debug_error("oscar", "Tried to write %"
-- G_GSIZE_FORMAT " bytes to fetch AIM hash data but "
-- "instead wrote %" G_GSSIZE_FORMAT " bytes\n",
-- strlen(buf), result);
-- }
-- g_free(buf);
-- g_free(pos->modname);
-- pos->inpa = purple_input_add(pos->fd, PURPLE_INPUT_READ, damn_you, pos);
-- return;
--}
--
--/* size of icbmui.ocm, the largest module in AIM 3.5 */
--#define AIM_MAX_FILE_SIZE 98304
--
--static int purple_memrequest(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
--{
-- va_list ap;
-- struct pieceofcrap *pos;
-- guint32 offset, len;
-- char *modname;
--
-- va_start(ap, fr);
-- offset = va_arg(ap, guint32);
-- len = va_arg(ap, guint32);
-- modname = va_arg(ap, char *);
-- va_end(ap);
--
-- purple_debug_misc("oscar", "offset: %u, len: %u, file: %s\n",
-- offset, len, (modname ? modname : "aim.exe"));
--
-- if (len == 0) {
-- purple_debug_misc("oscar", "len is 0, hashing NULL\n");
-- aim_sendmemblock(od, conn, offset, len, NULL,
-- AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
-- return 1;
-- }
--
-- pos = g_new0(struct pieceofcrap, 1);
-- pos->gc = od->gc;
-- pos->conn = conn;
--
-- pos->offset = offset;
-- pos->len = len;
-- pos->modname = g_strdup(modname);
--
-- if (purple_proxy_connect(pos->gc, pos->gc->account, "pidgin.im", 80,
-- straight_to_hell, pos) == NULL)
-- {
-- char buf[256];
-- g_free(pos->modname);
-- g_free(pos);
--
-- g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly. "
-- "If so, check %s for updates."),
-- oscar_get_ui_info_string("website", PURPLE_WEBSITE));
-- purple_notify_warning(pos->gc, NULL,
-- _("Unable to get a valid login hash."),
-- buf);
-- }
--
-- return 1;
--}
--
--int oscar_connect_to_bos(PurpleConnection *gc, OscarData *od, const char *host, guint16 port, guint8 *cookie, guint16 cookielen, const char *tls_certname)
--{
-- PurpleAccount *account;
-- FlapConnection *conn;
--
-- account = purple_connection_get_account(gc);
--
-- conn = flap_connection_new(od, SNAC_FAMILY_LOCATE);
-- conn->cookielen = cookielen;
-- conn->cookie = g_memdup(cookie, cookielen);
--
-- /*
-- * Use TLS only if the server provided us with a tls_certname. The server might not specify a tls_certname even if we requested to use TLS,
-- * and that is something we should be prepared to.
-- */
-- if (tls_certname)
-- {
-- conn->gsc = purple_ssl_connect_with_ssl_cn(account, host, port,
-- ssl_connection_established_cb, ssl_connection_error_cb,
-- tls_certname, conn);
-- }
-- else
-- {
-- conn->connect_data = purple_proxy_connect(NULL,
-- account, host, port,
-- connection_established_cb, conn);
-- }
--
-- if (conn->gsc == NULL && conn->connect_data == NULL)
-- {
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect"));
-- return 0;
-- }
--
-- od->default_port = port;
--
-- purple_connection_update_progress(gc, _("Received authorization"), 3, OSCAR_CONNECT_STEPS);
--
-- return 1;
--}
--
--/**
-- * Only used when connecting with the old-style BUCP login.
-- */
--static int
--purple_parse_auth_resp(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
--{
-- PurpleConnection *gc = od->gc;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- char *host; int port;
-- int i;
-- FlapConnection *newconn;
-- va_list ap;
-- struct aim_authresp_info *info;
--
-- port = purple_account_get_int(account, "port", od->default_port);
--
-- va_start(ap, fr);
-- info = va_arg(ap, struct aim_authresp_info *);
-- va_end(ap);
--
-- purple_debug_info("oscar",
-- "inside auth_resp (Username: %s)\n", info->bn);
--
-- if (info->errorcode || !info->bosip || !info->cookielen || !info->cookie) {
-- char buf[256];
-- switch (info->errorcode) {
-- case 0x01:
-- /* Unregistered username */
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_USERNAME, _("Username does not exist"));
-- break;
-- case 0x05:
-- /* Incorrect password */
-- if (!purple_account_get_remember_password(account))
-- purple_account_set_password(account, NULL);
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Incorrect password"));
-- break;
-- case 0x11:
-- /* Suspended account */
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Your account is currently suspended"));
-- break;
-- case 0x02:
-- case 0x14:
-- /* service temporarily unavailable */
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("The AOL Instant Messenger service is temporarily unavailable."));
-- break;
-- case 0x18:
-- /* username connecting too frequently */
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Your username has been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer."));
-- break;
-- case 0x1c:
-- {
-- /* client too old */
-- g_snprintf(buf, sizeof(buf), _("The client version you are using is too old. Please upgrade at %s"),
-- oscar_get_ui_info_string("website", PURPLE_WEBSITE));
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, buf);
-- break;
-- }
-- case 0x1d:
-- /* IP address connecting too frequently */
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Your IP address has been connecting and disconnecting too frequently. Wait a minute and try again. If you continue to try, you will need to wait even longer."));
-- break;
-- default:
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Unknown reason"));
-- break;
-- }
-- purple_debug_info("oscar", "Login Error Code 0x%04hx\n", info->errorcode);
-- purple_debug_info("oscar", "Error URL: %s\n", info->errorurl ? info->errorurl : "");
-- return 1;
-- }
--
-- purple_debug_misc("oscar", "Reg status: %hu\n"
-- "Email: %s\n"
-- "BOSIP: %s\n",
-- info->regstatus,
-- info->email ? info->email : "null",
-- info->bosip ? info->bosip : "null");
-- purple_debug_info("oscar", "Closing auth connection...\n");
-- flap_connection_schedule_destroy(conn, OSCAR_DISCONNECT_DONE, NULL);
--
-- for (i = 0; i < strlen(info->bosip); i++) {
-- if (info->bosip[i] == ':') {
-- port = atoi(&(info->bosip[i+1]));
-- break;
-- }
-- }
-- host = g_strndup(info->bosip, i);
-- newconn = flap_connection_new(od, SNAC_FAMILY_LOCATE);
-- newconn->cookielen = info->cookielen;
-- newconn->cookie = g_memdup(info->cookie, info->cookielen);
--
-- if (od->use_ssl)
-- {
-- /*
-- * This shouldn't be hardcoded to "bos.oscar.aol.com" except that
-- * the server isn't sending us a name to use for comparing the
-- * certificate common name.
-- */
-- newconn->gsc = purple_ssl_connect_with_ssl_cn(account, host, port,
-- ssl_connection_established_cb, ssl_connection_error_cb,
-- "bos.oscar.aol.com", newconn);
-- }
-- else
-- {
-- newconn->connect_data = purple_proxy_connect(NULL, account, host, port,
-- connection_established_cb, newconn);
-- }
--
-- g_free(host);
-- if (newconn->gsc == NULL && newconn->connect_data == NULL)
-- {
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect"));
-- return 0;
-- }
--
-- purple_connection_update_progress(gc, _("Received authorization"), 3, OSCAR_CONNECT_STEPS);
--
-- return 1;
--}
--
--/**
-- * Only used when connecting with the old-style BUCP login.
-- */
--static void
--purple_parse_auth_securid_request_yes_cb(gpointer user_data, const char *msg)
--{
-- PurpleConnection *gc = user_data;
-- OscarData *od = purple_connection_get_protocol_data(gc);
--
-- aim_auth_securid_send(od, msg);
--}
--
--/**
-- * Only used when connecting with the old-style BUCP login.
-- */
--static void
--purple_parse_auth_securid_request_no_cb(gpointer user_data, const char *value)
--{
-- PurpleConnection *gc = user_data;
--
-- /* Disconnect */
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
-- _("The SecurID key entered is invalid"));
--}
--
--/**
-- * Only used when connecting with the old-style BUCP login.
-- */
--static int
--purple_parse_auth_securid_request(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
--{
-- PurpleConnection *gc = od->gc;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- gchar *primary;
--
-- purple_debug_info("oscar", "Got SecurID request\n");
--
-- primary = g_strdup_printf("Enter the SecurID key for %s.", purple_account_get_username(account));
-- purple_request_input(gc, NULL, _("Enter SecurID"), primary,
-- _("Enter the 6 digit number from the digital display."),
-- FALSE, FALSE, NULL,
-- _("_OK"), G_CALLBACK(purple_parse_auth_securid_request_yes_cb),
-- _("_Cancel"), G_CALLBACK(purple_parse_auth_securid_request_no_cb),
-- account, NULL, NULL,
-- gc);
-- g_free(primary);
--
-- return 1;
--}
--
--/**
-- * Only used when connecting with the old-style BUCP login.
-- */
--static int
--purple_parse_login(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
--{
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- ClientInfo aiminfo = CLIENTINFO_PURPLE_AIM;
-- ClientInfo icqinfo = CLIENTINFO_PURPLE_ICQ;
-- va_list ap;
-- char *key;
-- gboolean truncate_pass;
--
-- gc = od->gc;
-- account = purple_connection_get_account(gc);
--
-- va_start(ap, fr);
-- key = va_arg(ap, char *);
-- truncate_pass = va_arg(ap, int);
-- va_end(ap);
--
-- aim_send_login(od, conn, purple_account_get_username(account),
-- purple_connection_get_password(gc), truncate_pass,
-- od->icq ? &icqinfo : &aiminfo, key,
-- purple_account_get_bool(account, "allow_multiple_logins", OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS));
--
-- purple_connection_update_progress(gc, _("Password sent"), 2, OSCAR_CONNECT_STEPS);
--
-- return 1;
--}
--
--static int
--purple_handle_redirect(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
--{
-- PurpleConnection *gc = od->gc;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- char *host, *separator;
-- int port;
-- FlapConnection *newconn;
-- va_list ap;
-- struct aim_redirect_data *redir;
--
-- va_start(ap, fr);
-- redir = va_arg(ap, struct aim_redirect_data *);
-- va_end(ap);
--
-- port = od->default_port;
-- separator = strchr(redir->ip, ':');
-- if (separator != NULL)
-- {
-- host = g_strndup(redir->ip, separator - redir->ip);
-- port = atoi(separator + 1);
-- }
-- else
-- host = g_strdup(redir->ip);
--
-- if (!redir->use_ssl) {
-- const gchar *encryption_type = purple_account_get_string(account, "encryption", OSCAR_DEFAULT_ENCRYPTION);
-- if (strcmp(encryption_type, OSCAR_OPPORTUNISTIC_ENCRYPTION) == 0) {
-- purple_debug_warning("oscar", "We won't use SSL for FLAP type 0x%04hx.\n", redir->group);
-- } else if (strcmp(encryption_type, OSCAR_REQUIRE_ENCRYPTION) == 0) {
-- purple_debug_error("oscar", "FLAP server %s:%d of type 0x%04hx doesn't support encryption.", host, port, redir->group);
-- purple_connection_error_reason(
-- gc,
-- PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
-- _("You required encryption in your account settings, but one of the servers doesn't support it."));
-- return 0;
-- }
-- }
--
-- /*
-- * These FLAP servers advertise SSL (type "0x02"), but SSL connections to these hosts
-- * die a painful death. iChat and Miranda, when using SSL, still do these in plaintext.
-- */
-- if (redir->use_ssl && (redir->group == SNAC_FAMILY_ADMIN ||
-- redir->group == SNAC_FAMILY_BART))
-- {
-- purple_debug_info("oscar", "Ignoring broken SSL for FLAP type 0x%04hx.\n", redir->group);
-- redir->use_ssl = 0;
-- }
--
-- purple_debug_info("oscar", "Connecting to FLAP server %s:%d of type 0x%04hx\n", host, port, redir->group);
--
-- newconn = flap_connection_new(od, redir->group);
-- newconn->cookielen = redir->cookielen;
-- newconn->cookie = g_memdup(redir->cookie, redir->cookielen);
-- if (newconn->type == SNAC_FAMILY_CHAT)
-- {
-- struct chat_connection *cc;
-- cc = g_new0(struct chat_connection, 1);
-- cc->conn = newconn;
-- cc->gc = gc;
-- cc->name = g_strdup(redir->chat.room);
-- cc->exchange = redir->chat.exchange;
-- cc->instance = redir->chat.instance;
-- cc->show = extract_name(redir->chat.room);
-- newconn->new_conn_data = cc;
-- purple_debug_info("oscar", "Connecting to chat room %s exchange %hu\n", cc->name, cc->exchange);
-- }
--
--
-- if (redir->use_ssl)
-- {
-- newconn->gsc = purple_ssl_connect_with_ssl_cn(account, host, port,
-- ssl_connection_established_cb, ssl_connection_error_cb,
-- redir->ssl_cert_cn, newconn);
-- }
-- else
-- {
-- newconn->connect_data = purple_proxy_connect(NULL, account, host, port,
-- connection_established_cb, newconn);
-- }
--
-- if (newconn->gsc == NULL && newconn->connect_data == NULL)
-- {
-- flap_connection_schedule_destroy(newconn,
-- OSCAR_DISCONNECT_COULD_NOT_CONNECT,
-- _("Unable to initialize connection"));
-- purple_debug_error("oscar", "Unable to connect to FLAP server "
-- "of type 0x%04hx\n", redir->group);
-- }
-- g_free(host);
--
-- return 1;
--}
--
--
--static int purple_parse_oncoming(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
--{
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- PurpleBuddy *buddy = NULL;
-- PurpleStatus *previous_status = NULL;
-- struct buddyinfo *bi;
-- time_t time_idle = 0, signon = 0;
-- int type = 0;
-- gboolean buddy_is_away = FALSE;
-- const char *status_id;
-- va_list ap;
-- aim_userinfo_t *info;
-- char *message;
-- char *itmsurl = NULL;
--
-- gc = od->gc;
-- account = purple_connection_get_account(gc);
--
-- va_start(ap, fr);
-- info = va_arg(ap, aim_userinfo_t *);
-- va_end(ap);
--
-- g_return_val_if_fail(info != NULL, 1);
-- g_return_val_if_fail(info->bn != NULL, 1);
--
-- buddy = purple_find_buddy(account, info->bn);
-- if (buddy) {
-- previous_status = purple_presence_get_active_status(purple_buddy_get_presence(buddy));
-- }
--
-- /*
-- * If this is an AIM buddy and their name has formatting, set their
-- * server alias.
-- */
-- if (!oscar_util_valid_name_icq(info->bn)) {
-- gboolean bn_has_formatting = FALSE;
-- char *c;
-- for (c = info->bn; *c != '\0'; c++) {
-- if (!islower(*c)) {
-- bn_has_formatting = TRUE;
-- break;
-- }
-- }
-- serv_got_alias(gc, info->bn,
-- bn_has_formatting ? info->bn : NULL);
-- }
--
-- if (info->present & AIM_USERINFO_PRESENT_FLAGS) {
-- if (info->flags & AIM_FLAG_AWAY)
-- buddy_is_away = TRUE;
-- }
-- if (info->present & AIM_USERINFO_PRESENT_ICQEXTSTATUS) {
-- type = info->icqinfo.status;
-- if (!(info->icqinfo.status & AIM_ICQ_STATE_CHAT) &&
-- (info->icqinfo.status != AIM_ICQ_STATE_NORMAL)) {
-- buddy_is_away = TRUE;
-- }
-- }
--
-- if (oscar_util_valid_name_icq(info->bn)) {
-- if (type & AIM_ICQ_STATE_CHAT)
-- status_id = OSCAR_STATUS_ID_FREE4CHAT;
-- else if (type & AIM_ICQ_STATE_DND)
-- status_id = OSCAR_STATUS_ID_DND;
-- else if (type & AIM_ICQ_STATE_OUT)
-- status_id = OSCAR_STATUS_ID_NA;
-- else if (type & AIM_ICQ_STATE_BUSY)
-- status_id = OSCAR_STATUS_ID_OCCUPIED;
-- else if (type & AIM_ICQ_STATE_AWAY)
-- status_id = OSCAR_STATUS_ID_AWAY;
-- else if (type & AIM_ICQ_STATE_INVISIBLE)
-- status_id = OSCAR_STATUS_ID_INVISIBLE;
-- else if (type & AIM_ICQ_STATE_EVIL)
-- status_id = OSCAR_STATUS_ID_EVIL;
-- else if (type & AIM_ICQ_STATE_DEPRESSION)
-- status_id = OSCAR_STATUS_ID_DEPRESSION;
-- else if (type & AIM_ICQ_STATE_ATHOME)
-- status_id = OSCAR_STATUS_ID_ATHOME;
-- else if (type & AIM_ICQ_STATE_ATWORK)
-- status_id = OSCAR_STATUS_ID_ATWORK;
-- else if (type & AIM_ICQ_STATE_LUNCH)
-- status_id = OSCAR_STATUS_ID_LUNCH;
-- else
-- status_id = OSCAR_STATUS_ID_AVAILABLE;
-- } else {
-- if (type & AIM_ICQ_STATE_INVISIBLE)
-- status_id = OSCAR_STATUS_ID_INVISIBLE;
-- else if (buddy_is_away)
-- status_id = OSCAR_STATUS_ID_AWAY;
-- else
-- status_id = OSCAR_STATUS_ID_AVAILABLE;
-- }
--
-- if (info->flags & AIM_FLAG_WIRELESS) {
-- purple_prpl_got_user_status(account, info->bn, OSCAR_STATUS_ID_MOBILE, NULL);
-- } else {
-- purple_prpl_got_user_status_deactive(account, info->bn, OSCAR_STATUS_ID_MOBILE);
-- }
--
-- message = (info->status && info->status_len > 0)
-- ? oscar_encoding_to_utf8(info->status_encoding, info->status, info->status_len)
-- : NULL;
--
-- if (strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE) == 0) {
-- /* TODO: If itmsurl is NULL, does that mean the URL has been
-- cleared? Or does it mean the URL should remain unchanged? */
-- if (info->itmsurl != NULL) {
-- itmsurl = (info->itmsurl_len > 0) ? oscar_encoding_to_utf8(info->itmsurl_encoding, info->itmsurl, info->itmsurl_len) : NULL;
-- } else if (previous_status != NULL && purple_status_is_available(previous_status)) {
-- itmsurl = g_strdup(purple_status_get_attr_string(previous_status, "itmsurl"));
-- }
-- purple_debug_info("oscar", "Activating status '%s' for buddy %s, message = '%s', itmsurl = '%s'\n", status_id, info->bn, message ? message : "(null)", itmsurl ? itmsurl : "(null)");
-- purple_prpl_got_user_status(account, info->bn, status_id, "message", message, "itmsurl", itmsurl, NULL);
-- } else {
-- purple_debug_info("oscar", "Activating status '%s' for buddy %s, message = '%s'\n", status_id, info->bn, message ? message : "(null)");
-- purple_prpl_got_user_status(account, info->bn, status_id, "message", message, NULL);
-- }
--
-- g_free(message);
-- g_free(itmsurl);
--
-- /* Login time stuff */
-- if (info->present & AIM_USERINFO_PRESENT_ONLINESINCE)
-- signon = info->onlinesince;
-- else if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN)
-- signon = time(NULL) - info->sessionlen;
-- purple_prpl_got_user_login_time(account, info->bn, signon);
--
-- /* Idle time stuff */
-- /* info->idletime is the number of minutes that this user has been idle */
-- if (info->present & AIM_USERINFO_PRESENT_IDLE)
-- time_idle = time(NULL) - info->idletime * 60;
--
-- if (time_idle > 0)
-- purple_prpl_got_user_idle(account, info->bn, TRUE, time_idle);
-- else
-- purple_prpl_got_user_idle(account, info->bn, FALSE, 0);
--
-- /* Server stored icon stuff */
-- bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, info->bn));
-- if (!bi) {
-- bi = g_new0(struct buddyinfo, 1);
-- g_hash_table_insert(od->buddyinfo, g_strdup(purple_normalize(account, info->bn)), bi);
-- }
-- bi->typingnot = FALSE;
-- bi->ico_informed = FALSE;
-- bi->ipaddr = info->icqinfo.ipaddr;
--
-- if (info->iconcsumlen) {
-- const char *saved_b16 = NULL;
-- char *b16 = NULL;
-- PurpleBuddy *b = NULL;
--
-- b16 = purple_base16_encode(info->iconcsum, info->iconcsumlen);
-- b = purple_find_buddy(account, info->bn);
-- if (b != NULL)
-- saved_b16 = purple_buddy_icons_get_checksum_for_user(b);
--
-- if (!b16 || !saved_b16 || strcmp(b16, saved_b16)) {
-- /* Invalidate the old icon for this user */
-- purple_buddy_icons_set_for_user(account, info->bn, NULL, 0, NULL);
--
-- /* Fetch the new icon (if we're not already doing so) */
-- if (g_slist_find_custom(od->requesticon, info->bn,
-- (GCompareFunc)oscar_util_name_compare) == NULL)
-- {
-- od->requesticon = g_slist_prepend(od->requesticon,
-- g_strdup(purple_normalize(account, info->bn)));
-- purple_icons_fetch(gc);
-- }
-- }
-- g_free(b16);
-- }
--
-- return 1;
--}
--
--static int purple_parse_offgoing(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- PurpleConnection *gc = od->gc;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- va_list ap;
-- aim_userinfo_t *info;
--
-- va_start(ap, fr);
-- info = va_arg(ap, aim_userinfo_t *);
-- va_end(ap);
--
-- purple_prpl_got_user_status(account, info->bn, OSCAR_STATUS_ID_OFFLINE, NULL);
-- purple_prpl_got_user_status_deactive(account, info->bn, OSCAR_STATUS_ID_MOBILE);
-- g_hash_table_remove(od->buddyinfo, purple_normalize(gc->account, info->bn));
--
-- return 1;
--}
--
--static int incomingim_chan1(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args) {
-- PurpleConnection *gc = od->gc;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- PurpleMessageFlags flags = 0;
-- struct buddyinfo *bi;
-- PurpleStoredImage *img;
-- gchar *tmp;
-- const char *start, *end;
-- GData *attribs;
--
-- purple_debug_misc("oscar", "Received IM from %s\n", userinfo->bn);
--
-- bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, userinfo->bn));
-- if (!bi) {
-- bi = g_new0(struct buddyinfo, 1);
-- g_hash_table_insert(od->buddyinfo, g_strdup(purple_normalize(account, userinfo->bn)), bi);
-- }
--
-- if (args->icbmflags & AIM_IMFLAGS_AWAY)
-- flags |= PURPLE_MESSAGE_AUTO_RESP;
--
-- if (args->icbmflags & AIM_IMFLAGS_TYPINGNOT)
-- bi->typingnot = TRUE;
-- else
-- bi->typingnot = FALSE;
--
-- if ((args->icbmflags & AIM_IMFLAGS_HASICON) && (args->iconlen) && (args->iconsum) && (args->iconstamp)) {
-- purple_debug_misc("oscar", "%s has an icon\n", userinfo->bn);
-- if ((args->iconlen != bi->ico_len) || (args->iconsum != bi->ico_csum) || (args->iconstamp != bi->ico_time)) {
-- bi->ico_need = TRUE;
-- bi->ico_len = args->iconlen;
-- bi->ico_csum = args->iconsum;
-- bi->ico_time = args->iconstamp;
-- }
-- }
--
-- img = purple_buddy_icons_find_account_icon(account);
-- if ((img != NULL) &&
-- (args->icbmflags & AIM_IMFLAGS_BUDDYREQ) && !bi->ico_sent && bi->ico_informed) {
-- gconstpointer data = purple_imgstore_get_data(img);
-- size_t len = purple_imgstore_get_size(img);
-- purple_debug_info("oscar",
-- "Sending buddy icon to %s (%" G_GSIZE_FORMAT " bytes)\n",
-- userinfo->bn, len);
-- aim_im_sendch2_icon(od, userinfo->bn, data, len,
-- purple_buddy_icons_get_account_icon_timestamp(account),
-- aimutil_iconsum(data, len));
-- }
-- purple_imgstore_unref(img);
--
-- tmp = g_strdup(args->msg);
--
-- /*
-- * Convert iChat color tags to normal font tags.
-- */
-- if (purple_markup_find_tag("body", tmp, &start, &end, &attribs))
-- {
-- int len;
-- char *tmp2, *body;
-- const char *ichattextcolor, *ichatballooncolor;
-- const char *slash_body_start, *slash_body_end = NULL; /* </body> */
-- GData *unused;
--
-- /*
-- * Find the ending </body> so we can strip off the outer <html/>
-- * and <body/>
-- */
-- if (purple_markup_find_tag("/body", end + 1, &slash_body_start, &slash_body_end, &unused))
-- {
-- body = g_strndup(start, slash_body_end - start + 1);
-- g_datalist_clear(&unused);
-- }
-- else
-- {
-- purple_debug_warning("oscar", "Broken message contains <body> but not </body>!\n");
-- /* Take everything after <body> */
-- body = g_strdup(start);
-- }
--
-- ichattextcolor = g_datalist_get_data(&attribs, "ichattextcolor");
-- if (ichattextcolor != NULL)
-- {
-- tmp2 = g_strdup_printf("<font color=\"%s\">%s</font>", ichattextcolor, body);
-- g_free(body);
-- body = tmp2;
-- }
--
-- ichatballooncolor = g_datalist_get_data(&attribs, "ichatballooncolor");
-- if (ichatballooncolor != NULL)
-- {
-- tmp2 = g_strdup_printf("<font back=\"%s\">%s</font>", ichatballooncolor, body);
-- g_free(body);
-- body = tmp2;
-- }
--
-- g_datalist_clear(&attribs);
--
-- len = start - tmp;
-- tmp2 = g_strdup_printf("%.*s%s%s", len, tmp, body, slash_body_end ? slash_body_end + 1: "</body>");
-- g_free(tmp);
-- g_free(body);
--
-- tmp = tmp2;
-- }
--
-- /*
-- * Are there <html/> surrounding tags? If so, strip them out, too.
-- */
-- if (purple_markup_find_tag("html", tmp, &start, &end, &attribs))
-- {
-- gchar *tmp2;
-- int len;
--
-- g_datalist_clear(&attribs);
--
-- len = start - tmp;
-- tmp2 = g_strdup_printf("%.*s%s", len, tmp, end + 1);
-- g_free(tmp);
-- tmp = tmp2;
-- }
--
-- if (purple_markup_find_tag("/html", tmp, &start, &end, &attribs))
-- {
-- gchar *tmp2;
-- int len;
--
-- g_datalist_clear(&attribs);
--
-- len = start - tmp;
-- tmp2 = g_strdup_printf("%.*s%s", len, tmp, end + 1);
-- g_free(tmp);
-- tmp = tmp2;
-- }
--
-- serv_got_im(gc, userinfo->bn, tmp, flags, (args->icbmflags & AIM_IMFLAGS_OFFLINE) ? args->timestamp : time(NULL));
-- g_free(tmp);
--
-- return 1;
--}
--
--static int
--incomingim_chan2(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo, IcbmArgsCh2 *args)
--{
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- PurpleMessageFlags flags = 0;
-- char *message = NULL;
--
-- g_return_val_if_fail(od != NULL, 0);
-- g_return_val_if_fail(od->gc != NULL, 0);
--
-- gc = od->gc;
-- account = purple_connection_get_account(gc);
-- od = purple_connection_get_protocol_data(gc);
--
-- if (args == NULL)
-- return 0;
--
-- purple_debug_misc("oscar", "Incoming rendezvous message of type %"
-- G_GUINT64_FORMAT ", user %s, status %hu\n",
-- args->type, userinfo->bn, args->status);
--
-- if (args->msg != NULL) {
-- message = oscar_encoding_to_utf8(args->encoding, args->msg, args->msglen);
-- }
--
-- if (args->type & OSCAR_CAPABILITY_CHAT)
-- {
-- char *utf8name, *tmp;
-- GHashTable *components;
--
-- if (!args->info.chat.roominfo.name || !args->info.chat.roominfo.exchange) {
-- g_free(message);
-- return 1;
-- }
-- utf8name = oscar_encoding_to_utf8(args->encoding, args->info.chat.roominfo.name, args->info.chat.roominfo.namelen);
--
-- tmp = extract_name(utf8name);
-- if (tmp != NULL)
-- {
-- g_free(utf8name);
-- utf8name = tmp;
-- }
--
-- components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
-- g_free);
-- g_hash_table_replace(components, g_strdup("room"), utf8name);
-- g_hash_table_replace(components, g_strdup("exchange"),
-- g_strdup_printf("%d", args->info.chat.roominfo.exchange));
-- serv_got_chat_invite(gc,
-- utf8name,
-- userinfo->bn,
-- message,
-- components);
-- }
--
-- else if ((args->type & OSCAR_CAPABILITY_SENDFILE) || (args->type & OSCAR_CAPABILITY_DIRECTIM))
-- {
-- if (args->status == AIM_RENDEZVOUS_PROPOSE)
-- {
-- peer_connection_got_proposition(od, userinfo->bn, message, args);
-- }
-- else if (args->status == AIM_RENDEZVOUS_CANCEL)
-- {
-- /* The other user cancelled a peer request */
-- PeerConnection *conn;
--
-- conn = peer_connection_find_by_cookie(od, userinfo->bn, args->cookie);
-- /*
-- * If conn is NULL it means we haven't tried to create
-- * a connection with that user. They may be trying to
-- * do something malicious.
-- */
-- if (conn != NULL)
-- {
-- peer_connection_destroy(conn, OSCAR_DISCONNECT_REMOTE_CLOSED, NULL);
-- }
-- }
-- else if (args->status == AIM_RENDEZVOUS_CONNECTED)
-- {
-- /*
-- * Remote user has accepted our peer request. If we
-- * wanted to we could look up the PeerConnection using
-- * args->cookie, but we don't need to do anything here.
-- */
-- }
-- }
--
-- else if (args->type & OSCAR_CAPABILITY_GETFILE)
-- {
-- }
--
-- else if (args->type & OSCAR_CAPABILITY_TALK)
-- {
-- }
--
-- else if (args->type & OSCAR_CAPABILITY_BUDDYICON)
-- {
-- purple_buddy_icons_set_for_user(account, userinfo->bn,
-- g_memdup(args->info.icon.icon, args->info.icon.length),
-- args->info.icon.length,
-- NULL);
-- }
--
-- else if (args->type & OSCAR_CAPABILITY_ICQSERVERRELAY)
-- {
-- purple_debug_info("oscar", "Got an ICQ Server Relay message of "
-- "type %d\n", args->info.rtfmsg.msgtype);
--
-- if (args->info.rtfmsg.msgtype == 1) {
-- if (args->info.rtfmsg.msg != NULL) {
-- char *rtfmsg;
-- const char *encoding = args->encoding;
-- size_t len = strlen(args->info.rtfmsg.msg);
-- char *tmp, *tmp2;
--
-- if (encoding == NULL && !g_utf8_validate(args->info.rtfmsg.msg, len, NULL)) {
-- /* Yet another wonderful Miranda-related hack. If their user disables the "Send Unicode messages" setting,
-- * Miranda sends us ch2 messages in whatever Windows codepage is set as default on their user's system (instead of UTF-8).
-- * Of course, they don't bother to specify that codepage. Let's just fallback to the encoding OUR users can
-- * specify in account options as a last resort.
-- */
-- encoding = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING);
-- purple_debug_info("oscar", "Miranda, is that you? Using '%s' as encoding\n", encoding);
-- }
--
-- rtfmsg = oscar_encoding_to_utf8(encoding, args->info.rtfmsg.msg, len);
--
-- /* Channel 2 messages are supposed to be plain-text (never mind the name "rtfmsg", even
-- * the official client doesn't parse them as RTF). Therefore, we should escape them before
-- * showing to the user. */
-- tmp = g_markup_escape_text(rtfmsg, -1);
-- g_free(rtfmsg);
-- tmp2 = purple_strreplace(tmp, "\r\n", "<br>");
-- g_free(tmp);
--
-- serv_got_im(gc, userinfo->bn, tmp2, flags, time(NULL));
-- aim_im_send_icq_confirmation(od, userinfo->bn, args->cookie);
-- g_free(tmp2);
-- }
-- } else if (args->info.rtfmsg.msgtype == 26) {
-- purple_debug_info("oscar", "Sending X-Status Reply\n");
-- icq_relay_xstatus(od, userinfo->bn, args->cookie);
-- }
-- }
-- else
-- {
-- purple_debug_error("oscar", "Unknown request class %"
-- G_GUINT64_FORMAT "\n", args->type);
-- }
--
-- g_free(message);
--
-- return 1;
--}
--
--/* When someone sends you buddies */
--static void
--purple_icq_buddyadd(struct name_data *data)
--{
-- PurpleConnection *gc = data->gc;
--
-- purple_blist_request_add_buddy(purple_connection_get_account(gc), data->name, NULL, data->nick);
--
-- oscar_free_name_data(data);
--}
--
--static int
--incomingim_chan4(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch4_args *args, time_t t)
--{
-- PurpleConnection *gc = od->gc;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- gchar **msg1, **msg2;
-- int i, numtoks;
--
-- if (!args->type || !args->msg || !args->uin)
-- return 1;
--
-- purple_debug_info("oscar",
-- "Received a channel 4 message of type 0x%02hx.\n",
-- args->type);
--
-- /*
-- * Split up the message at the delimeter character, then convert each
-- * string to UTF-8. Unless, of course, this is a type 1 message. If
-- * this is a type 1 message, then the delimiter 0xfe could be a valid
-- * character in whatever encoding the message was sent in. Type 1
-- * messages are always made up of only one part, so we can easily account
-- * for this suck-ass part of the protocol by splitting the string into at
-- * most 1 baby string.
-- */
-- msg1 = g_strsplit(args->msg, "\376", (args->type == 0x01 ? 1 : 0));
-- for (numtoks=0; msg1[numtoks]; numtoks++);
-- msg2 = (gchar **)g_malloc((numtoks+1)*sizeof(gchar *));
-- for (i=0; msg1[i]; i++) {
-- gchar *uin = g_strdup_printf("%u", args->uin);
--
-- purple_str_strip_char(msg1[i], '\r');
-- /* TODO: Should use an encoding other than ASCII? */
-- msg2[i] = oscar_decode_im(account, uin, AIM_CHARSET_ASCII, msg1[i], strlen(msg1[i]));
-- g_free(uin);
-- }
-- msg2[i] = NULL;
--
-- switch (args->type) {
-- case 0x01: { /* MacICQ message or basic offline message */
-- if (i >= 1) {
-- gchar *uin = g_strdup_printf("%u", args->uin);
-- gchar *tmp;
--
-- /* If the message came from an ICQ user then escape any HTML */
-- tmp = g_markup_escape_text(msg2[0], -1);
--
-- if (t) { /* This is an offline message */
-- /* The timestamp is UTC-ish, so we need to get the offset */
--#ifdef HAVE_TM_GMTOFF
-- time_t now;
-- struct tm *tm;
-- now = time(NULL);
-- tm = localtime(&now);
-- t += tm->tm_gmtoff;
--#else
--# ifdef HAVE_TIMEZONE
-- tzset();
-- t -= timezone;
--# endif
--#endif
-- serv_got_im(gc, uin, tmp, 0, t);
-- } else { /* This is a message from MacICQ/Miranda */
-- serv_got_im(gc, uin, tmp, 0, time(NULL));
-- }
-- g_free(uin);
-- g_free(tmp);
-- }
-- } break;
--
-- case 0x04: { /* Someone sent you a URL */
-- if (i >= 2) {
-- if (msg2[1] != NULL) {
-- gchar *uin = g_strdup_printf("%u", args->uin);
-- gchar *message = g_strdup_printf("<A HREF=\"%s\">%s</A>",
-- msg2[1],
-- (msg2[0] && msg2[0][0]) ? msg2[0] : msg2[1]);
-- serv_got_im(gc, uin, message, 0, time(NULL));
-- g_free(uin);
-- g_free(message);
-- }
-- }
-- } break;
--
-- case 0x06: { /* Someone requested authorization */
-- if (i >= 6) {
-- gchar *bn = g_strdup_printf("%u", args->uin);
-- gchar *reason = NULL;
--
-- if (msg2[5] != NULL)
-- reason = oscar_decode_im(account, bn, AIM_CHARSET_LATIN_1, msg2[5], strlen(msg2[5]));
--
-- purple_debug_info("oscar",
-- "Received an authorization request from UIN %u\n",
-- args->uin);
-- aim_icq_getalias(od, bn, TRUE, reason);
-- g_free(bn);
-- g_free(reason);
-- }
-- } break;
--
-- case 0x07: { /* Someone has denied you authorization */
-- if (i >= 1) {
-- gchar *dialog_msg = g_strdup_printf(_("The user %u has denied your request to add them to your buddy list for the following reason:\n%s"), args->uin, msg2[0] ? msg2[0] : _("No reason given."));
-- purple_notify_info(gc, NULL, _("ICQ authorization denied."),
-- dialog_msg);
-- g_free(dialog_msg);
-- }
-- } break;
--
-- case 0x08: { /* Someone has granted you authorization */
-- gchar *dialog_msg = g_strdup_printf(_("The user %u has granted your request to add them to your buddy list."), args->uin);
-- purple_notify_info(gc, NULL, "ICQ authorization accepted.",
-- dialog_msg);
-- g_free(dialog_msg);
-- } break;
--
-- case 0x09: { /* Message from the Godly ICQ server itself, I think */
-- if (i >= 5) {
-- gchar *dialog_msg = g_strdup_printf(_("You have received a special message\n\nFrom: %s [%s]\n%s"), msg2[0], msg2[3], msg2[5]);
-- purple_notify_info(gc, NULL, "ICQ Server Message", dialog_msg);
-- g_free(dialog_msg);
-- }
-- } break;
--
-- case 0x0d: { /* Someone has sent you a pager message from http://www.icq.com/your_uin */
-- if (i >= 6) {
-- gchar *dialog_msg = g_strdup_printf(_("You have received an ICQ page\n\nFrom: %s [%s]\n%s"), msg2[0], msg2[3], msg2[5]);
-- purple_notify_info(gc, NULL, "ICQ Page", dialog_msg);
-- g_free(dialog_msg);
-- }
-- } break;
--
-- case 0x0e: { /* Someone has emailed you at your_uin@pager.icq.com */
-- if (i >= 6) {
-- gchar *dialog_msg = g_strdup_printf(_("You have received an ICQ email from %s [%s]\n\nMessage is:\n%s"), msg2[0], msg2[3], msg2[5]);
-- purple_notify_info(gc, NULL, "ICQ Email", dialog_msg);
-- g_free(dialog_msg);
-- }
-- } break;
--
-- case 0x12: {
-- /* Ack for authorizing/denying someone. Or possibly an ack for sending any system notice */
-- /* Someone added you to their buddy list? */
-- } break;
--
-- case 0x13: { /* Someone has sent you some ICQ buddies */
-- guint i, num;
-- gchar **text;
-- text = g_strsplit(args->msg, "\376", 0);
-- if (text) {
-- /* Read the number of contacts that we were sent */
-- errno = 0;
-- num = text[0] ? strtoul(text[0], NULL, 10) : 0;
--
-- if (num > 0 && errno == 0) {
-- for (i=0; i<num; i++) {
-- struct name_data *data;
-- gchar *message;
--
-- if (!text[i*2 + 1] || !text[i*2 + 2]) {
-- /* We're missing the contact name or nickname. Bail out. */
-- gchar *tmp = g_strescape(args->msg, NULL);
-- purple_debug_error("oscar", "Unknown syntax parsing "
-- "ICQ buddies. args->msg=%s\n", tmp);
-- g_free(tmp);
-- break;
-- }
--
-- message = g_strdup_printf(_("ICQ user %u has sent you a buddy: %s (%s)"), args->uin, text[i*2+2], text[i*2+1]);
--
-- data = g_new(struct name_data, 1);
-- data->gc = gc;
-- data->name = g_strdup(text[i*2+1]);
-- data->nick = g_strdup(text[i*2+2]);
--
-- purple_request_action(gc, NULL, message,
-- _("Do you want to add this buddy "
-- "to your buddy list?"),
-- PURPLE_DEFAULT_ACTION_NONE,
-- purple_connection_get_account(gc), data->name, NULL,
-- data, 2,
-- _("_Add"), G_CALLBACK(purple_icq_buddyadd),
-- _("_Decline"), G_CALLBACK(oscar_free_name_data));
-- g_free(message);
-- }
-- } else {
-- gchar *tmp = g_strescape(args->msg, NULL);
-- purple_debug_error("oscar", "Unknown syntax parsing "
-- "ICQ buddies. args->msg=%s\n", tmp);
-- g_free(tmp);
-- }
-- g_strfreev(text);
-- }
-- } break;
--
-- case 0x1a: { /* Handle SMS or someone has sent you a greeting card or requested buddies? */
-- ByteStream qbs;
-- guint16 smstype;
-- guint32 taglen, smslen;
-- char *tagstr = NULL, *smsmsg = NULL;
-- xmlnode *xmlroot = NULL, *xmltmp = NULL;
-- gchar *uin = NULL, *message = NULL;
--
-- /* From libicq2000-0.3.2/src/ICQ.cpp */
-- byte_stream_init(&qbs, (guint8 *)args->msg, args->msglen);
-- byte_stream_advance(&qbs, 21);
-- /* expected: 01 00 00 20 00 0e 28 f6 00 11 e7 d3 11 bc f3 00 04 ac 96 9d c2 | 00 00 | 06 00 00 00 | 49 43 51 53 43 53 ...*/
-- /* unexpected: 00 00 26 00 81 1a 18 bc 0e 6c 18 47 a5 91 6f 18 dc c7 6f 1a | 00 00 | 0d 00 00 00 | 49 43 51 57 65 62 4d 65 73 73 61 67 65 ... */
-- smstype = byte_stream_getle16(&qbs);
-- if (smstype != 0)
-- break;
-- taglen = byte_stream_getle32(&qbs);
-- if (taglen > 2000) {
-- /* Avoid trying to allocate large amounts of memory, in
-- case we get something unexpected. */
-- break;
-- }
-- tagstr = byte_stream_getstr(&qbs, taglen);
-- if (tagstr == NULL)
-- break;
-- byte_stream_advance(&qbs, 3);
-- byte_stream_advance(&qbs, 4);
-- smslen = byte_stream_getle32(&qbs);
-- if (smslen > 2000) {
-- /* Avoid trying to allocate large amounts of memory, in
-- case we get something unexpected. */
-- g_free(tagstr);
-- break;
-- }
-- smsmsg = byte_stream_getstr(&qbs, smslen);
--
-- /* Check if this is an SMS being sent from server */
-- if ((smstype == 0) && (!strcmp(tagstr, "ICQSMS")) && (smsmsg != NULL))
-- {
-- xmlroot = xmlnode_from_str(smsmsg, -1);
-- if (xmlroot != NULL)
-- {
-- xmltmp = xmlnode_get_child(xmlroot, "sender");
-- if (xmltmp != NULL)
-- uin = xmlnode_get_data(xmltmp);
--
-- xmltmp = xmlnode_get_child(xmlroot, "text");
-- if (xmltmp != NULL)
-- message = xmlnode_get_data(xmltmp);
--
-- if ((uin != NULL) && (message != NULL))
-- serv_got_im(gc, uin, message, 0, time(NULL));
--
-- g_free(uin);
-- g_free(message);
-- xmlnode_free(xmlroot);
-- }
-- }
-- g_free(tagstr);
-- g_free(smsmsg);
-- } break;
--
-- default: {
-- purple_debug_info("oscar",
-- "Received a channel 4 message of unknown type "
-- "(type 0x%02hhx).\n", args->type);
-- } break;
-- }
--
-- g_strfreev(msg1);
-- g_strfreev(msg2);
--
-- return 1;
--}
--
--static int purple_parse_incoming_im(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- guint16 channel;
-- int ret = 0;
-- aim_userinfo_t *userinfo;
-- va_list ap;
--
-- va_start(ap, fr);
-- channel = (guint16)va_arg(ap, unsigned int);
-- userinfo = va_arg(ap, aim_userinfo_t *);
--
-- switch (channel) {
-- case 1: { /* standard message */
-- struct aim_incomingim_ch1_args *args;
-- args = va_arg(ap, struct aim_incomingim_ch1_args *);
-- ret = incomingim_chan1(od, conn, userinfo, args);
-- } break;
--
-- case 2: { /* rendezvous */
-- IcbmArgsCh2 *args;
-- args = va_arg(ap, IcbmArgsCh2 *);
-- ret = incomingim_chan2(od, conn, userinfo, args);
-- } break;
--
-- case 4: { /* ICQ */
-- struct aim_incomingim_ch4_args *args;
-- args = va_arg(ap, struct aim_incomingim_ch4_args *);
-- ret = incomingim_chan4(od, conn, userinfo, args, 0);
-- } break;
--
-- default: {
-- purple_debug_warning("oscar",
-- "ICBM received on unsupported channel (channel "
-- "0x%04hx).", channel);
-- } break;
-- }
--
-- va_end(ap);
--
-- return ret;
--}
--
--static int purple_parse_misses(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- PurpleConnection *gc = od->gc;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- char *buf;
-- va_list ap;
-- guint16 chan, nummissed, reason;
-- aim_userinfo_t *userinfo;
--
-- va_start(ap, fr);
-- chan = (guint16)va_arg(ap, unsigned int);
-- userinfo = va_arg(ap, aim_userinfo_t *);
-- nummissed = (guint16)va_arg(ap, unsigned int);
-- reason = (guint16)va_arg(ap, unsigned int);
-- va_end(ap);
--
-- switch(reason) {
-- case 0: /* Invalid (0) */
-- buf = g_strdup_printf(
-- dngettext(PACKAGE,
-- "You missed %hu message from %s because it was invalid.",
-- "You missed %hu messages from %s because they were invalid.",
-- nummissed),
-- nummissed,
-- userinfo->bn);
-- break;
-- case 1: /* Message too large */
-- buf = g_strdup_printf(
-- dngettext(PACKAGE,
-- "You missed %hu message from %s because it was too large.",
-- "You missed %hu messages from %s because they were too large.",
-- nummissed),
-- nummissed,
-- userinfo->bn);
-- break;
-- case 2: /* Rate exceeded */
-- buf = g_strdup_printf(
-- dngettext(PACKAGE,
-- "You missed %hu message from %s because the rate limit has been exceeded.",
-- "You missed %hu messages from %s because the rate limit has been exceeded.",
-- nummissed),
-- nummissed,
-- userinfo->bn);
-- break;
-- case 3: /* Evil Sender */
-- buf = g_strdup_printf(
-- dngettext(PACKAGE,
-- "You missed %hu message from %s because his/her warning level is too high.",
-- "You missed %hu messages from %s because his/her warning level is too high.",
-- nummissed),
-- nummissed,
-- userinfo->bn);
-- break;
-- case 4: /* Evil Receiver */
-- buf = g_strdup_printf(
-- dngettext(PACKAGE,
-- "You missed %hu message from %s because your warning level is too high.",
-- "You missed %hu messages from %s because your warning level is too high.",
-- nummissed),
-- nummissed,
-- userinfo->bn);
-- break;
-- default:
-- buf = g_strdup_printf(
-- dngettext(PACKAGE,
-- "You missed %hu message from %s for an unknown reason.",
-- "You missed %hu messages from %s for an unknown reason.",
-- nummissed),
-- nummissed,
-- userinfo->bn);
-- break;
-- }
--
-- if (!purple_conv_present_error(userinfo->bn, account, buf))
-- purple_notify_error(od->gc, NULL, buf, NULL);
-- g_free(buf);
--
-- return 1;
--}
--
--static int
--purple_parse_clientauto_ch2(OscarData *od, const char *who, guint16 reason, const guchar *cookie)
--{
-- if (reason == 0x0003)
-- {
-- /* Rendezvous was refused. */
-- PeerConnection *conn;
--
-- conn = peer_connection_find_by_cookie(od, who, cookie);
--
-- if (conn == NULL)
-- {
-- purple_debug_info("oscar", "Received a rendezvous cancel message "
-- "for a nonexistant connection from %s.\n", who);
-- }
-- else
-- {
-- peer_connection_destroy(conn, OSCAR_DISCONNECT_REMOTE_REFUSED, NULL);
-- }
-- }
-- else
-- {
-- purple_debug_warning("oscar", "Received an unknown rendezvous "
-- "message from %s. Type 0x%04hx\n", who, reason);
-- }
--
-- return 0;
--}
--
--static int purple_parse_clientauto_ch4(OscarData *od, char *who, guint16 reason, guint32 state, char *msg) {
-- PurpleConnection *gc = od->gc;
--
-- switch(reason) {
-- case 0x0003: { /* Reply from an ICQ status message request */
-- char *statusmsg, **splitmsg;
-- PurpleNotifyUserInfo *user_info;
--
-- /* Split at (carriage return/newline)'s, then rejoin later with BRs between. */
-- statusmsg = oscar_icqstatus(state);
-- splitmsg = g_strsplit(msg, "\r\n", 0);
--
-- user_info = purple_notify_user_info_new();
--
-- purple_notify_user_info_add_pair(user_info, _("UIN"), who);
-- purple_notify_user_info_add_pair(user_info, _("Status"), statusmsg);
-- purple_notify_user_info_add_section_break(user_info);
-- purple_notify_user_info_add_pair(user_info, NULL, g_strjoinv("<BR>", splitmsg));
--
-- g_free(statusmsg);
-- g_strfreev(splitmsg);
--
-- purple_notify_userinfo(gc, who, user_info, NULL, NULL);
-- purple_notify_user_info_destroy(user_info);
--
-- } break;
--
-- case 0x0006: { /* Reply from an ICQ status message request */
-- char *statusmsg, **splitmsg;
-- PurpleNotifyUserInfo *user_info;
--
-- /* Split at (carriage return/newline)'s, then rejoin later with BRs between. */
-- statusmsg = oscar_icqstatus(state);
-- splitmsg = g_strsplit(msg, "\r\n", 0);
--
-- user_info = purple_notify_user_info_new();
--
-- purple_notify_user_info_add_pair(user_info, _("UIN"), who);
-- purple_notify_user_info_add_pair(user_info, _("Status"), statusmsg);
-- purple_notify_user_info_add_section_break(user_info);
-- purple_notify_user_info_add_pair(user_info, NULL, g_strjoinv("<BR>", splitmsg));
--
-- g_free(statusmsg);
-- g_strfreev(splitmsg);
--
-- purple_notify_userinfo(gc, who, user_info, NULL, NULL);
-- purple_notify_user_info_destroy(user_info);
--
-- } break;
--
-- default: {
-- purple_debug_warning("oscar",
-- "Received an unknown client auto-response from %s. "
-- "Type 0x%04hx\n", who, reason);
-- } break;
-- } /* end of switch */
--
-- return 0;
--}
--
--static int purple_parse_clientauto(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- va_list ap;
-- guint16 chan, reason;
-- char *who;
-- int ret = 1;
--
-- va_start(ap, fr);
-- chan = (guint16)va_arg(ap, unsigned int);
-- who = va_arg(ap, char *);
-- reason = (guint16)va_arg(ap, unsigned int);
--
-- if (chan == 0x0002) { /* File transfer declined */
-- guchar *cookie = va_arg(ap, guchar *);
-- ret = purple_parse_clientauto_ch2(od, who, reason, cookie);
-- } else if (chan == 0x0004) { /* ICQ message */
-- guint32 state = 0;
-- char *msg = NULL;
-- if (reason == 0x0003) {
-- state = va_arg(ap, guint32);
-- msg = va_arg(ap, char *);
-- }
-- ret = purple_parse_clientauto_ch4(od, who, reason, state, msg);
-- }
--
-- va_end(ap);
--
-- return ret;
--}
--
--static int purple_parse_genericerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- va_list ap;
-- guint16 reason;
--
-- va_start(ap, fr);
-- reason = (guint16) va_arg(ap, unsigned int);
-- va_end(ap);
--
-- purple_debug_error("oscar", "snac threw error (reason 0x%04hx: %s)\n",
-- reason, oscar_get_msgerr_reason(reason));
-- return 1;
--}
--
--static int purple_parse_mtn(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- PurpleConnection *gc = od->gc;
-- va_list ap;
-- guint16 channel, event;
-- char *bn;
--
-- va_start(ap, fr);
-- channel = (guint16) va_arg(ap, unsigned int);
-- bn = va_arg(ap, char *);
-- event = (guint16) va_arg(ap, unsigned int);
-- va_end(ap);
--
-- switch (event) {
-- case 0x0000: { /* Text has been cleared */
-- serv_got_typing_stopped(gc, bn);
-- } break;
--
-- case 0x0001: { /* Paused typing */
-- serv_got_typing(gc, bn, 0, PURPLE_TYPED);
-- } break;
--
-- case 0x0002: { /* Typing */
-- serv_got_typing(gc, bn, 0, PURPLE_TYPING);
-- } break;
--
-- case 0x000f: { /* Closed IM window */
-- serv_got_typing_stopped(gc, bn);
-- } break;
--
-- default: {
-- purple_debug_info("oscar", "Received unknown typing "
-- "notification message from %s. Channel is 0x%04x "
-- "and event is 0x%04hx.\n", bn, channel, event);
-- } break;
-- }
--
-- return 1;
--}
--
--static int purple_parse_motd(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
--{
-- char *msg;
-- guint16 id;
-- va_list ap;
--
-- va_start(ap, fr);
-- id = (guint16) va_arg(ap, unsigned int);
-- msg = va_arg(ap, char *);
-- va_end(ap);
--
-- purple_debug_misc("oscar",
-- "MOTD: %s (%hu)\n", msg ? msg : "Unknown", id);
-- if (id < 4)
-- purple_notify_warning(od->gc, NULL,
-- _("Your AIM connection may be lost."), NULL);
--
-- return 1;
--}
--
--static int purple_chatnav_info(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- va_list ap;
-- guint16 type;
--
-- va_start(ap, fr);
-- type = (guint16) va_arg(ap, unsigned int);
--
-- switch(type) {
-- case 0x0002: {
-- GString *msg = g_string_new("");
-- guint8 maxrooms;
-- struct aim_chat_exchangeinfo *exchanges;
-- int exchangecount, i;
--
-- maxrooms = (guint8) va_arg(ap, unsigned int);
-- exchangecount = va_arg(ap, int);
-- exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
--
-- g_string_append_printf(msg, "chat info: Max Concurrent Rooms: %hhd, Exchange List (%d total): ", maxrooms, exchangecount);
-- for (i = 0; i < exchangecount; i++) {
-- g_string_append_printf(msg, "%hu", exchanges[i].number);
-- if (exchanges[i].name) {
-- g_string_append_printf(msg, " %s", exchanges[i].name);
-- }
-- g_string_append(msg, ", ");
-- }
-- purple_debug_misc("oscar", "%s\n", msg->str);
-- g_string_free(msg, TRUE);
--
-- while (od->create_rooms) {
-- struct create_room *cr = od->create_rooms->data;
-- purple_debug_info("oscar",
-- "creating room %s\n", cr->name);
-- aim_chatnav_createroom(od, conn, cr->name, cr->exchange);
-- g_free(cr->name);
-- od->create_rooms = g_slist_remove(od->create_rooms, cr);
-- g_free(cr);
-- }
-- }
-- break;
-- case 0x0008: {
-- char *fqcn, *name, *ck;
-- guint16 instance, flags, maxmsglen, maxoccupancy, unknown, exchange;
-- guint8 createperms;
-- guint32 createtime;
--
-- fqcn = va_arg(ap, char *);
-- instance = (guint16)va_arg(ap, unsigned int);
-- exchange = (guint16)va_arg(ap, unsigned int);
-- flags = (guint16)va_arg(ap, unsigned int);
-- createtime = va_arg(ap, guint32);
-- maxmsglen = (guint16)va_arg(ap, unsigned int);
-- maxoccupancy = (guint16)va_arg(ap, unsigned int);
-- createperms = (guint8)va_arg(ap, unsigned int);
-- unknown = (guint16)va_arg(ap, unsigned int);
-- name = va_arg(ap, char *);
-- ck = va_arg(ap, char *);
--
-- purple_debug_misc("oscar",
-- "created room: %s %hu %hu %hu %u %hu %hu %hhu %hu %s %s\n",
-- fqcn ? fqcn : "(null)", exchange, instance, flags, createtime,
-- maxmsglen, maxoccupancy, createperms, unknown,
-- name ? name : "(null)", ck);
-- aim_chat_join(od, exchange, ck, instance);
-- }
-- break;
-- default:
-- purple_debug_warning("oscar",
-- "chatnav info: unknown type (%04hx)\n", type);
-- break;
-- }
--
-- va_end(ap);
--
-- return 1;
--}
--
--static int purple_conv_chat_join(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- va_list ap;
-- int count, i;
-- aim_userinfo_t *info;
-- PurpleConnection *gc = od->gc;
--
-- struct chat_connection *c = NULL;
--
-- va_start(ap, fr);
-- count = va_arg(ap, int);
-- info = va_arg(ap, aim_userinfo_t *);
-- va_end(ap);
--
-- c = find_oscar_chat_by_conn(gc, conn);
-- if (!c)
-- return 1;
--
-- for (i = 0; i < count; i++)
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(c->conv), info[i].bn, NULL, PURPLE_CBFLAGS_NONE, TRUE);
--
-- return 1;
--}
--
--static int purple_conv_chat_leave(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- va_list ap;
-- int count, i;
-- aim_userinfo_t *info;
-- PurpleConnection *gc = od->gc;
--
-- struct chat_connection *c = NULL;
--
-- va_start(ap, fr);
-- count = va_arg(ap, int);
-- info = va_arg(ap, aim_userinfo_t *);
-- va_end(ap);
--
-- c = find_oscar_chat_by_conn(gc, conn);
-- if (!c)
-- return 1;
--
-- for (i = 0; i < count; i++)
-- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(c->conv), info[i].bn, NULL);
--
-- return 1;
--}
--
--static int purple_conv_chat_info_update(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- va_list ap;
-- guint16 maxmsglen, maxvisiblemsglen;
-- PurpleConnection *gc = od->gc;
-- struct chat_connection *ccon = find_oscar_chat_by_conn(gc, conn);
--
-- if (!ccon)
-- return 1;
--
-- va_start(ap, fr);
-- maxmsglen = (guint16)va_arg(ap, unsigned int);
-- maxvisiblemsglen = (guint16)va_arg(ap, unsigned int);
-- va_end(ap);
--
-- purple_debug_misc("oscar",
-- "inside chat_info_update (maxmsglen = %hu, maxvislen = %hu)\n",
-- maxmsglen, maxvisiblemsglen);
--
-- ccon->maxlen = maxmsglen;
-- ccon->maxvis = maxvisiblemsglen;
--
-- return 1;
--}
--
--static int purple_conv_chat_incoming_msg(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- PurpleConnection *gc = od->gc;
-- struct chat_connection *ccon = find_oscar_chat_by_conn(gc, conn);
-- gchar *utf8;
-- va_list ap;
-- aim_userinfo_t *info;
-- int len;
-- char *msg;
-- char *charset;
--
-- if (!ccon)
-- return 1;
--
-- va_start(ap, fr);
-- info = va_arg(ap, aim_userinfo_t *);
-- len = va_arg(ap, int);
-- msg = va_arg(ap, char *);
-- charset = va_arg(ap, char *);
-- va_end(ap);
--
-- utf8 = oscar_encoding_to_utf8(charset, msg, len);
-- serv_got_chat_in(gc, ccon->id, info->bn, 0, utf8, time(NULL));
-- g_free(utf8);
--
-- return 1;
--}
--
--static int purple_email_parseupdate(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- va_list ap;
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- struct aim_emailinfo *emailinfo;
-- int havenewmail;
-- char *alertitle, *alerturl;
--
-- gc = od->gc;
-- account = purple_connection_get_account(gc);
--
-- va_start(ap, fr);
-- emailinfo = va_arg(ap, struct aim_emailinfo *);
-- havenewmail = va_arg(ap, int);
-- alertitle = va_arg(ap, char *);
-- alerturl = va_arg(ap, char *);
-- va_end(ap);
--
-- if (account != NULL && emailinfo != NULL && purple_account_get_check_mail(account) &&
-- emailinfo->unread && havenewmail) {
-- gchar *to = g_strdup_printf("%s%s%s",
-- purple_account_get_username(account),
-- emailinfo->domain ? "@" : "",
-- emailinfo->domain ? emailinfo->domain : "");
-- const char *tos[2] = { to };
-- const char *urls[2] = { emailinfo->url };
-- purple_notify_emails(gc, emailinfo->nummsgs, FALSE, NULL, NULL,
-- tos, urls, NULL, NULL);
-- g_free(to);
-- }
--
-- if (alertitle)
-- purple_debug_misc("oscar", "Got an alert '%s' %s\n", alertitle, alerturl ? alerturl : "");
--
-- return 1;
--}
--
--static int purple_icon_parseicon(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- PurpleConnection *gc = od->gc;
-- va_list ap;
-- char *bn;
-- guint8 iconcsumtype, *iconcsum, *icon;
-- guint16 iconcsumlen, iconlen;
--
-- va_start(ap, fr);
-- bn = va_arg(ap, char *);
-- iconcsumtype = va_arg(ap, int);
-- iconcsum = va_arg(ap, guint8 *);
-- iconcsumlen = va_arg(ap, int);
-- icon = va_arg(ap, guint8 *);
-- iconlen = va_arg(ap, int);
-- va_end(ap);
--
-- /*
-- * Some AIM clients will send a blank GIF image with iconlen 90 when
-- * no icon is set. Ignore these.
-- */
-- if ((iconlen > 0) && (iconlen != 90)) {
-- char *b16 = purple_base16_encode(iconcsum, iconcsumlen);
-- purple_buddy_icons_set_for_user(purple_connection_get_account(gc),
-- bn, g_memdup(icon, iconlen), iconlen, b16);
-- g_free(b16);
-- }
--
-- return 1;
--}
--
--static void
--purple_icons_fetch(PurpleConnection *gc)
--{
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- aim_userinfo_t *userinfo;
-- FlapConnection *conn;
--
-- conn = flap_connection_getbytype(od, SNAC_FAMILY_BART);
-- if (!conn) {
-- if (!od->iconconnecting) {
-- aim_srv_requestnew(od, SNAC_FAMILY_BART);
-- od->iconconnecting = TRUE;
-- }
-- return;
-- }
--
-- if (od->set_icon) {
-- PurpleAccount *account = purple_connection_get_account(gc);
-- PurpleStoredImage *img = purple_buddy_icons_find_account_icon(account);
-- if (img == NULL) {
-- aim_ssi_delicon(od);
-- } else {
-- purple_debug_info("oscar",
-- "Uploading icon to icon server\n");
-- aim_bart_upload(od, purple_imgstore_get_data(img),
-- purple_imgstore_get_size(img));
-- purple_imgstore_unref(img);
-- }
-- od->set_icon = FALSE;
-- }
--
-- while (od->requesticon != NULL)
-- {
-- userinfo = aim_locate_finduserinfo(od, (char *)od->requesticon->data);
-- if ((userinfo != NULL) && (userinfo->iconcsumlen > 0))
-- aim_bart_request(od, od->requesticon->data, userinfo->iconcsumtype, userinfo->iconcsum, userinfo->iconcsumlen);
--
-- g_free(od->requesticon->data);
-- od->requesticon = g_slist_delete_link(od->requesticon, od->requesticon);
-- }
--
-- purple_debug_misc("oscar", "no more icons to request\n");
--}
--
--static int purple_selfinfo(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- int warning_level;
-- va_list ap;
-- aim_userinfo_t *info;
--
-- va_start(ap, fr);
-- info = va_arg(ap, aim_userinfo_t *);
-- va_end(ap);
--
-- purple_connection_set_display_name(od->gc, info->bn);
--
-- /*
-- * What's with the + 0.5?
-- * The 0.5 is basically poor-man's rounding. Normally
-- * casting "13.7" to an int will truncate to "13," but
-- * with 13.7 + 0.5 = 14.2, which becomes "14" when
-- * truncated.
-- */
-- warning_level = info->warnlevel/10.0 + 0.5;
--
-- return 1;
--}
--
--static int purple_connerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- PurpleConnection *gc = od->gc;
-- va_list ap;
-- guint16 code;
-- char *msg;
--
-- va_start(ap, fr);
-- code = (guint16)va_arg(ap, int);
-- msg = va_arg(ap, char *);
-- va_end(ap);
--
-- purple_debug_info("oscar", "Disconnected. Code is 0x%04x and msg is %s\n",
-- code, (msg != NULL ? msg : ""));
--
-- g_return_val_if_fail(conn != NULL, 1);
--
-- if (conn->type == SNAC_FAMILY_CHAT) {
-- struct chat_connection *cc;
-- PurpleConversation *conv = NULL;
--
-- cc = find_oscar_chat_by_conn(gc, conn);
-- if (cc != NULL)
-- {
-- conv = purple_find_chat(gc, cc->id);
--
-- if (conv != NULL)
-- {
-- /*
-- * TOOD: Have flap_connection_destroy_cb() send us the
-- * error message stored in 'tmp', which should be
-- * human-friendly, and print that to the chat room.
-- */
-- gchar *buf;
-- buf = g_strdup_printf(_("You have been disconnected from chat "
-- "room %s."), cc->name);
-- purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_ERROR, time(NULL));
-- g_free(buf);
-- }
-- oscar_chat_kill(gc, cc);
-- }
-- }
--
-- return 1;
--}
--
--static int purple_parse_locaterights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
--{
-- PurpleConnection *gc = od->gc;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- va_list ap;
-- guint16 maxsiglen;
--
-- va_start(ap, fr);
-- maxsiglen = (guint16) va_arg(ap, int);
-- va_end(ap);
--
-- purple_debug_misc("oscar",
-- "locate rights: max sig len = %d\n", maxsiglen);
--
-- od->rights.maxsiglen = od->rights.maxawaymsglen = (guint)maxsiglen;
--
-- aim_locate_setcaps(od, purple_caps);
-- oscar_set_info_and_status(account, TRUE, account->user_info, TRUE,
-- purple_account_get_active_status(account));
--
-- return 1;
--}
--
--static int purple_parse_buddyrights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- va_list ap;
-- guint16 maxbuddies, maxwatchers;
--
-- va_start(ap, fr);
-- maxbuddies = (guint16) va_arg(ap, unsigned int);
-- maxwatchers = (guint16) va_arg(ap, unsigned int);
-- va_end(ap);
--
-- purple_debug_misc("oscar",
-- "buddy list rights: Max buddies = %hu / Max watchers = %hu\n", maxbuddies, maxwatchers);
--
-- od->rights.maxbuddies = (guint)maxbuddies;
-- od->rights.maxwatchers = (guint)maxwatchers;
--
-- return 1;
--}
--
--static void oscar_format_username(PurpleConnection *gc, const char *new_display_name)
--{
-- OscarData *od;
-- const char *old_display_name, *username;
-- char *tmp, *at_sign;
--
-- old_display_name = purple_connection_get_display_name(gc);
-- if (old_display_name && strchr(old_display_name, '@')) {
-- purple_debug_info("oscar", "Cowardly refusing to attempt to format "
-- "screen name because the current formatting according to "
-- "the server (%s) appears to be an email address\n",
-- old_display_name);
-- return;
-- }
--
-- username = purple_account_get_username(purple_connection_get_account(gc));
-- if (oscar_util_name_compare(username, new_display_name)) {
-- purple_notify_error(gc, NULL, _("The new formatting is invalid."),
-- _("Username formatting can change only capitalization and whitespace."));
-- return;
-- }
--
-- tmp = g_strdup(new_display_name);
--
-- /*
-- * If our local username is an email address then strip off the domain.
-- * This allows formatting to work if the user entered their username as
-- * 'something@aim.com' or possibly other AOL-owned domains.
-- */
-- at_sign = strchr(tmp, '@');
-- if (at_sign)
-- at_sign[0] = '\0';
--
-- od = purple_connection_get_protocol_data(gc);
-- if (!flap_connection_getbytype(od, SNAC_FAMILY_ADMIN)) {
-- /* We don't have a connection to an "admin" server. Make one. */
-- od->setnick = TRUE;
-- g_free(od->newformatting);
-- od->newformatting = tmp;
-- aim_srv_requestnew(od, SNAC_FAMILY_ADMIN);
-- } else {
-- aim_admin_setnick(od, flap_connection_getbytype(od, SNAC_FAMILY_ADMIN), tmp);
-- g_free(tmp);
-- }
--}
--
--static int purple_bosrights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- PurpleStatus *status;
-- gboolean is_available;
-- PurplePresence *presence;
-- const char *username, *message, *itmsurl;
-- char *tmp;
-- va_list ap;
-- guint16 maxpermits, maxdenies;
--
-- gc = od->gc;
-- od = purple_connection_get_protocol_data(gc);
-- account = purple_connection_get_account(gc);
--
-- va_start(ap, fr);
-- maxpermits = (guint16) va_arg(ap, unsigned int);
-- maxdenies = (guint16) va_arg(ap, unsigned int);
-- va_end(ap);
--
-- purple_debug_misc("oscar",
-- "BOS rights: Max permit = %hu / Max deny = %hu\n", maxpermits, maxdenies);
--
-- od->rights.maxpermits = (guint)maxpermits;
-- od->rights.maxdenies = (guint)maxdenies;
--
-- purple_debug_info("oscar", "buddy list loaded\n");
--
-- if (purple_account_get_user_info(account) != NULL)
-- serv_set_info(gc, purple_account_get_user_info(account));
--
-- username = purple_account_get_username(account);
-- if (!od->icq && strcmp(username, purple_connection_get_display_name(gc)) != 0) {
-- /*
-- * Format the username for AIM accounts if it's different
-- * than what's currently set.
-- */
-- oscar_format_username(gc, username);
-- }
--
-- /* Set our available message based on the current status */
-- status = purple_account_get_active_status(account);
-- is_available = purple_status_is_available(status);
-- if (is_available)
-- message = purple_status_get_attr_string(status, "message");
-- else
-- message = NULL;
-- tmp = purple_markup_strip_html(message);
-- itmsurl = purple_status_get_attr_string(status, "itmsurl");
-- aim_srv_setextrainfo(od, FALSE, 0, is_available, tmp, itmsurl);
-- aim_srv_set_dc_info(od);
-- g_free(tmp);
--
-- presence = purple_status_get_presence(status);
-- aim_srv_setidle(od, !purple_presence_is_idle(presence) ? 0 : time(NULL) - purple_presence_get_idle_time(presence));
--
-- if (od->icq) {
-- oscar_set_extended_status(gc);
-- aim_icq_setsecurity(od,
-- purple_account_get_bool(account, "authorization", OSCAR_DEFAULT_AUTHORIZATION),
-- purple_account_get_bool(account, "web_aware", OSCAR_DEFAULT_WEB_AWARE));
-- }
--
-- aim_srv_requestnew(od, SNAC_FAMILY_ALERT);
-- aim_srv_requestnew(od, SNAC_FAMILY_CHATNAV);
--
-- od->bos.have_rights = TRUE;
--
-- /*
-- * If we've already received our feedbag data then we're not waiting on
-- * anything else, so send the server clientready.
-- *
-- * Normally we get bos rights before we get our feedbag data, so this
-- * rarely (never?) happens. And I'm not sure it actually matters if we
-- * wait for bos rights before calling clientready. But it seems safer
-- * to do it this way.
-- */
-- if (od->ssi.received_data) {
-- aim_srv_clientready(od, conn);
--
-- /* Request offline messages for AIM and ICQ */
-- aim_im_reqofflinemsgs(od);
--
-- purple_connection_set_state(gc, PURPLE_CONNECTED);
-- }
--
-- return 1;
--}
--
--static int purple_popup(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
--{
-- PurpleConnection *gc = od->gc;
-- gchar *text;
-- va_list ap;
-- char *msg, *url;
-- guint16 wid, hei, delay;
--
-- va_start(ap, fr);
-- msg = va_arg(ap, char *);
-- url = va_arg(ap, char *);
-- wid = (guint16) va_arg(ap, int);
-- hei = (guint16) va_arg(ap, int);
-- delay = (guint16) va_arg(ap, int);
-- va_end(ap);
--
-- text = g_strdup_printf("%s<br><a href=\"%s\">%s</a>", msg, url, url);
-- purple_notify_formatted(gc, NULL, _("Pop-Up Message"), NULL, text, NULL, NULL);
-- g_free(text);
--
-- return 1;
--}
--
--static void oscar_searchresults_add_buddy_cb(PurpleConnection *gc, GList *row, void *user_data)
--{
-- purple_blist_request_add_buddy(purple_connection_get_account(gc),
-- g_list_nth_data(row, 0), NULL, NULL);
--}
--
--static int purple_parse_searchreply(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
--{
-- PurpleConnection *gc = od->gc;
-- PurpleNotifySearchResults *results;
-- PurpleNotifySearchColumn *column;
-- gchar *secondary;
-- int i, num;
-- va_list ap;
-- char *email, *usernames;
--
-- va_start(ap, fr);
-- email = va_arg(ap, char *);
-- num = va_arg(ap, int);
-- usernames = va_arg(ap, char *);
-- va_end(ap);
--
-- results = purple_notify_searchresults_new();
--
-- if (results == NULL) {
-- purple_debug_error("oscar", "purple_parse_searchreply: "
-- "Unable to display the search results.\n");
-- purple_notify_error(gc, NULL,
-- _("Unable to display the search results."),
-- NULL);
-- return 1;
-- }
--
-- secondary = g_strdup_printf(
-- dngettext(PACKAGE, "The following username is associated with %s",
-- "The following usernames are associated with %s",
-- num),
-- email);
--
-- column = purple_notify_searchresults_column_new(_("Username"));
-- purple_notify_searchresults_column_add(results, column);
--
-- for (i = 0; i < num; i++) {
-- GList *row;
-- row = g_list_append(NULL, g_strdup(&usernames[i * (MAXSNLEN + 1)]));
-- purple_notify_searchresults_row_add(results, row);
-- }
-- purple_notify_searchresults_button_add(results, PURPLE_NOTIFY_BUTTON_ADD,
-- oscar_searchresults_add_buddy_cb);
-- purple_notify_searchresults(gc, NULL, NULL, secondary, results, NULL, NULL);
--
-- g_free(secondary);
--
-- return 1;
--}
--
--static int purple_parse_searcherror(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- va_list ap;
-- char *email;
-- char *buf;
--
-- va_start(ap, fr);
-- email = va_arg(ap, char *);
-- va_end(ap);
--
-- buf = g_strdup_printf(_("No results found for email address %s"), email);
-- purple_notify_error(od->gc, NULL, buf, NULL);
-- g_free(buf);
--
-- return 1;
--}
--
--static int purple_account_confirm(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- PurpleConnection *gc = od->gc;
-- guint16 status;
-- va_list ap;
-- char msg[256];
--
-- va_start(ap, fr);
-- status = (guint16) va_arg(ap, unsigned int); /* status code of confirmation request */
-- va_end(ap);
--
-- purple_debug_info("oscar",
-- "account confirmation returned status 0x%04x (%s)\n", status,
-- status ? "unknown" : "email sent");
-- if (!status) {
-- g_snprintf(msg, sizeof(msg), _("You should receive an email asking to confirm %s."),
-- purple_account_get_username(purple_connection_get_account(gc)));
-- purple_notify_info(gc, NULL, _("Account Confirmation Requested"), msg);
-- }
--
-- return 1;
--}
--
--static int purple_info_change(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- PurpleConnection *gc = od->gc;
-- va_list ap;
-- guint16 perms, err;
-- char *url, *bn, *email;
-- int change;
--
-- va_start(ap, fr);
-- change = va_arg(ap, int);
-- perms = (guint16) va_arg(ap, unsigned int);
-- err = (guint16) va_arg(ap, unsigned int);
-- url = va_arg(ap, char *);
-- bn = va_arg(ap, char *);
-- email = va_arg(ap, char *);
-- va_end(ap);
--
-- purple_debug_misc("oscar",
-- "account info: because of %s, perms=0x%04x, err=0x%04x, url=%s, bn=%s, email=%s\n",
-- change ? "change" : "request", perms, err,
-- (url != NULL) ? url : "(null)",
-- (bn != NULL) ? bn : "(null)",
-- (email != NULL) ? email : "(null)");
--
-- if ((err > 0) && (url != NULL)) {
-- char *dialog_msg;
--
-- if (err == 0x0001)
-- dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format username because the requested name differs from the original."), err);
-- else if (err == 0x0006)
-- dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format username because it is invalid."), err);
-- else if (err == 0x00b)
-- dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format username because the requested name is too long."), err);
-- else if (err == 0x001d)
-- dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change email address because there is already a request pending for this username."), err);
-- else if (err == 0x0021)
-- dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change email address because the given address has too many usernames associated with it."), err);
-- else if (err == 0x0023)
-- dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change email address because the given address is invalid."), err);
-- else
-- dialog_msg = g_strdup_printf(_("Error 0x%04x: Unknown error."), err);
-- purple_notify_error(gc, NULL,
-- _("Error Changing Account Info"), dialog_msg);
-- g_free(dialog_msg);
-- return 1;
-- }
--
-- if (email != NULL) {
-- char *dialog_msg = g_strdup_printf(_("The email address for %s is %s"),
-- purple_account_get_username(purple_connection_get_account(gc)), email);
-- purple_notify_info(gc, NULL, _("Account Info"), dialog_msg);
-- g_free(dialog_msg);
-- }
--
-- return 1;
--}
--
--void
--oscar_keepalive(PurpleConnection *gc)
--{
-- OscarData *od;
-- GSList *l;
--
-- od = purple_connection_get_protocol_data(gc);
-- for (l = od->oscar_connections; l; l = l->next) {
-- flap_connection_send_keepalive(od, l->data);
-- }
--}
--
--unsigned int
--oscar_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state)
--{
-- OscarData *od;
-- PeerConnection *conn;
--
-- od = purple_connection_get_protocol_data(gc);
-- conn = peer_connection_find_by_type(od, name, OSCAR_CAPABILITY_DIRECTIM);
--
-- if ((conn != NULL) && (conn->ready))
-- {
-- peer_odc_send_typing(conn, state);
-- }
-- else {
-- /* Don't send if this turkey is in our deny list */
-- GSList *list;
-- for (list=gc->account->deny; (list && oscar_util_name_compare(name, list->data)); list=list->next);
-- if (!list) {
-- struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(gc->account, name));
-- if (bi && bi->typingnot) {
-- if (state == PURPLE_TYPING)
-- aim_im_sendmtn(od, 0x0001, name, 0x0002);
-- else if (state == PURPLE_TYPED)
-- aim_im_sendmtn(od, 0x0001, name, 0x0001);
-- else
-- aim_im_sendmtn(od, 0x0001, name, 0x0000);
-- }
-- }
-- }
-- return 0;
--}
--
--/* TODO: Move this into odc.c! */
--static void
--purple_odc_send_im(PeerConnection *conn, const char *message, PurpleMessageFlags imflags)
--{
-- GString *msg;
-- GString *data;
-- gchar *tmp;
-- gsize tmplen;
-- guint16 charset;
-- GData *attribs;
-- const char *start, *end, *last;
-- int oscar_id = 0;
--
-- msg = g_string_new("<HTML><BODY>");
-- data = g_string_new("<BINARY>");
-- last = message;
--
-- /* for each valid IMG tag... */
-- while (last && *last && purple_markup_find_tag("img", last, &start, &end, &attribs))
-- {
-- PurpleStoredImage *image = NULL;
-- const char *id;
--
-- if (start - last) {
-- g_string_append_len(msg, last, start - last);
-- }
--
-- id = g_datalist_get_data(&attribs, "id");
--
-- /* ... if it refers to a valid purple image ... */
-- if (id && (image = purple_imgstore_find_by_id(atoi(id)))) {
-- /* ... append the message from start to the tag ... */
-- unsigned long size = purple_imgstore_get_size(image);
-- const char *filename = purple_imgstore_get_filename(image);
-- gconstpointer imgdata = purple_imgstore_get_data(image);
--
-- oscar_id++;
--
-- /* ... insert a new img tag with the oscar id ... */
-- if (filename)
-- g_string_append_printf(msg,
-- "<IMG SRC=\"%s\" ID=\"%d\" DATASIZE=\"%lu\">",
-- filename, oscar_id, size);
-- else
-- g_string_append_printf(msg,
-- "<IMG ID=\"%d\" DATASIZE=\"%lu\">",
-- oscar_id, size);
--
-- /* ... and append the data to the binary section ... */
-- g_string_append_printf(data, "<DATA ID=\"%d\" SIZE=\"%lu\">",
-- oscar_id, size);
-- g_string_append_len(data, imgdata, size);
-- g_string_append(data, "</DATA>");
-- }
-- /* If the tag is invalid, skip it, thus no else here */
--
-- g_datalist_clear(&attribs);
--
-- /* continue from the end of the tag */
-- last = end + 1;
-- }
--
-- /* append any remaining message data */
-- if (last && *last)
-- g_string_append(msg, last);
--
-- g_string_append(msg, "</BODY></HTML>");
--
-- /* Convert the message to a good encoding */
-- tmp = oscar_encode_im(msg->str, &tmplen, &charset, NULL);
-- g_string_free(msg, TRUE);
-- msg = g_string_new_len(tmp, tmplen);
-- g_free(tmp);
--
-- /* Append any binary data that we may have */
-- if (oscar_id) {
-- msg = g_string_append_len(msg, data->str, data->len);
-- msg = g_string_append(msg, "</BINARY>");
-- }
-- g_string_free(data, TRUE);
--
-- purple_debug_info("oscar", "sending direct IM %s using charset %i", msg->str, charset);
--
-- peer_odc_send_im(conn, msg->str, msg->len, charset,
-- imflags & PURPLE_MESSAGE_AUTO_RESP);
-- g_string_free(msg, TRUE);
--}
--
--int
--oscar_send_im(PurpleConnection *gc, const char *name, const char *message, PurpleMessageFlags imflags)
--{
-- OscarData *od;
-- PurpleAccount *account;
-- PeerConnection *conn;
-- int ret;
-- char *tmp1, *tmp2;
-- gboolean is_sms, is_html;
--
-- od = purple_connection_get_protocol_data(gc);
-- account = purple_connection_get_account(gc);
-- ret = 0;
--
-- is_sms = oscar_util_valid_name_sms(name);
--
-- if (od->icq && is_sms) {
-- /*
-- * We're sending to a phone number and this is ICQ,
-- * so send the message as an SMS using aim_icq_sendsms()
-- */
-- int ret;
-- purple_debug_info("oscar", "Sending SMS to %s.\n", name);
-- ret = aim_icq_sendsms(od, name, message, purple_account_get_username(account));
-- return (ret >= 0 ? 1 : ret);
-- }
--
-- if (imflags & PURPLE_MESSAGE_AUTO_RESP)
-- tmp1 = oscar_util_format_string(message, name);
-- else
-- tmp1 = g_strdup(message);
--
-- conn = peer_connection_find_by_type(od, name, OSCAR_CAPABILITY_DIRECTIM);
-- if ((conn != NULL) && (conn->ready))
-- {
-- /* If we're directly connected, send a direct IM */
-- purple_debug_info("oscar", "Sending direct IM with flags %i\n", imflags);
-- purple_odc_send_im(conn, tmp1, imflags);
-- } else {
-- struct buddyinfo *bi;
-- struct aim_sendimext_args args;
-- PurpleConversation *conv;
-- PurpleStoredImage *img;
-- PurpleBuddy *buddy;
--
-- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, account);
--
-- if (strstr(tmp1, "<IMG "))
-- purple_conversation_write(conv, "",
-- _("Your IM Image was not sent. "
-- "You must be Direct Connected to send IM Images."),
-- PURPLE_MESSAGE_ERROR, time(NULL));
--
-- buddy = purple_find_buddy(account, name);
--
-- bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, name));
-- if (!bi) {
-- bi = g_new0(struct buddyinfo, 1);
-- g_hash_table_insert(od->buddyinfo, g_strdup(purple_normalize(account, name)), bi);
-- }
--
-- args.flags = 0;
--
-- if (!is_sms && (!buddy || !PURPLE_BUDDY_IS_ONLINE(buddy)))
-- args.flags |= AIM_IMFLAGS_OFFLINE;
--
-- if (od->icq) {
-- args.features = features_icq;
-- args.featureslen = sizeof(features_icq);
-- } else {
-- args.features = features_aim;
-- args.featureslen = sizeof(features_aim);
--
-- if (imflags & PURPLE_MESSAGE_AUTO_RESP)
-- args.flags |= AIM_IMFLAGS_AWAY;
-- }
--
-- if (bi->ico_need) {
-- purple_debug_info("oscar",
-- "Sending buddy icon request with message\n");
-- args.flags |= AIM_IMFLAGS_BUDDYREQ;
-- bi->ico_need = FALSE;
-- }
--
-- img = purple_buddy_icons_find_account_icon(account);
-- if (img) {
-- gconstpointer data = purple_imgstore_get_data(img);
-- args.iconlen = purple_imgstore_get_size(img);
-- args.iconsum = aimutil_iconsum(data, args.iconlen);
-- args.iconstamp = purple_buddy_icons_get_account_icon_timestamp(account);
--
-- if ((args.iconlen != bi->ico_me_len) || (args.iconsum != bi->ico_me_csum) || (args.iconstamp != bi->ico_me_time)) {
-- bi->ico_informed = FALSE;
-- bi->ico_sent = FALSE;
-- }
--
-- /*
-- * TODO:
-- * For some reason sending our icon to people only works
-- * when we're the ones who initiated the conversation. If
-- * the other person sends the first IM then they never get
-- * the icon. We should fix that.
-- */
-- if (!bi->ico_informed) {
-- purple_debug_info("oscar",
-- "Claiming to have a buddy icon\n");
-- args.flags |= AIM_IMFLAGS_HASICON;
-- bi->ico_me_len = args.iconlen;
-- bi->ico_me_csum = args.iconsum;
-- bi->ico_me_time = args.iconstamp;
-- bi->ico_informed = TRUE;
-- }
--
-- purple_imgstore_unref(img);
-- }
--
-- args.destbn = name;
--
-- if (oscar_util_valid_name_sms(name)) {
-- /* Messaging an SMS (mobile) user--strip HTML */
-- tmp2 = purple_markup_strip_html(tmp1);
-- is_html = FALSE;
-- } else {
-- /* ICQ 6 wants its HTML wrapped in these tags. Oblige it. */
-- tmp2 = g_strdup_printf("<HTML><BODY>%s</BODY></HTML>", tmp1);
-- is_html = TRUE;
-- }
-- g_free(tmp1);
-- tmp1 = tmp2;
--
-- args.msg = oscar_encode_im(tmp1, &args.msglen, &args.charset, NULL);
-- if (is_html && (args.msglen > MAXMSGLEN)) {
-- /* If the length was too long, try stripping the HTML and then running it back through
-- * purple_strdup_withhtml() and the encoding process. The result may be shorter. */
-- g_free((char *)args.msg);
--
-- tmp2 = purple_markup_strip_html(tmp1);
-- g_free(tmp1);
--
-- /* re-escape the entities */
-- tmp1 = g_markup_escape_text(tmp2, -1);
-- g_free(tmp2);
--
-- tmp2 = purple_strdup_withhtml(tmp1);
-- g_free(tmp1);
-- tmp1 = tmp2;
--
-- args.msg = oscar_encode_im(tmp1, &args.msglen, &args.charset, NULL);
-- purple_debug_info("oscar", "Sending %s as %s because the original was too long.\n",
-- message, (char *)args.msg);
-- }
--
-- purple_debug_info("oscar", "Sending IM, charset=0x%04hx, length=%" G_GSIZE_FORMAT "\n", args.charset, args.msglen);
-- ret = aim_im_sendch1_ext(od, &args);
-- g_free((char *)args.msg);
-- }
--
-- g_free(tmp1);
--
-- if (ret >= 0)
-- return 1;
--
-- return ret;
--}
--
--/*
-- * As of 26 June 2006, ICQ users can request AIM info from
-- * everyone, and can request ICQ info from ICQ users, and
-- * AIM users can only request AIM info.
-- */
--void oscar_get_info(PurpleConnection *gc, const char *name) {
-- OscarData *od = purple_connection_get_protocol_data(gc);
--
-- if (od->icq && oscar_util_valid_name_icq(name))
-- aim_icq_getallinfo(od, name);
-- else
-- aim_locate_getinfoshort(od, name, 0x00000003);
--}
--
--void oscar_set_idle(PurpleConnection *gc, int time) {
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- aim_srv_setidle(od, time);
--}
--
--void
--oscar_set_info(PurpleConnection *gc, const char *rawinfo)
--{
-- PurpleAccount *account;
-- PurpleStatus *status;
--
-- account = purple_connection_get_account(gc);
-- status = purple_account_get_active_status(account);
-- oscar_set_info_and_status(account, TRUE, rawinfo, FALSE, status);
--}
--
--static guint32
--oscar_get_extended_status(PurpleConnection *gc)
--{
-- OscarData *od;
-- PurpleAccount *account;
-- PurpleStatus *status;
-- const gchar *status_id;
-- guint32 data = 0x00000000;
--
-- od = purple_connection_get_protocol_data(gc);
-- account = purple_connection_get_account(gc);
-- status = purple_account_get_active_status(account);
-- status_id = purple_status_get_id(status);
--
-- data |= AIM_ICQ_STATE_HIDEIP;
-- if (purple_account_get_bool(account, "web_aware", OSCAR_DEFAULT_WEB_AWARE))
-- data |= AIM_ICQ_STATE_WEBAWARE;
--
-- if (!strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE))
-- data |= AIM_ICQ_STATE_NORMAL;
-- else if (!strcmp(status_id, OSCAR_STATUS_ID_AWAY))
-- data |= AIM_ICQ_STATE_AWAY;
-- else if (!strcmp(status_id, OSCAR_STATUS_ID_DND))
-- data |= AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY;
-- else if (!strcmp(status_id, OSCAR_STATUS_ID_NA))
-- data |= AIM_ICQ_STATE_OUT | AIM_ICQ_STATE_AWAY;
-- else if (!strcmp(status_id, OSCAR_STATUS_ID_OCCUPIED))
-- data |= AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY;
-- else if (!strcmp(status_id, OSCAR_STATUS_ID_FREE4CHAT))
-- data |= AIM_ICQ_STATE_CHAT;
-- else if (!strcmp(status_id, OSCAR_STATUS_ID_INVISIBLE))
-- data |= AIM_ICQ_STATE_INVISIBLE;
-- else if (!strcmp(status_id, OSCAR_STATUS_ID_EVIL))
-- data |= AIM_ICQ_STATE_EVIL;
-- else if (!strcmp(status_id, OSCAR_STATUS_ID_DEPRESSION))
-- data |= AIM_ICQ_STATE_DEPRESSION;
-- else if (!strcmp(status_id, OSCAR_STATUS_ID_ATWORK))
-- data |= AIM_ICQ_STATE_ATWORK;
-- else if (!strcmp(status_id, OSCAR_STATUS_ID_ATHOME))
-- data |= AIM_ICQ_STATE_ATHOME;
-- else if (!strcmp(status_id, OSCAR_STATUS_ID_LUNCH))
-- data |= AIM_ICQ_STATE_LUNCH;
-- else if (!strcmp(status_id, OSCAR_STATUS_ID_CUSTOM))
-- data |= AIM_ICQ_STATE_OUT | AIM_ICQ_STATE_AWAY;
--
-- return data;
--}
--
--static void
--oscar_set_extended_status(PurpleConnection *gc)
--{
-- aim_srv_setextrainfo(purple_connection_get_protocol_data(gc), TRUE, oscar_get_extended_status(gc), FALSE, NULL, NULL);
--}
--
--static void
--oscar_set_info_and_status(PurpleAccount *account, gboolean setinfo, const char *rawinfo,
-- gboolean setstatus, PurpleStatus *status)
--{
-- PurpleConnection *gc = purple_account_get_connection(account);
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- PurpleStatusType *status_type;
-- PurpleStatusPrimitive primitive;
--
-- char *info_encoding = NULL;
-- char *info = NULL;
-- gsize infolen = 0;
--
-- char *away_encoding = NULL;
-- char *away = NULL;
-- gsize awaylen = 0;
--
-- char *status_text = NULL;
-- const char *itmsurl = NULL;
--
-- status_type = purple_status_get_type(status);
-- primitive = purple_status_type_get_primitive(status_type);
--
-- if (!setinfo)
-- {
-- /* Do nothing! */
-- }
-- else if (od->rights.maxsiglen == 0)
-- {
-- purple_notify_warning(gc, NULL, _("Unable to set AIM profile."),
-- _("You have probably requested to set your "
-- "profile before the login procedure completed. "
-- "Your profile remains unset; try setting it "
-- "again when you are fully connected."));
-- }
-- else if (rawinfo != NULL)
-- {
-- char *htmlinfo = purple_strdup_withhtml(rawinfo);
-- info = oscar_encode_im(htmlinfo, &infolen, NULL, &info_encoding);
-- g_free(htmlinfo);
--
-- if (infolen > od->rights.maxsiglen)
-- {
-- gchar *errstr;
-- errstr = g_strdup_printf(dngettext(PACKAGE, "The maximum profile length of %d byte "
-- "has been exceeded. It has been truncated for you.",
-- "The maximum profile length of %d bytes "
-- "has been exceeded. It has been truncated for you.",
-- od->rights.maxsiglen), od->rights.maxsiglen);
-- purple_notify_warning(gc, NULL, _("Profile too long."), errstr);
-- g_free(errstr);
-- }
-- }
--
-- if (setstatus)
-- {
-- const char *status_html;
--
-- status_html = purple_status_get_attr_string(status, "message");
--
-- if (status_html == NULL || primitive == PURPLE_STATUS_AVAILABLE || primitive == PURPLE_STATUS_INVISIBLE)
-- {
-- /* This is needed for us to un-set any previous away message. */
-- away = g_strdup("");
-- }
-- else
-- {
-- gchar *linkified;
--
-- /* We do this for icq too so that they work for old third party clients */
-- linkified = purple_markup_linkify(status_html);
-- away = oscar_encode_im(linkified, &awaylen, NULL, &away_encoding);
-- g_free(linkified);
--
-- if (awaylen > od->rights.maxawaymsglen)
-- {
-- gchar *errstr;
--
-- errstr = g_strdup_printf(dngettext(PACKAGE, "The maximum away message length of %d byte "
-- "has been exceeded. It has been truncated for you.",
-- "The maximum away message length of %d bytes "
-- "has been exceeded. It has been truncated for you.",
-- od->rights.maxawaymsglen), od->rights.maxawaymsglen);
-- purple_notify_warning(gc, NULL, _("Away message too long."), errstr);
-- g_free(errstr);
-- }
-- }
-- }
--
-- aim_locate_setprofile(od,
-- info_encoding, info, MIN(infolen, od->rights.maxsiglen),
-- away_encoding, away, MIN(awaylen, od->rights.maxawaymsglen));
-- g_free(info);
-- g_free(away);
--
-- if (setstatus)
-- {
-- const char *status_html;
--
-- status_html = purple_status_get_attr_string(status, "message");
-- if (status_html != NULL)
-- {
-- status_text = purple_markup_strip_html(status_html);
-- /* If the status_text is longer than 251 characters then truncate it */
-- if (strlen(status_text) > MAXAVAILMSGLEN)
-- {
-- char *tmp = g_utf8_find_prev_char(status_text, &status_text[MAXAVAILMSGLEN - 2]);
-- strcpy(tmp, "...");
-- }
-- }
--
-- itmsurl = purple_status_get_attr_string(status, "itmsurl");
--
-- aim_srv_setextrainfo(od, TRUE, oscar_get_extended_status(gc), TRUE, status_text, itmsurl);
-- g_free(status_text);
-- }
--}
--
--static void
--oscar_set_icq_permdeny(PurpleAccount *account)
--{
-- PurpleConnection *gc = purple_account_get_connection(account);
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- gboolean invisible = purple_account_is_status_active(account, OSCAR_STATUS_ID_INVISIBLE);
--
-- /*
-- * For ICQ the permit/deny setting controls who can see you
-- * online. Mimicking the official client's behavior, we use PURPLE_PRIVACY_ALLOW_USERS
-- * when our status is "invisible" and PURPLE_PRIVACY_DENY_USERS otherwise.
-- * In the former case, we are visible only to buddies on our "permanently visible" list.
-- * In the latter, we are invisible only to buddies on our "permanently invisible" list.
-- */
-- aim_ssi_setpermdeny(od, invisible ? PURPLE_PRIVACY_ALLOW_USERS : PURPLE_PRIVACY_DENY_USERS);
--}
--
--void
--oscar_set_status(PurpleAccount *account, PurpleStatus *status)
--{
-- PurpleConnection *pc;
-- OscarData *od;
--
-- purple_debug_info("oscar", "Set status to %s\n", purple_status_get_name(status));
--
-- /* Either setting a new status active or setting a status inactive.
-- * (Only possible for independent status (i.e. X-Status moods.) */
-- if (!purple_status_is_active(status) && !purple_status_is_independent(status))
-- return;
--
-- if (!purple_account_is_connected(account))
-- return;
--
-- pc = purple_account_get_connection(account);
-- od = purple_connection_get_protocol_data(pc);
--
-- /* There's no need to do the stuff below for mood updates. */
-- if (purple_status_type_get_primitive(purple_status_get_type(status)) == PURPLE_STATUS_MOOD) {
-- aim_locate_setcaps(od, purple_caps);
-- return;
-- }
--
-- if (od->icq) {
-- /* Set visibility */
-- oscar_set_icq_permdeny(account);
-- }
--
-- /* Set the AIM-style away message for both AIM and ICQ accounts */
-- oscar_set_info_and_status(account, FALSE, NULL, TRUE, status);
--}
--
--void
--oscar_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *msg)
--{
-- OscarData *od;
-- PurpleAccount *account;
-- const char *bname, *gname;
--
-- od = purple_connection_get_protocol_data(gc);
-- account = purple_connection_get_account(gc);
-- bname = purple_buddy_get_name(buddy);
-- gname = purple_group_get_name(group);
--
-- if (!oscar_util_valid_name(bname)) {
-- gchar *buf;
-- buf = g_strdup_printf(_("Unable to add the buddy %s because the username is invalid. Usernames must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), bname);
-- if (!purple_conv_present_error(bname, account, buf))
-- purple_notify_error(gc, NULL, _("Unable to Add"), buf);
-- g_free(buf);
--
-- /* Remove from local list */
-- purple_blist_remove_buddy(buddy);
--
-- return;
-- }
--
-- if (od->ssi.received_data) {
-- if (!aim_ssi_itemlist_finditem(od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY)) {
-- purple_debug_info("oscar",
-- "ssi: adding buddy %s to group %s\n", bname, gname);
-- aim_ssi_addbuddy(od, bname, gname, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, 0);
--
-- /* Mobile users should always be online */
-- if (bname[0] == '+') {
-- purple_prpl_got_user_status(account, bname,
-- OSCAR_STATUS_ID_AVAILABLE, NULL);
-- purple_prpl_got_user_status(account, bname,
-- OSCAR_STATUS_ID_MOBILE, NULL);
-- }
-- } else if (aim_ssi_waitingforauth(od->ssi.local,
-- aim_ssi_itemlist_findparentname(od->ssi.local, bname),
-- bname)) {
-- /* Not authorized -- Re-request authorization */
-- oscar_auth_sendrequest(gc, bname, msg);
-- }
-- }
--
-- /* XXX - Should this be done from AIM accounts, as well? */
-- if (od->icq)
-- aim_icq_getalias(od, bname, FALSE, NULL);
--}
--
--void oscar_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) {
-- OscarData *od = purple_connection_get_protocol_data(gc);
--
-- if (od->ssi.received_data) {
-- const char *gname = purple_group_get_name(group);
-- const char *bname = purple_buddy_get_name(buddy);
-- purple_debug_info("oscar",
-- "ssi: deleting buddy %s from group %s\n", bname, gname);
-- aim_ssi_delbuddy(od, bname, gname);
-- }
--}
--
--void oscar_move_buddy(PurpleConnection *gc, const char *name, const char *old_group, const char *new_group) {
-- OscarData *od = purple_connection_get_protocol_data(gc);
--
-- if (od->ssi.received_data && strcmp(old_group, new_group)) {
-- purple_debug_info("oscar",
-- "ssi: moving buddy %s from group %s to group %s\n", name, old_group, new_group);
-- aim_ssi_movebuddy(od, old_group, new_group, name);
-- }
--}
--
--void oscar_alias_buddy(PurpleConnection *gc, const char *name, const char *alias) {
-- OscarData *od = purple_connection_get_protocol_data(gc);
--
-- if (od->ssi.received_data) {
-- char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, name);
-- if (gname) {
-- purple_debug_info("oscar",
-- "ssi: changing the alias for buddy %s to %s\n", name, alias ? alias : "(none)");
-- aim_ssi_aliasbuddy(od, gname, name, alias);
-- }
-- }
--}
--
--/*
-- * FYI, the OSCAR SSI code removes empty groups automatically.
-- */
--void oscar_rename_group(PurpleConnection *gc, const char *old_name, PurpleGroup *group, GList *moved_buddies) {
-- OscarData *od = purple_connection_get_protocol_data(gc);
--
-- if (od->ssi.received_data) {
-- const char *gname = purple_group_get_name(group);
-- if (aim_ssi_itemlist_finditem(od->ssi.local, gname, NULL, AIM_SSI_TYPE_GROUP)) {
-- GList *cur, *groups = NULL;
-- PurpleAccount *account = purple_connection_get_account(gc);
--
-- /* Make a list of what the groups each buddy is in */
-- for (cur = moved_buddies; cur != NULL; cur = cur->next) {
-- PurpleBlistNode *node = cur->data;
-- /* node is PurpleBuddy, parent is a PurpleContact.
-- * We must go two levels up to get the Group */
-- groups = g_list_append(groups,
-- purple_buddy_get_group((PurpleBuddy*)node));
-- }
--
-- purple_account_remove_buddies(account, moved_buddies, groups);
-- purple_account_add_buddies(account, moved_buddies);
-- g_list_free(groups);
-- purple_debug_info("oscar",
-- "ssi: moved all buddies from group %s to %s\n", old_name, gname);
-- } else {
-- aim_ssi_rename_group(od, old_name, gname);
-- purple_debug_info("oscar",
-- "ssi: renamed group %s to %s\n", old_name, gname);
-- }
-- }
--}
--
--void oscar_remove_group(PurpleConnection *gc, PurpleGroup *group)
--{
-- aim_ssi_delgroup(purple_connection_get_protocol_data(gc), purple_group_get_name(group));
--}
--
--static gboolean purple_ssi_rerequestdata(gpointer data) {
-- OscarData *od = data;
--
-- aim_ssi_reqdata(od);
--
-- return TRUE;
--}
--
--static int purple_ssi_parseerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- PurpleConnection *gc = od->gc;
-- va_list ap;
-- guint16 reason;
--
-- va_start(ap, fr);
-- reason = (guint16)va_arg(ap, unsigned int);
-- va_end(ap);
--
-- purple_debug_error("oscar", "ssi: SNAC error %hu\n", reason);
--
-- if (reason == 0x0005) {
-- if (od->getblisttimer > 0)
-- purple_timeout_remove(od->getblisttimer);
-- else
-- /* We only show this error the first time it happens */
-- purple_notify_error(gc, NULL,
-- _("Unable to Retrieve Buddy List"),
-- _("The AIM servers were temporarily unable to send "
-- "your buddy list. Your buddy list is not lost, and "
-- "will probably become available in a few minutes."));
-- od->getblisttimer = purple_timeout_add_seconds(30, purple_ssi_rerequestdata, od);
-- return 1;
-- }
--
-- return 1;
--}
--
--static int purple_ssi_parserights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- int i;
-- va_list ap;
-- int numtypes;
-- guint16 *maxitems;
-- GString *msg;
--
-- va_start(ap, fr);
-- numtypes = va_arg(ap, int);
-- maxitems = va_arg(ap, guint16 *);
-- va_end(ap);
--
-- msg = g_string_new("ssi rights:");
-- for (i=0; i<numtypes; i++)
-- g_string_append_printf(msg, " max type 0x%04x=%hd,", i, maxitems[i]);
-- g_string_append(msg, "\n");
-- purple_debug_misc("oscar", "%s", msg->str);
-- g_string_free(msg, TRUE);
--
-- if (numtypes >= 0)
-- od->rights.maxbuddies = maxitems[0];
-- if (numtypes >= 1)
-- od->rights.maxgroups = maxitems[1];
-- if (numtypes >= 2)
-- od->rights.maxpermits = maxitems[2];
-- if (numtypes >= 3)
-- od->rights.maxdenies = maxitems[3];
--
-- return 1;
--}
--
--static int purple_ssi_parselist(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
--{
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- PurpleGroup *g;
-- PurpleBuddy *b;
-- GSList *cur, *next, *buddies;
-- struct aim_ssi_item *curitem;
-- guint32 tmp;
-- PurpleStoredImage *img;
-- va_list ap;
-- guint16 fmtver, numitems;
-- guint32 timestamp;
-- guint16 deny_entry_type = aim_ssi_getdenyentrytype(od);
--
-- gc = od->gc;
-- od = purple_connection_get_protocol_data(gc);
-- account = purple_connection_get_account(gc);
--
-- va_start(ap, fr);
-- fmtver = (guint16)va_arg(ap, int);
-- numitems = (guint16)va_arg(ap, int);
-- timestamp = va_arg(ap, guint32);
-- va_end(ap);
--
-- /* Don't attempt to re-request our buddy list later */
-- if (od->getblisttimer != 0) {
-- purple_timeout_remove(od->getblisttimer);
-- od->getblisttimer = 0;
-- }
--
-- purple_debug_info("oscar", "ssi: syncing local list and server list\n");
--
-- /* Clean the buddy list */
-- aim_ssi_cleanlist(od);
--
-- /*** Begin code for pruning buddies from local list if they're not in server list ***/
--
-- /* Buddies */
-- cur = NULL;
-- for (buddies = purple_find_buddies(account, NULL);
-- buddies;
-- buddies = g_slist_delete_link(buddies, buddies))
-- {
-- PurpleGroup *g;
-- const char *gname;
-- const char *bname;
--
-- b = buddies->data;
-- g = purple_buddy_get_group(b);
-- gname = purple_group_get_name(g);
-- bname = purple_buddy_get_name(b);
--
-- if (aim_ssi_itemlist_exists(od->ssi.local, bname)) {
-- /* If the buddy is an ICQ user then load his nickname */
-- const char *servernick = purple_blist_node_get_string((PurpleBlistNode*)b, "servernick");
-- char *alias;
-- const char *balias;
-- if (servernick)
-- serv_got_alias(gc, bname, servernick);
--
-- /* Store local alias on server */
-- alias = aim_ssi_getalias(od->ssi.local, gname, bname);
-- balias = purple_buddy_get_local_buddy_alias(b);
-- if (!alias && balias && *balias)
-- aim_ssi_aliasbuddy(od, gname, bname, balias);
-- g_free(alias);
-- } else {
-- purple_debug_info("oscar",
-- "ssi: removing buddy %s from local list\n", bname);
-- /* Queue the buddy for removal from the local list */
-- cur = g_slist_prepend(cur, b);
-- }
-- }
-- while (cur != NULL) {
-- purple_blist_remove_buddy(cur->data);
-- cur = g_slist_delete_link(cur, cur);
-- }
--
-- /* Permit list (ICQ doesn't have one) */
-- if (!od->icq) {
-- next = account->permit;
-- while (next != NULL) {
-- cur = next;
-- next = next->next;
-- if (!aim_ssi_itemlist_finditem(od->ssi.local, NULL, cur->data, AIM_SSI_TYPE_PERMIT)) {
-- purple_debug_info("oscar",
-- "ssi: removing permit %s from local list\n", (const char *)cur->data);
-- purple_privacy_permit_remove(account, cur->data, TRUE);
-- }
-- }
-- }
--
-- /* Deny list */
-- next = account->deny;
-- while (next != NULL) {
-- cur = next;
-- next = next->next;
-- if (!aim_ssi_itemlist_finditem(od->ssi.local, NULL, cur->data, deny_entry_type)) {
-- purple_debug_info("oscar",
-- "ssi: removing deny %s from local list\n", (const char *)cur->data);
-- purple_privacy_deny_remove(account, cur->data, TRUE);
-- }
-- }
--
-- /* Presence settings (idle time visibility) */
-- tmp = aim_ssi_getpresence(od->ssi.local);
-- if (tmp != 0xFFFFFFFF) {
-- const char *idle_reporting_pref;
-- gboolean report_idle;
--
-- idle_reporting_pref = purple_prefs_get_string("/purple/away/idle_reporting");
-- report_idle = strcmp(idle_reporting_pref, "none") != 0;
--
-- if (report_idle)
-- aim_ssi_setpresence(od, tmp | AIM_SSI_PRESENCE_FLAG_SHOWIDLE);
-- else
-- aim_ssi_setpresence(od, tmp & ~AIM_SSI_PRESENCE_FLAG_SHOWIDLE);
-- }
--
-- /*** End code for pruning buddies from local list ***/
--
-- /*** Begin code for adding from server list to local list ***/
--
-- for (curitem=od->ssi.local; curitem; curitem=curitem->next) {
-- if (curitem->name && !g_utf8_validate(curitem->name, -1, NULL)) {
-- /* Got node with invalid UTF-8 in the name. Skip it. */
-- purple_debug_warning("oscar", "ssi: server list contains item of "
-- "type 0x%04hhx with a non-utf8 name\n", curitem->type);
-- continue;
-- }
--
-- switch (curitem->type) {
-- case AIM_SSI_TYPE_BUDDY: { /* Buddy */
-- if (curitem->name) {
-- struct aim_ssi_item *groupitem;
-- char *gname, *gname_utf8, *alias, *alias_utf8;
--
-- groupitem = aim_ssi_itemlist_find(od->ssi.local, curitem->gid, 0x0000);
-- gname = groupitem ? groupitem->name : NULL;
-- gname_utf8 = oscar_utf8_try_convert(account, od, gname);
--
-- g = purple_find_group(gname_utf8 ? gname_utf8 : _("Orphans"));
-- if (g == NULL) {
-- g = purple_group_new(gname_utf8 ? gname_utf8 : _("Orphans"));
-- purple_blist_add_group(g, NULL);
-- }
--
-- alias = aim_ssi_getalias(od->ssi.local, gname, curitem->name);
-- alias_utf8 = oscar_utf8_try_convert(account, od, alias);
--
-- b = purple_find_buddy_in_group(account, curitem->name, g);
-- if (b) {
-- /* Get server stored alias */
-- purple_blist_alias_buddy(b, alias_utf8);
-- } else {
-- b = purple_buddy_new(account, curitem->name, alias_utf8);
--
-- purple_debug_info("oscar",
-- "ssi: adding buddy %s to group %s to local list\n", curitem->name, gname);
-- purple_blist_add_buddy(b, NULL, g, NULL);
-- }
--
-- /* Mobile users should always be online */
-- if (curitem->name[0] == '+') {
-- purple_prpl_got_user_status(account,
-- purple_buddy_get_name(b),
-- OSCAR_STATUS_ID_AVAILABLE, NULL);
-- purple_prpl_got_user_status(account,
-- purple_buddy_get_name(b),
-- OSCAR_STATUS_ID_MOBILE, NULL);
-- }
--
-- g_free(gname_utf8);
-- g_free(alias);
-- g_free(alias_utf8);
-- }
-- } break;
--
-- case AIM_SSI_TYPE_GROUP: { /* Group */
-- if (curitem->name != NULL && purple_find_group(curitem->name) == NULL) {
-- g = purple_group_new(curitem->name);
-- purple_blist_add_group(g, NULL);
-- }
-- } break;
--
-- case AIM_SSI_TYPE_PERMIT: { /* Permit buddy (unless we're on ICQ) */
-- if (!od->icq && curitem->name) {
-- for (cur = account->permit; (cur && oscar_util_name_compare(curitem->name, cur->data)); cur = cur->next);
-- if (!cur) {
-- purple_debug_info("oscar",
-- "ssi: adding permit buddy %s to local list\n", curitem->name);
-- purple_privacy_permit_add(account, curitem->name, TRUE);
-- }
-- }
-- } break;
--
-- case AIM_SSI_TYPE_ICQDENY:
-- case AIM_SSI_TYPE_DENY: { /* Deny buddy */
-- if (curitem->type == deny_entry_type && curitem->name) {
-- for (cur = account->deny; (cur && oscar_util_name_compare(curitem->name, cur->data)); cur = cur->next);
-- if (!cur) {
-- purple_debug_info("oscar",
-- "ssi: adding deny buddy %s to local list\n", curitem->name);
-- purple_privacy_deny_add(account, curitem->name, TRUE);
-- }
-- }
-- } break;
--
-- case AIM_SSI_TYPE_PDINFO: { /* Permit/deny setting */
-- /*
-- * We don't inherit the permit/deny setting from the server
-- * for ICQ because, for ICQ, this setting controls who can
-- * see your online status when you are invisible. Thus it is
-- * a part of your status and not really related to blocking.
-- */
-- if (!od->icq && curitem->data) {
-- guint8 perm_deny = aim_ssi_getpermdeny(od->ssi.local);
-- if (perm_deny != 0 && perm_deny != account->perm_deny)
-- {
-- purple_debug_info("oscar",
-- "ssi: changing permdeny from %d to %hhu\n", account->perm_deny, perm_deny);
-- account->perm_deny = perm_deny;
-- }
-- }
-- } break;
--
-- case AIM_SSI_TYPE_PRESENCEPREFS: { /* Presence setting */
-- /* We don't want to change Purple's setting because it applies to all accounts */
-- } break;
-- } /* End of switch on curitem->type */
-- } /* End of for loop */
--
-- /*** End code for adding from server list to local list ***/
--
-- if (od->icq) {
-- oscar_set_icq_permdeny(account);
-- } else {
-- oscar_set_aim_permdeny(gc);
-- }
--
-- /* Activate SSI */
-- /* Sending the enable causes other people to be able to see you, and you to see them */
-- /* Make sure your privacy setting/invisibility is set how you want it before this! */
-- purple_debug_info("oscar",
-- "ssi: activating server-stored buddy list\n");
-- aim_ssi_enable(od);
--
-- /*
-- * Make sure our server-stored icon is updated correctly in
-- * the event that the local user set a new icon while this
-- * account was offline.
-- */
-- img = purple_buddy_icons_find_account_icon(account);
-- oscar_set_icon(gc, img);
-- purple_imgstore_unref(img);
--
-- /*
-- * If we've already received our bos rights then we're not waiting on
-- * anything else, so send the server clientready.
-- */
-- if (od->bos.have_rights) {
-- aim_srv_clientready(od, conn);
--
-- /* Request offline messages for AIM and ICQ */
-- aim_im_reqofflinemsgs(od);
--
-- purple_connection_set_state(gc, PURPLE_CONNECTED);
-- }
--
-- return 1;
--}
--
--static int purple_ssi_parseack(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- PurpleConnection *gc = od->gc;
-- va_list ap;
-- struct aim_ssi_tmp *retval;
--
-- va_start(ap, fr);
-- retval = va_arg(ap, struct aim_ssi_tmp *);
-- va_end(ap);
--
-- while (retval) {
-- purple_debug_misc("oscar",
-- "ssi: status is 0x%04hx for a 0x%04hx action with name %s\n", retval->ack, retval->action, retval->item ? (retval->item->name ? retval->item->name : "no name") : "no item");
--
-- if (retval->ack != 0xffff)
-- switch (retval->ack) {
-- case 0x0000: { /* added successfully */
-- } break;
--
-- case 0x000c: { /* you are over the limit, the cheat is to the limit, come on fhqwhgads */
-- gchar *buf;
-- buf = g_strdup_printf(_("Unable to add the buddy %s because you have too many buddies in your buddy list. Please remove one and try again."), (retval->name ? retval->name : _("(no name)")));
-- if ((retval->name != NULL) && !purple_conv_present_error(retval->name, purple_connection_get_account(gc), buf))
-- purple_notify_error(gc, NULL, _("Unable to Add"), buf);
-- g_free(buf);
-- }
--
-- case 0x000e: { /* buddy requires authorization */
-- if ((retval->action == SNAC_SUBTYPE_FEEDBAG_ADD) && (retval->name))
-- oscar_auth_sendrequest(gc, retval->name, NULL);
-- } break;
--
-- default: { /* La la la */
-- gchar *buf;
-- purple_debug_error("oscar", "ssi: Action 0x%04hx was unsuccessful with error 0x%04hx\n", retval->action, retval->ack);
-- buf = g_strdup_printf(_("Unable to add the buddy %s for an unknown reason."),
-- (retval->name ? retval->name : _("(no name)")));
-- if ((retval->name != NULL) && !purple_conv_present_error(retval->name, purple_connection_get_account(gc), buf))
-- purple_notify_error(gc, NULL, _("Unable to Add"), buf);
-- g_free(buf);
-- } break;
-- }
--
-- retval = retval->next;
-- }
--
-- return 1;
--}
--
--static int
--purple_ssi_parseaddmod(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
--{
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- char *gname, *gname_utf8, *alias, *alias_utf8;
-- PurpleBuddy *b;
-- PurpleGroup *g;
-- struct aim_ssi_item *ssi_item;
-- va_list ap;
-- guint16 snac_subtype, type;
-- const char *name;
--
-- gc = od->gc;
-- account = purple_connection_get_account(gc);
--
-- va_start(ap, fr);
-- snac_subtype = (guint16)va_arg(ap, int);
-- type = (guint16)va_arg(ap, int);
-- name = va_arg(ap, char *);
-- va_end(ap);
--
-- if ((type != 0x0000) || (name == NULL))
-- return 1;
--
-- gname = aim_ssi_itemlist_findparentname(od->ssi.local, name);
-- gname_utf8 = gname ? oscar_utf8_try_convert(account, od, gname) : NULL;
--
-- alias = aim_ssi_getalias(od->ssi.local, gname, name);
-- alias_utf8 = oscar_utf8_try_convert(account, od, alias);
-- g_free(alias);
--
-- b = purple_find_buddy(account, name);
-- if (b) {
-- /*
-- * You're logged in somewhere else and you aliased one
-- * of your buddies, so update our local buddy list with
-- * the person's new alias.
-- */
-- purple_blist_alias_buddy(b, alias_utf8);
-- } else if (snac_subtype == 0x0008) {
-- /*
-- * You're logged in somewhere else and you added a buddy to
-- * your server list, so add them to your local buddy list.
-- */
-- b = purple_buddy_new(account, name, alias_utf8);
--
-- if (!(g = purple_find_group(gname_utf8 ? gname_utf8 : _("Orphans")))) {
-- g = purple_group_new(gname_utf8 ? gname_utf8 : _("Orphans"));
-- purple_blist_add_group(g, NULL);
-- }
--
-- purple_debug_info("oscar",
-- "ssi: adding buddy %s to group %s to local list\n", name, gname_utf8 ? gname_utf8 : _("Orphans"));
-- purple_blist_add_buddy(b, NULL, g, NULL);
--
-- /* Mobile users should always be online */
-- if (name[0] == '+') {
-- purple_prpl_got_user_status(account,
-- name, OSCAR_STATUS_ID_AVAILABLE, NULL);
-- purple_prpl_got_user_status(account,
-- name, OSCAR_STATUS_ID_MOBILE, NULL);
-- }
--
-- }
--
-- ssi_item = aim_ssi_itemlist_finditem(od->ssi.local,
-- gname, name, AIM_SSI_TYPE_BUDDY);
-- if (ssi_item == NULL)
-- {
-- purple_debug_error("oscar", "purple_ssi_parseaddmod: "
-- "Could not find ssi item for oncoming buddy %s, "
-- "group %s\n", name, gname);
-- }
--
-- g_free(gname_utf8);
-- g_free(alias_utf8);
--
-- return 1;
--}
--
--static int purple_ssi_authgiven(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- PurpleConnection *gc = od->gc;
-- va_list ap;
-- char *bn, *msg;
-- gchar *dialog_msg, *nombre;
-- struct name_data *data;
-- PurpleBuddy *buddy;
--
-- va_start(ap, fr);
-- bn = va_arg(ap, char *);
-- msg = va_arg(ap, char *);
-- va_end(ap);
--
-- purple_debug_info("oscar",
-- "ssi: %s has given you permission to add him to your buddy list\n", bn);
--
-- buddy = purple_find_buddy(purple_connection_get_account(gc), bn);
-- if (buddy && (purple_buddy_get_alias_only(buddy)))
-- nombre = g_strdup_printf("%s (%s)", bn, purple_buddy_get_alias_only(buddy));
-- else
-- nombre = g_strdup(bn);
--
-- dialog_msg = g_strdup_printf(_("The user %s has given you permission to add him or her to your buddy list. Do you want to add this user?"), nombre);
-- g_free(nombre);
--
-- data = g_new(struct name_data, 1);
-- data->gc = gc;
-- data->name = g_strdup(bn);
-- data->nick = (buddy ? g_strdup(purple_buddy_get_alias_only(buddy)) : NULL);
--
-- purple_request_yes_no(gc, NULL, _("Authorization Given"), dialog_msg,
-- PURPLE_DEFAULT_ACTION_NONE,
-- purple_connection_get_account(gc), bn, NULL,
-- data,
-- G_CALLBACK(purple_icq_buddyadd),
-- G_CALLBACK(oscar_free_name_data));
-- g_free(dialog_msg);
--
-- return 1;
--}
--
--static int purple_ssi_authrequest(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
--{
-- va_list ap;
-- const char *bn;
-- char *msg;
--
-- va_start(ap, fr);
-- bn = va_arg(ap, const char *);
-- msg = va_arg(ap, char *);
-- va_end(ap);
--
-- purple_debug_info("oscar",
-- "ssi: received authorization request from %s\n", bn);
--
-- if (!msg) {
-- purple_debug_warning("oscar", "Received auth request from %s with "
-- "empty message\n", bn);
-- } else if (!g_utf8_validate(msg, -1, NULL)) {
-- purple_debug_warning("oscar", "Received auth request from %s with "
-- "invalid UTF-8 message\n", bn);
-- msg = NULL;
-- }
--
-- aim_icq_getalias(od, bn, TRUE, msg);
-- return 1;
--}
--
--static int purple_ssi_authreply(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- PurpleConnection *gc = od->gc;
-- va_list ap;
-- char *bn, *msg;
-- gchar *dialog_msg, *nombre;
-- guint8 reply;
-- PurpleBuddy *buddy;
--
-- va_start(ap, fr);
-- bn = va_arg(ap, char *);
-- reply = (guint8)va_arg(ap, int);
-- msg = va_arg(ap, char *);
-- va_end(ap);
--
-- purple_debug_info("oscar",
-- "ssi: received authorization reply from %s. Reply is 0x%04hhx\n", bn, reply);
--
-- buddy = purple_find_buddy(purple_connection_get_account(gc), bn);
-- if (buddy && (purple_buddy_get_alias_only(buddy)))
-- nombre = g_strdup_printf("%s (%s)", bn, purple_buddy_get_alias_only(buddy));
-- else
-- nombre = g_strdup(bn);
--
-- if (reply) {
-- /* Granted */
-- dialog_msg = g_strdup_printf(_("The user %s has granted your request to add them to your buddy list."), nombre);
-- purple_notify_info(gc, NULL, _("Authorization Granted"), dialog_msg);
-- } else {
-- /* Denied */
-- dialog_msg = g_strdup_printf(_("The user %s has denied your request to add them to your buddy list for the following reason:\n%s"), nombre, msg ? msg : _("No reason given."));
-- purple_notify_info(gc, NULL, _("Authorization Denied"), dialog_msg);
-- }
-- g_free(dialog_msg);
-- g_free(nombre);
--
-- return 1;
--}
--
--static int purple_ssi_gotadded(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
-- PurpleConnection *gc = od->gc;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- va_list ap;
-- char *bn;
-- PurpleBuddy *buddy;
--
-- va_start(ap, fr);
-- bn = va_arg(ap, char *);
-- va_end(ap);
--
-- buddy = purple_find_buddy(account, bn);
-- purple_debug_info("oscar", "ssi: %s added you to their buddy list\n", bn);
-- purple_account_notify_added(account, bn, NULL,
-- (buddy ? purple_buddy_get_alias_only(buddy) : NULL), NULL);
--
-- return 1;
--}
--
--GList *oscar_chat_info(PurpleConnection *gc) {
-- GList *m = NULL;
-- struct proto_chat_entry *pce;
--
-- pce = g_new0(struct proto_chat_entry, 1);
-- pce->label = _("_Room:");
-- pce->identifier = "room";
-- pce->required = TRUE;
-- m = g_list_append(m, pce);
--
-- pce = g_new0(struct proto_chat_entry, 1);
-- pce->label = _("_Exchange:");
-- pce->identifier = "exchange";
-- pce->required = TRUE;
-- pce->is_int = TRUE;
-- pce->min = 4;
-- pce->max = 20;
-- m = g_list_append(m, pce);
--
-- return m;
--}
--
--GHashTable *oscar_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, "room", g_strdup(chat_name));
-- g_hash_table_insert(defaults, "exchange", g_strdup("4"));
--
-- return defaults;
--}
--
--char *
--oscar_get_chat_name(GHashTable *data)
--{
-- return g_strdup(g_hash_table_lookup(data, "room"));
--}
--
--void
--oscar_join_chat(PurpleConnection *gc, GHashTable *data)
--{
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- FlapConnection *conn;
-- char *name, *exchange;
-- int exchange_int;
--
-- name = g_hash_table_lookup(data, "room");
-- exchange = g_hash_table_lookup(data, "exchange");
--
-- g_return_if_fail(name != NULL && *name != '\0');
-- g_return_if_fail(exchange != NULL);
--
-- errno = 0;
-- exchange_int = strtol(exchange, NULL, 10);
-- g_return_if_fail(errno == 0);
--
-- purple_debug_info("oscar", "Attempting to join chat room %s.\n", name);
--
-- if ((conn = flap_connection_getbytype(od, SNAC_FAMILY_CHATNAV)))
-- {
-- purple_debug_info("oscar", "chatnav exists, creating room\n");
-- aim_chatnav_createroom(od, conn, name, exchange_int);
-- } else {
-- /* this gets tricky */
-- struct create_room *cr = g_new0(struct create_room, 1);
-- purple_debug_info("oscar", "chatnav does not exist, opening chatnav\n");
-- cr->exchange = exchange_int;
-- cr->name = g_strdup(name);
-- od->create_rooms = g_slist_prepend(od->create_rooms, cr);
-- aim_srv_requestnew(od, SNAC_FAMILY_CHATNAV);
-- }
--}
--
--void
--oscar_chat_invite(PurpleConnection *gc, int id, const char *message, const char *name)
--{
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- struct chat_connection *ccon = find_oscar_chat(gc, id);
--
-- if (ccon == NULL)
-- return;
--
-- aim_im_sendch2_chatinvite(od, name, message ? message : "",
-- ccon->exchange, ccon->name, 0x0);
--}
--
--void
--oscar_chat_leave(PurpleConnection *gc, int id)
--{
-- PurpleConversation *conv;
-- struct chat_connection *cc;
--
-- conv = purple_find_chat(gc, id);
--
-- g_return_if_fail(conv != NULL);
--
-- purple_debug_info("oscar", "Leaving chat room %s\n",
-- purple_conversation_get_name(conv));
--
-- cc = find_oscar_chat(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)));
-- flap_connection_schedule_destroy(cc->conn, OSCAR_DISCONNECT_DONE, NULL);
-- oscar_chat_kill(gc, cc);
--}
--
--int oscar_send_chat(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)
--{
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- PurpleConversation *conv = NULL;
-- struct chat_connection *c = NULL;
-- char *buf, *buf2, *buf3;
-- guint16 charset;
-- char *charsetstr;
-- gsize len;
--
-- if (!(conv = purple_find_chat(gc, id)))
-- return -EINVAL;
--
-- if (!(c = find_oscar_chat_by_conv(gc, conv)))
-- return -EINVAL;
--
-- buf = purple_strdup_withhtml(message);
--
-- if (strstr(buf, "<IMG "))
-- purple_conversation_write(conv, "",
-- _("Your IM Image was not sent. "
-- "You cannot send IM Images in AIM chats."),
-- PURPLE_MESSAGE_ERROR, time(NULL));
--
-- buf2 = oscar_encode_im(buf, &len, &charset, &charsetstr);
-- /*
-- * Evan S. suggested that maxvis really does mean "number of
-- * visible characters" and not "number of bytes"
-- */
-- if ((len > c->maxlen) || (len > c->maxvis)) {
-- /* If the length was too long, try stripping the HTML and then running it back through
-- * purple_strdup_withhtml() and the encoding process. The result may be shorter. */
-- g_free(buf2);
--
-- buf3 = purple_markup_strip_html(buf);
-- g_free(buf);
--
-- buf = purple_strdup_withhtml(buf3);
-- g_free(buf3);
--
-- buf2 = oscar_encode_im(buf, &len, &charset, &charsetstr);
--
-- if ((len > c->maxlen) || (len > c->maxvis)) {
-- purple_debug_warning("oscar",
-- "Could not send %s because (%" G_GSIZE_FORMAT " > maxlen %i) or (%" G_GSIZE_FORMAT " > maxvis %i)\n",
-- buf2, len, c->maxlen, len, c->maxvis);
-- g_free(buf);
-- g_free(buf2);
-- return -E2BIG;
-- }
--
-- purple_debug_info("oscar", "Sending %s as %s because the original was too long.\n",
-- message, buf2);
-- }
--
-- aim_chat_send_im(od, c->conn, 0, buf2, len, charsetstr, "en");
-- g_free(buf2);
-- g_free(buf);
--
-- return 0;
--}
--
--PurpleMood* oscar_get_purple_moods(PurpleAccount *account)
--{
-- return icq_get_purple_moods(account);
--}
--
--const char *oscar_list_icon_icq(PurpleAccount *a, PurpleBuddy *b)
--{
-- const char *name = b ? purple_buddy_get_name(b) : NULL;
-- if (name && !oscar_util_valid_name_sms(name) && oscar_util_valid_name_icq(name))
-- return "icq";
--
-- return "icq";
--}
--
--const char *oscar_list_icon_aim(PurpleAccount *a, PurpleBuddy *b)
--{
-- const char *name = b ? purple_buddy_get_name(b) : NULL;
-- if (name && !oscar_util_valid_name_sms(name) && oscar_util_valid_name_icq(name))
-- return "icq";
--
-- return "aim";
--}
--
--const char *oscar_list_emblem(PurpleBuddy *b)
--{
-- PurpleConnection *gc = NULL;
-- OscarData *od = NULL;
-- PurpleAccount *account = NULL;
-- PurplePresence *presence;
-- PurpleStatus *status;
-- const char *status_id;
-- aim_userinfo_t *userinfo = NULL;
-- const char *name;
--
-- account = purple_buddy_get_account(b);
-- name = purple_buddy_get_name(b);
-- if (account != NULL)
-- gc = purple_account_get_connection(account);
-- if (gc != NULL)
-- od = purple_connection_get_protocol_data(gc);
-- if (od != NULL)
-- userinfo = aim_locate_finduserinfo(od, name);
--
-- presence = purple_buddy_get_presence(b);
-- status = purple_presence_get_active_status(presence);
-- status_id = purple_status_get_id(status);
--
-- if (purple_presence_is_online(presence) == FALSE) {
-- char *gname;
-- if ((name) && (od) && (od->ssi.received_data) &&
-- (gname = aim_ssi_itemlist_findparentname(od->ssi.local, name)) &&
-- (aim_ssi_waitingforauth(od->ssi.local, gname, name))) {
-- return "not-authorized";
-- }
-- }
--
-- if (userinfo != NULL ) {
-- if (userinfo->flags & AIM_FLAG_ADMINISTRATOR)
-- return "admin";
-- if (userinfo->flags & AIM_FLAG_ACTIVEBUDDY)
-- return "bot";
-- if (userinfo->capabilities & OSCAR_CAPABILITY_SECUREIM)
-- return "secure";
-- if (userinfo->icqinfo.status & AIM_ICQ_STATE_BIRTHDAY)
-- return "birthday";
--
-- /* Make the mood icon override anything below this. */
-- if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_MOOD))
-- return NULL;
--
-- if (userinfo->capabilities & OSCAR_CAPABILITY_HIPTOP)
-- return "hiptop";
-- }
-- return NULL;
--}
--
--void oscar_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
--{
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- OscarData *od;
-- aim_userinfo_t *userinfo;
--
-- if (!PURPLE_BUDDY_IS_ONLINE(b))
-- return;
--
-- account = purple_buddy_get_account(b);
-- gc = purple_account_get_connection(account);
-- od = purple_connection_get_protocol_data(gc);
-- userinfo = aim_locate_finduserinfo(od, purple_buddy_get_name(b));
--
-- oscar_user_info_append_status(gc, user_info, b, userinfo, /* use_html_status */ FALSE);
--
-- if (full)
-- oscar_user_info_append_extra_info(gc, user_info, b, userinfo);
--}
--
--char *oscar_status_text(PurpleBuddy *b)
--{
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- OscarData *od;
-- const PurplePresence *presence;
-- const PurpleStatus *status;
-- const char *id;
-- const char *message;
-- gchar *ret = NULL;
--
-- gc = purple_account_get_connection(purple_buddy_get_account(b));
-- account = purple_connection_get_account(gc);
-- od = purple_connection_get_protocol_data(gc);
-- presence = purple_buddy_get_presence(b);
-- status = purple_presence_get_active_status(presence);
-- id = purple_status_get_id(status);
--
-- if ((od != NULL) && !purple_presence_is_online(presence))
-- {
-- const char *name = purple_buddy_get_name(b);
-- char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, name);
-- if (aim_ssi_waitingforauth(od->ssi.local, gname, name))
-- ret = g_strdup(_("Not Authorized"));
-- else
-- ret = g_strdup(_("Offline"));
-- }
-- else
-- {
-- message = purple_status_get_attr_string(status, "message");
-- if (message != NULL)
-- {
-- gchar *tmp = oscar_util_format_string(message, purple_account_get_username(account));
-- ret = purple_markup_escape_text(tmp, -1);
-- g_free(tmp);
-- }
-- else if (purple_status_is_available(status))
-- {
-- /* Don't show "Available" as status message in case buddy doesn't have a status message */
-- }
-- else
-- {
-- ret = g_strdup(purple_status_get_name(status));
-- }
-- }
--
-- return ret;
--}
--
--void oscar_set_aim_permdeny(PurpleConnection *gc) {
-- PurpleAccount *account = purple_connection_get_account(gc);
-- OscarData *od = purple_connection_get_protocol_data(gc);
--
-- /*
-- * Conveniently there is a one-to-one mapping between the
-- * values of libpurple's PurplePrivacyType and the values used
-- * by the oscar protocol.
-- */
-- aim_ssi_setpermdeny(od, account->perm_deny);
--}
--
--void oscar_add_permit(PurpleConnection *gc, const char *who) {
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- purple_debug_info("oscar", "ssi: About to add a permit\n");
-- aim_ssi_add_to_private_list(od, who, AIM_SSI_TYPE_PERMIT);
--}
--
--void oscar_add_deny(PurpleConnection *gc, const char *who) {
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- purple_debug_info("oscar", "ssi: About to add a deny\n");
-- aim_ssi_add_to_private_list(od, who, aim_ssi_getdenyentrytype(od));
--}
--
--void oscar_rem_permit(PurpleConnection *gc, const char *who) {
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- purple_debug_info("oscar", "ssi: About to delete a permit\n");
-- aim_ssi_del_from_private_list(od, who, AIM_SSI_TYPE_PERMIT);
--}
--
--void oscar_rem_deny(PurpleConnection *gc, const char *who) {
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- purple_debug_info("oscar", "ssi: About to delete a deny\n");
-- aim_ssi_del_from_private_list(od, who, aim_ssi_getdenyentrytype(od));
--}
--
--GList *
--oscar_status_types(PurpleAccount *account)
--{
-- gboolean is_icq;
-- GList *status_types = NULL;
-- PurpleStatusType *type;
--
-- g_return_val_if_fail(account != NULL, NULL);
--
-- /* Used to flag some statuses as "user settable" or not */
-- is_icq = oscar_util_valid_name_icq(purple_account_get_username(account));
--
-- /* Common status types */
-- /* Really the available message should only be settable for AIM accounts */
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
-- OSCAR_STATUS_ID_AVAILABLE,
-- NULL, TRUE, TRUE, FALSE,
-- "message", _("Message"),
-- purple_value_new(PURPLE_TYPE_STRING),
-- "itmsurl", _("iTunes Music Store Link"),
-- purple_value_new(PURPLE_TYPE_STRING), NULL);
-- status_types = g_list_prepend(status_types, type);
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
-- OSCAR_STATUS_ID_FREE4CHAT,
-- _("Free For Chat"), TRUE, is_icq, FALSE,
-- "message", _("Message"),
-- purple_value_new(PURPLE_TYPE_STRING), NULL);
--
-- status_types = g_list_prepend(status_types, type);
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
-- OSCAR_STATUS_ID_EVIL,
-- _("Evil"), TRUE, is_icq, FALSE,
-- "message", _("Message"),
-- purple_value_new(PURPLE_TYPE_STRING), NULL);
-- status_types = g_list_prepend(status_types, type);
--
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
-- OSCAR_STATUS_ID_DEPRESSION,
-- _("Depression"), TRUE, is_icq, FALSE,
-- "message", _("Message"),
-- purple_value_new(PURPLE_TYPE_STRING), NULL);
-- status_types = g_list_prepend(status_types, type);
--
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
-- OSCAR_STATUS_ID_ATHOME,
-- _("At home"), TRUE, is_icq, FALSE,
-- "message", _("Message"),
-- purple_value_new(PURPLE_TYPE_STRING), NULL);
-- status_types = g_list_prepend(status_types, type);
--
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
-- OSCAR_STATUS_ID_ATWORK,
-- _("At work"), TRUE, is_icq, FALSE,
-- "message", _("Message"),
-- purple_value_new(PURPLE_TYPE_STRING), NULL);
--
-- status_types = g_list_prepend(status_types, type);
--
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
-- OSCAR_STATUS_ID_LUNCH,
-- _("Lunch"), TRUE, is_icq, FALSE,
-- "message", _("Message"),
-- purple_value_new(PURPLE_TYPE_STRING), NULL);
--
-- status_types = g_list_prepend(status_types, type);
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY,
-- OSCAR_STATUS_ID_AWAY,
-- NULL, TRUE, TRUE, FALSE,
-- "message", _("Message"),
-- purple_value_new(PURPLE_TYPE_STRING), NULL);
-- status_types = g_list_prepend(status_types, type);
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_INVISIBLE,
-- OSCAR_STATUS_ID_INVISIBLE,
-- NULL, TRUE, TRUE, FALSE,
-- "message", _("Message"),
-- purple_value_new(PURPLE_TYPE_STRING), NULL);
--
-- status_types = g_list_prepend(status_types, type);
--
-- type = purple_status_type_new_full(PURPLE_STATUS_MOBILE, OSCAR_STATUS_ID_MOBILE, NULL, FALSE, FALSE, TRUE);
-- status_types = g_list_prepend(status_types, type);
--
-- /* ICQ-specific status types */
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE,
-- OSCAR_STATUS_ID_OCCUPIED,
-- _("Occupied"), TRUE, is_icq, FALSE,
-- "message", _("Message"),
-- purple_value_new(PURPLE_TYPE_STRING), NULL);
-- status_types = g_list_prepend(status_types, type);
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE,
-- OSCAR_STATUS_ID_DND,
-- _("Do Not Disturb"), TRUE, is_icq, FALSE,
-- "message", _("Message"),
-- purple_value_new(PURPLE_TYPE_STRING), NULL);
-- status_types = g_list_prepend(status_types, type);
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_EXTENDED_AWAY,
-- OSCAR_STATUS_ID_NA,
-- _("Not Available"), TRUE, is_icq, FALSE,
-- "message", _("Message"),
-- purple_value_new(PURPLE_TYPE_STRING), NULL);
-- status_types = g_list_prepend(status_types, type);
--
-- type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE,
-- OSCAR_STATUS_ID_OFFLINE,
-- NULL, TRUE, TRUE, FALSE);
-- status_types = g_list_prepend(status_types, type);
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_MOOD,
-- "mood", NULL, TRUE, is_icq, TRUE,
-- PURPLE_MOOD_NAME, _("Mood Name"), purple_value_new(PURPLE_TYPE_STRING),
-- PURPLE_MOOD_COMMENT, _("Mood Comment"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- status_types = g_list_prepend(status_types, type);
--
-- return g_list_reverse(status_types);
--}
--
--static void oscar_ssi_editcomment(struct name_data *data, const char *text) {
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- OscarData *od;
-- PurpleBuddy *b;
-- PurpleGroup *g;
--
-- gc = data->gc;
-- od = purple_connection_get_protocol_data(gc);
-- account = purple_connection_get_account(gc);
--
-- b = purple_find_buddy(account, data->name);
-- if (b == NULL) {
-- oscar_free_name_data(data);
-- return;
-- }
--
-- g = purple_buddy_get_group(b);
-- if (g == NULL) {
-- oscar_free_name_data(data);
-- return;
-- }
--
-- aim_ssi_editcomment(od, purple_group_get_name(g), data->name, text);
-- oscar_free_name_data(data);
--}
--
--static void oscar_buddycb_edit_comment(PurpleBlistNode *node, gpointer ignore) {
--
-- PurpleBuddy *buddy;
-- PurpleConnection *gc;
-- OscarData *od;
-- struct name_data *data;
-- PurpleGroup *g;
-- char *comment;
-- gchar *comment_utf8;
-- gchar *title;
-- PurpleAccount *account;
-- const char *name;
--
-- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
--
-- buddy = (PurpleBuddy *) node;
-- name = purple_buddy_get_name(buddy);
-- account = purple_buddy_get_account(buddy);
-- gc = purple_account_get_connection(account);
-- od = purple_connection_get_protocol_data(gc);
--
-- if (!(g = purple_buddy_get_group(buddy)))
-- return;
--
-- data = g_new(struct name_data, 1);
--
-- comment = aim_ssi_getcomment(od->ssi.local, purple_group_get_name(g), name);
-- comment_utf8 = comment ? oscar_utf8_try_convert(account, od, comment) : NULL;
--
-- data->gc = gc;
-- data->name = g_strdup(name);
-- data->nick = g_strdup(purple_buddy_get_alias_only(buddy));
--
-- title = g_strdup_printf(_("Buddy Comment for %s"), data->name);
-- purple_request_input(gc, title, _("Buddy Comment:"), NULL,
-- comment_utf8, TRUE, FALSE, NULL,
-- _("_OK"), G_CALLBACK(oscar_ssi_editcomment),
-- _("_Cancel"), G_CALLBACK(oscar_free_name_data),
-- account, data->name, NULL,
-- data);
-- g_free(title);
--
-- g_free(comment);
-- g_free(comment_utf8);
--}
--
--static void
--oscar_ask_directim_yes_cb(struct oscar_ask_directim_data *data)
--{
-- peer_connection_propose(data->od, OSCAR_CAPABILITY_DIRECTIM, data->who);
-- g_free(data->who);
-- g_free(data);
--}
--
--static void
--oscar_ask_directim_no_cb(struct oscar_ask_directim_data *data)
--{
-- g_free(data->who);
-- g_free(data);
--}
--
--/* This is called from right-click menu on a buddy node. */
--static void
--oscar_ask_directim(gpointer object, gpointer ignored)
--{
-- PurpleBlistNode *node;
-- PurpleBuddy *buddy;
-- PurpleConnection *gc;
-- gchar *buf;
-- struct oscar_ask_directim_data *data;
-- PurpleAccount *account;
--
-- node = object;
--
-- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
--
-- buddy = (PurpleBuddy *)node;
-- account = purple_buddy_get_account(buddy);
-- gc = purple_account_get_connection(account);
--
-- data = g_new0(struct oscar_ask_directim_data, 1);
-- data->who = g_strdup(purple_buddy_get_name(buddy));
-- data->od = purple_connection_get_protocol_data(gc);
-- buf = g_strdup_printf(_("You have selected to open a Direct IM connection with %s."),
-- data->who);
--
-- purple_request_action(gc, NULL, buf,
-- _("Because this reveals your IP address, it "
-- "may be considered a security risk. Do you "
-- "wish to continue?"),
-- 0, /* Default action is "connect" */
-- account, data->who, NULL,
-- data, 2,
-- _("C_onnect"), G_CALLBACK(oscar_ask_directim_yes_cb),
-- _("_Cancel"), G_CALLBACK(oscar_ask_directim_no_cb));
-- g_free(buf);
--}
--
--static void
--oscar_close_directim(gpointer object, gpointer ignored)
--{
-- PurpleBlistNode *node;
-- PurpleBuddy *buddy;
-- PurpleAccount *account;
-- PurpleConnection *gc;
-- PurpleConversation *conv;
-- OscarData *od;
-- PeerConnection *conn;
-- const char *name;
--
-- node = object;
--
-- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
--
-- buddy = (PurpleBuddy*)node;
-- name = purple_buddy_get_name(buddy);
-- account = purple_buddy_get_account(buddy);
-- gc = purple_account_get_connection(account);
-- od = gc->proto_data;
-- conn = peer_connection_find_by_type(od, name, OSCAR_CAPABILITY_DIRECTIM);
--
-- if (conn != NULL)
-- {
-- if (!conn->ready)
-- aim_im_sendch2_cancel(conn);
--
-- peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);
--
-- /* OSCAR_DISCONNECT_LOCAL_CLOSED doesn't write anything to the convo
-- * window. Let the user know that we cancelled the Direct IM. */
-- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, name);
-- purple_conversation_write(conv, NULL, _("You closed the connection."),
-- PURPLE_MESSAGE_SYSTEM, time(NULL));
-- }
--}
--
--static void oscar_get_icqxstatusmsg(PurpleBlistNode *node, gpointer ignore)
--{
-- PurpleBuddy *buddy;
-- PurpleConnection *gc;
-- OscarData *od;
-- PurpleAccount *account;
-- const char *bname;
--
-- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
--
-- buddy = (PurpleBuddy *)node;
-- bname = purple_buddy_get_name(buddy);
--
-- account = purple_buddy_get_account(buddy);
-- gc = purple_account_get_connection(account);
-- od = purple_connection_get_protocol_data(gc);
--
-- purple_debug_info("oscar", "Manual X-Status Get From %s to %s:\n", bname, purple_account_get_username(account));
--
-- icq_im_xstatus_request(od, bname);
--}
--
--static void
--oscar_get_aim_info_cb(PurpleBlistNode *node, gpointer ignore)
--{
-- PurpleBuddy *buddy;
-- PurpleConnection *gc;
--
-- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
--
-- buddy = (PurpleBuddy *)node;
-- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
--
-- aim_locate_getinfoshort(purple_connection_get_protocol_data(gc),
-- purple_buddy_get_name(buddy), 0x00000003);
--}
--
--static GList *
--oscar_buddy_menu(PurpleBuddy *buddy) {
-- PurpleConnection *gc;
-- OscarData *od;
-- GList *menu;
-- PurpleMenuAction *act;
-- aim_userinfo_t *userinfo;
-- PurpleAccount *account;
-- const char *bname = purple_buddy_get_name(buddy);
--
-- account = purple_buddy_get_account(buddy);
-- gc = purple_account_get_connection(account);
-- od = purple_connection_get_protocol_data(gc);
-- userinfo = aim_locate_finduserinfo(od, bname);
-- menu = NULL;
--
-- if (od->icq && oscar_util_valid_name_icq(bname))
-- {
-- act = purple_menu_action_new(_("Get AIM Info"),
-- PURPLE_CALLBACK(oscar_get_aim_info_cb),
-- NULL, NULL);
-- menu = g_list_prepend(menu, act);
-- }
--
-- if (purple_buddy_get_group(buddy) != NULL)
-- {
-- /* We only do this if the user is in our buddy list */
-- act = purple_menu_action_new(_("Edit Buddy Comment"),
-- PURPLE_CALLBACK(oscar_buddycb_edit_comment),
-- NULL, NULL);
-- menu = g_list_prepend(menu, act);
-- }
--
-- if (od->icq)
-- {
-- act = purple_menu_action_new(_("Get X-Status Msg"),
-- PURPLE_CALLBACK(oscar_get_icqxstatusmsg),
-- NULL, NULL);
-- menu = g_list_prepend(menu, act);
-- menu = g_list_prepend(menu, create_visibility_menu_item(od, bname));
-- }
--
-- if (userinfo &&
-- oscar_util_name_compare(purple_account_get_username(account), bname) &&
-- PURPLE_BUDDY_IS_ONLINE(buddy))
-- {
-- PeerConnection *conn;
-- conn = peer_connection_find_by_type(od, bname, OSCAR_CAPABILITY_DIRECTIM);
--
-- if (userinfo->capabilities & OSCAR_CAPABILITY_DIRECTIM)
-- {
-- if (conn)
-- {
-- act = purple_menu_action_new(_("End Direct IM Session"),
-- PURPLE_CALLBACK(oscar_close_directim),
-- NULL, NULL);
-- }
-- else
-- {
-- act = purple_menu_action_new(_("Direct IM"),
-- PURPLE_CALLBACK(oscar_ask_directim),
-- NULL, NULL);
-- }
-- menu = g_list_prepend(menu, act);
-- }
-- }
--
-- if (od->ssi.received_data && purple_buddy_get_group(buddy) != NULL)
-- {
-- /*
-- * We only do this if the user is in our buddy list and we're
-- * waiting for authorization.
-- */
-- char *gname;
-- gname = aim_ssi_itemlist_findparentname(od->ssi.local, bname);
-- if (gname && aim_ssi_waitingforauth(od->ssi.local, gname, bname))
-- {
-- act = purple_menu_action_new(_("Re-request Authorization"),
-- PURPLE_CALLBACK(oscar_auth_sendrequest_menu),
-- NULL, NULL);
-- menu = g_list_prepend(menu, act);
-- }
-- }
--
-- menu = g_list_reverse(menu);
--
-- return menu;
--}
--
--
--GList *oscar_blist_node_menu(PurpleBlistNode *node) {
-- if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
-- return oscar_buddy_menu((PurpleBuddy *) node);
-- } else {
-- return NULL;
-- }
--}
--
--static void
--oscar_icq_privacy_opts(PurpleConnection *gc, PurpleRequestFields *fields)
--{
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- PurpleAccount *account = purple_connection_get_account(gc);
-- PurpleRequestField *f;
-- gboolean auth, web_aware;
--
-- f = purple_request_fields_get_field(fields, "authorization");
-- auth = purple_request_field_bool_get_value(f);
--
-- f = purple_request_fields_get_field(fields, "web_aware");
-- web_aware = purple_request_field_bool_get_value(f);
--
-- purple_account_set_bool(account, "authorization", auth);
-- purple_account_set_bool(account, "web_aware", web_aware);
--
-- oscar_set_extended_status(gc);
-- aim_icq_setsecurity(od, auth, web_aware);
--}
--
--static void
--oscar_show_icq_privacy_opts(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *) action->context;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- PurpleRequestFields *fields;
-- PurpleRequestFieldGroup *g;
-- PurpleRequestField *f;
-- gboolean auth, web_aware;
--
-- auth = purple_account_get_bool(account, "authorization", OSCAR_DEFAULT_AUTHORIZATION);
-- web_aware = purple_account_get_bool(account, "web_aware", OSCAR_DEFAULT_WEB_AWARE);
--
-- fields = purple_request_fields_new();
--
-- g = purple_request_field_group_new(NULL);
--
-- f = purple_request_field_bool_new("authorization", _("Require authorization"), auth);
-- purple_request_field_group_add_field(g, f);
--
-- f = purple_request_field_bool_new("web_aware", _("Web aware (enabling this will cause you to receive SPAM!)"), web_aware);
-- purple_request_field_group_add_field(g, f);
--
-- purple_request_fields_add_group(fields, g);
--
-- purple_request_fields(gc, _("ICQ Privacy Options"), _("ICQ Privacy Options"),
-- NULL, fields,
-- _("OK"), G_CALLBACK(oscar_icq_privacy_opts),
-- _("Cancel"), NULL,
-- purple_connection_get_account(gc), NULL, NULL,
-- gc);
--}
--
--static void oscar_confirm_account(PurplePluginAction *action)
--{
-- PurpleConnection *gc;
-- OscarData *od;
-- FlapConnection *conn;
--
-- gc = (PurpleConnection *)action->context;
-- od = purple_connection_get_protocol_data(gc);
--
-- conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN);
-- if (conn != NULL) {
-- aim_admin_reqconfirm(od, conn);
-- } else {
-- od->conf = TRUE;
-- aim_srv_requestnew(od, SNAC_FAMILY_ADMIN);
-- }
--}
--
--static void oscar_show_email(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *) action->context;
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- FlapConnection *conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN);
--
-- if (conn) {
-- aim_admin_getinfo(od, conn, 0x11);
-- } else {
-- od->reqemail = TRUE;
-- aim_srv_requestnew(od, SNAC_FAMILY_ADMIN);
-- }
--}
--
--static void oscar_change_email(PurpleConnection *gc, const char *email)
--{
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- FlapConnection *conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN);
--
-- if (conn) {
-- aim_admin_setemail(od, conn, email);
-- } else {
-- od->setemail = TRUE;
-- od->email = g_strdup(email);
-- aim_srv_requestnew(od, SNAC_FAMILY_ADMIN);
-- }
--}
--
--static void oscar_show_change_email(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *) action->context;
-- purple_request_input(gc, NULL, _("Change Address To:"), NULL, NULL,
-- FALSE, FALSE, NULL,
-- _("_OK"), G_CALLBACK(oscar_change_email),
-- _("_Cancel"), NULL,
-- purple_connection_get_account(gc), NULL, NULL,
-- gc);
--}
--
--static void oscar_show_awaitingauth(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *) action->context;
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- PurpleAccount *account = purple_connection_get_account(gc);
-- GSList *buddies, *filtered_buddies, *cur;
-- gchar *text;
--
-- buddies = purple_find_buddies(account, NULL);
-- filtered_buddies = NULL;
-- for (cur = buddies; cur != NULL; cur = cur->next) {
-- PurpleBuddy *buddy;
-- const gchar *bname, *gname;
--
-- buddy = cur->data;
-- bname = purple_buddy_get_name(buddy);
-- gname = purple_group_get_name(purple_buddy_get_group(buddy));
-- if (aim_ssi_waitingforauth(od->ssi.local, gname, bname)) {
-- filtered_buddies = g_slist_prepend(filtered_buddies, buddy);
-- }
-- }
--
-- g_slist_free(buddies);
--
-- filtered_buddies = g_slist_reverse(filtered_buddies);
-- text = oscar_format_buddies(filtered_buddies, _("you are not waiting for authorization"));
-- g_slist_free(filtered_buddies);
--
-- purple_notify_formatted(gc, NULL, _("You are awaiting authorization from "
-- "the following buddies"), _("You can re-request "
-- "authorization from these buddies by "
-- "right-clicking on them and selecting "
-- "\"Re-request Authorization.\""), text, NULL, NULL);
-- g_free(text);
--}
--
--static void search_by_email_cb(PurpleConnection *gc, const char *email)
--{
-- OscarData *od = purple_connection_get_protocol_data(gc);
--
-- aim_search_address(od, email);
--}
--
--static void oscar_show_find_email(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *) action->context;
-- purple_request_input(gc, _("Find Buddy by Email"),
-- _("Search for a buddy by email address"),
-- _("Type the email address of the buddy you are "
-- "searching for."),
-- NULL, FALSE, FALSE, NULL,
-- _("_Search"), G_CALLBACK(search_by_email_cb),
-- _("_Cancel"), NULL,
-- purple_connection_get_account(gc), NULL, NULL,
-- gc);
--}
--
--static void oscar_show_set_info(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *) action->context;
-- purple_account_request_change_user_info(purple_connection_get_account(gc));
--}
--
--static void oscar_show_set_info_icqurl(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *) action->context;
-- purple_notify_uri(gc, "http://www.icq.com/whitepages/user_details.php");
--}
--
--static void oscar_change_pass(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *) action->context;
-- purple_account_request_change_password(purple_connection_get_account(gc));
--}
--
--/**
-- * Only used when connecting with the old-style BUCP login.
-- */
--static void oscar_show_chpassurl(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *) action->context;
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- gchar *substituted = purple_strreplace(od->authinfo->chpassurl, "%s", purple_account_get_username(purple_connection_get_account(gc)));
-- purple_notify_uri(gc, substituted);
-- g_free(substituted);
--}
--
--static void oscar_show_imforwardingurl(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *) action->context;
-- purple_notify_uri(gc, "http://mymobile.aol.com/dbreg/register?action=imf&clientID=1");
--}
--
--void oscar_set_icon(PurpleConnection *gc, PurpleStoredImage *img)
--{
-- OscarData *od = purple_connection_get_protocol_data(gc);
--
-- if (img == NULL) {
-- aim_ssi_delicon(od);
-- } else {
-- PurpleCipherContext *context;
-- guchar md5[16];
-- gconstpointer data = purple_imgstore_get_data(img);
-- size_t len = purple_imgstore_get_size(img);
--
-- context = purple_cipher_context_new_by_name("md5", NULL);
-- purple_cipher_context_append(context, data, len);
-- purple_cipher_context_digest(context, 16, md5, NULL);
-- purple_cipher_context_destroy(context);
--
-- aim_ssi_seticon(od, md5, 16);
-- }
--}
--
--/**
-- * Called by the Purple core to determine whether or not we're
-- * allowed to send a file to this user.
-- */
--gboolean
--oscar_can_receive_file(PurpleConnection *gc, const char *who)
--{
-- OscarData *od;
-- PurpleAccount *account;
--
-- od = purple_connection_get_protocol_data(gc);
-- account = purple_connection_get_account(gc);
--
-- if (od != NULL)
-- {
-- aim_userinfo_t *userinfo;
-- userinfo = aim_locate_finduserinfo(od, who);
--
-- /*
-- * Don't allowing sending a file to a user that does not support
-- * file transfer, and don't allow sending to ourselves.
-- */
-- if (((userinfo == NULL) ||
-- (userinfo->capabilities & OSCAR_CAPABILITY_SENDFILE)) &&
-- oscar_util_name_compare(who, purple_account_get_username(account)))
-- {
-- return TRUE;
-- }
-- }
--
-- return FALSE;
--}
--
--PurpleXfer *
--oscar_new_xfer(PurpleConnection *gc, const char *who)
--{
-- PurpleXfer *xfer;
-- OscarData *od;
-- PurpleAccount *account;
-- PeerConnection *conn;
--
-- od = purple_connection_get_protocol_data(gc);
-- account = purple_connection_get_account(gc);
--
-- xfer = purple_xfer_new(account, PURPLE_XFER_SEND, who);
-- if (xfer)
-- {
-- purple_xfer_ref(xfer);
-- purple_xfer_set_init_fnc(xfer, peer_oft_sendcb_init);
-- purple_xfer_set_cancel_send_fnc(xfer, peer_oft_cb_generic_cancel);
-- purple_xfer_set_request_denied_fnc(xfer, peer_oft_cb_generic_cancel);
-- purple_xfer_set_ack_fnc(xfer, peer_oft_sendcb_ack);
--
-- conn = peer_connection_new(od, OSCAR_CAPABILITY_SENDFILE, who);
-- conn->flags |= PEER_CONNECTION_FLAG_INITIATED_BY_ME;
-- conn->flags |= PEER_CONNECTION_FLAG_APPROVED;
-- aim_icbm_makecookie(conn->cookie);
-- conn->xfer = xfer;
-- xfer->data = conn;
-- }
--
-- return xfer;
--}
--
--/*
-- * Called by the Purple core when the user indicates that a
-- * file is to be sent to a special someone.
-- */
--void
--oscar_send_file(PurpleConnection *gc, const char *who, const char *file)
--{
-- PurpleXfer *xfer;
--
-- xfer = oscar_new_xfer(gc, who);
--
-- if (file != NULL)
-- purple_xfer_request_accepted(xfer, file);
-- else
-- purple_xfer_request(xfer);
--}
--
--GList *
--oscar_actions(PurplePlugin *plugin, gpointer context)
--{
-- PurpleConnection *gc = (PurpleConnection *) context;
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- GList *menu = NULL;
-- PurplePluginAction *act;
--
-- act = purple_plugin_action_new(_("Set User Info..."),
-- oscar_show_set_info);
-- menu = g_list_prepend(menu, act);
--
-- if (od->icq)
-- {
-- act = purple_plugin_action_new(_("Set User Info (web)..."),
-- oscar_show_set_info_icqurl);
-- menu = g_list_prepend(menu, act);
-- }
--
-- act = purple_plugin_action_new(_("Change Password..."),
-- oscar_change_pass);
-- menu = g_list_prepend(menu, act);
--
-- if (od->authinfo != NULL && od->authinfo->chpassurl != NULL)
-- {
-- /* This only happens when connecting with the old-style BUCP login */
-- act = purple_plugin_action_new(_("Change Password (web)"),
-- oscar_show_chpassurl);
-- menu = g_list_prepend(menu, act);
-- }
--
-- if (!od->icq)
-- {
-- act = purple_plugin_action_new(_("Configure IM Forwarding (web)"),
-- oscar_show_imforwardingurl);
-- menu = g_list_prepend(menu, act);
-- }
--
-- menu = g_list_prepend(menu, NULL);
--
-- if (od->icq)
-- {
-- /* ICQ actions */
-- act = purple_plugin_action_new(_("Set Privacy Options..."),
-- oscar_show_icq_privacy_opts);
-- menu = g_list_prepend(menu, act);
--
-- act = purple_plugin_action_new(_("Show Visible List"), oscar_show_visible_list);
-- menu = g_list_prepend(menu, act);
--
-- act = purple_plugin_action_new(_("Show Invisible List"), oscar_show_invisible_list);
-- menu = g_list_prepend(menu, act);
-- }
-- else
-- {
-- /* AIM actions */
-- act = purple_plugin_action_new(_("Confirm Account"),
-- oscar_confirm_account);
-- menu = g_list_prepend(menu, act);
--
-- act = purple_plugin_action_new(_("Display Currently Registered Email Address"),
-- oscar_show_email);
-- menu = g_list_prepend(menu, act);
--
-- act = purple_plugin_action_new(_("Change Currently Registered Email Address..."),
-- oscar_show_change_email);
-- menu = g_list_prepend(menu, act);
-- }
--
-- menu = g_list_prepend(menu, NULL);
--
-- act = purple_plugin_action_new(_("Show Buddies Awaiting Authorization"),
-- oscar_show_awaitingauth);
-- menu = g_list_prepend(menu, act);
--
-- menu = g_list_prepend(menu, NULL);
--
-- act = purple_plugin_action_new(_("Search for Buddy by Email Address..."),
-- oscar_show_find_email);
-- menu = g_list_prepend(menu, act);
--
-- menu = g_list_reverse(menu);
--
-- return menu;
--}
--
--void oscar_change_passwd(PurpleConnection *gc, const char *old, const char *new)
--{
-- OscarData *od = purple_connection_get_protocol_data(gc);
--
-- if (od->icq) {
-- aim_icq_changepasswd(od, new);
-- } else {
-- FlapConnection *conn;
-- conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN);
-- if (conn) {
-- aim_admin_changepasswd(od, conn, new, old);
-- } else {
-- od->chpass = TRUE;
-- od->oldp = g_strdup(old);
-- od->newp = g_strdup(new);
-- aim_srv_requestnew(od, SNAC_FAMILY_ADMIN);
-- }
-- }
--}
--
--void
--oscar_convo_closed(PurpleConnection *gc, const char *who)
--{
-- OscarData *od;
-- PeerConnection *conn;
--
-- od = purple_connection_get_protocol_data(gc);
-- conn = peer_connection_find_by_type(od, who, OSCAR_CAPABILITY_DIRECTIM);
--
-- if (conn != NULL)
-- {
-- if (!conn->ready)
-- aim_im_sendch2_cancel(conn);
--
-- peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);
-- }
--}
--
--const char *
--oscar_normalize(const PurpleAccount *account, const char *str)
--{
-- static char buf[BUF_LEN];
-- char *tmp1, *tmp2;
-- int i, j;
--
-- g_return_val_if_fail(str != NULL, NULL);
--
-- /* copy str to buf and skip all blanks */
-- i = 0;
-- for (j = 0; str[j]; j++) {
-- if (str[j] != ' ') {
-- buf[i++] = str[j];
-- if (i >= BUF_LEN - 1)
-- break;
-- }
-- }
-- buf[i] = '\0';
--
-- tmp1 = g_utf8_strdown(buf, -1);
-- tmp2 = g_utf8_normalize(tmp1, -1, G_NORMALIZE_DEFAULT);
-- if (strlen(tmp2) > sizeof(buf) - 1) {
-- purple_debug_error("oscar", "normalized string exceeds buffer length!\n");
-- }
-- g_strlcpy(buf, tmp2, sizeof(buf));
-- g_free(tmp2);
-- g_free(tmp1);
--
-- return buf;
--}
--
--gboolean
--oscar_offline_message(const PurpleBuddy *buddy)
--{
-- return TRUE;
--}
--
--/* TODO: Find somewhere to put this instead of including it in a bunch of places.
-- * Maybe just change purple_accounts_find() to return anything for the prpl if there is no acct_id.
-- */
--static PurpleAccount *find_acct(const char *prpl, const char *acct_id)
--{
-- PurpleAccount *acct = NULL;
--
-- /* If we have a specific acct, use it */
-- if (acct_id) {
-- acct = purple_accounts_find(acct_id, prpl);
-- if (acct && !purple_account_is_connected(acct))
-- acct = NULL;
-- } else { /* Otherwise find an active account for the protocol */
-- GList *l = purple_accounts_get_all();
-- while (l) {
-- if (!strcmp(prpl, purple_account_get_protocol_id(l->data))
-- && purple_account_is_connected(l->data)) {
-- acct = l->data;
-- break;
-- }
-- l = l->next;
-- }
-- }
--
-- return acct;
--}
--
--
--static gboolean oscar_uri_handler(const char *proto, const char *cmd, GHashTable *params)
--{
-- char *acct_id = g_hash_table_lookup(params, "account");
-- char prpl[11];
-- PurpleAccount *acct;
--
-- if (g_ascii_strcasecmp(proto, "aim") && g_ascii_strcasecmp(proto, "icq"))
-- return FALSE;
--
-- g_snprintf(prpl, sizeof(prpl), "prpl-%s", proto);
--
-- acct = find_acct(prpl, acct_id);
--
-- if (!acct)
-- return FALSE;
--
-- /* aim:GoIM?screenname=SCREENNAME&message=MESSAGE */
-- if (!g_ascii_strcasecmp(cmd, "GoIM")) {
-- char *bname = g_hash_table_lookup(params, "screenname");
-- if (bname) {
-- char *message = g_hash_table_lookup(params, "message");
--
-- PurpleConversation *conv = purple_find_conversation_with_account(
-- PURPLE_CONV_TYPE_IM, bname, acct);
-- if (conv == NULL)
-- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, bname);
-- purple_conversation_present(conv);
--
-- if (message) {
-- /* Spaces are encoded as '+' */
-- g_strdelimit(message, "+", ' ');
-- purple_conv_send_confirm(conv, message);
-- }
-- }
-- /*else
-- **If pidgindialogs_im() was in the core, we could use it here.
-- * It is all purple_request_* based, but I'm not sure it really belongs in the core
-- pidgindialogs_im();*/
--
-- return TRUE;
-- }
-- /* aim:GoChat?roomname=CHATROOMNAME&exchange=4 */
-- else if (!g_ascii_strcasecmp(cmd, "GoChat")) {
-- char *rname = g_hash_table_lookup(params, "roomname");
-- if (rname) {
-- /* This is somewhat hacky, but the params aren't useful after this command */
-- g_hash_table_insert(params, g_strdup("exchange"), g_strdup("4"));
-- g_hash_table_insert(params, g_strdup("room"), g_strdup(rname));
-- serv_join_chat(purple_account_get_connection(acct), params);
-- }
-- /*else
-- ** Same as above (except that this would have to be re-written using purple_request_*)
-- pidgin_blist_joinchat_show(); */
--
-- return TRUE;
-- }
-- /* aim:AddBuddy?screenname=SCREENNAME&groupname=GROUPNAME*/
-- else if (!g_ascii_strcasecmp(cmd, "AddBuddy")) {
-- char *bname = g_hash_table_lookup(params, "screenname");
-- char *gname = g_hash_table_lookup(params, "groupname");
-- purple_blist_request_add_buddy(acct, bname, gname, NULL);
-- return TRUE;
-- }
--
-- return FALSE;
--}
--
--void oscar_init(PurplePlugin *plugin, gboolean is_icq)
--{
-- PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
-- PurpleAccountOption *option;
-- static gboolean init = FALSE;
-- static const gchar *encryption_keys[] = {
-- N_("Use encryption if available"),
-- N_("Require encryption"),
-- N_("Don't use encryption"),
-- NULL
-- };
-- static const gchar *encryption_values[] = {
-- OSCAR_OPPORTUNISTIC_ENCRYPTION,
-- OSCAR_REQUIRE_ENCRYPTION,
-- OSCAR_NO_ENCRYPTION,
-- NULL
-- };
-- GList *encryption_options = NULL;
-- int i;
--
-- option = purple_account_option_string_new(_("Server"), "server", get_login_server(is_icq, TRUE));
-- prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
--
-- option = purple_account_option_int_new(_("Port"), "port", OSCAR_DEFAULT_LOGIN_PORT);
-- prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
--
-- for (i = 0; encryption_keys[i]; i++) {
-- PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1);
-- kvp->key = g_strdup(_(encryption_keys[i]));
-- kvp->value = g_strdup(encryption_values[i]);
-- encryption_options = g_list_append(encryption_options, kvp);
-- }
-- option = purple_account_option_list_new(_("Connection security"), "encryption", encryption_options);
-- prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
--
-- option = purple_account_option_bool_new(_("Use clientLogin"), "use_clientlogin",
-- OSCAR_DEFAULT_USE_CLIENTLOGIN);
-- prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
--
-- option = purple_account_option_bool_new(
-- _("Always use AIM/ICQ proxy server for\nfile transfers and direct IM (slower,\nbut does not reveal your IP address)"), "always_use_rv_proxy",
-- OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY);
-- prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
--
-- if (g_str_equal(purple_plugin_get_id(plugin), "prpl-aim")) {
-- option = purple_account_option_bool_new(_("Allow multiple simultaneous logins"), "allow_multiple_logins",
-- OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS);
-- prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
-- }
--
-- if (init)
-- return;
-- init = TRUE;
--
-- /* Preferences */
-- purple_prefs_add_none("/plugins/prpl/oscar");
-- purple_prefs_add_bool("/plugins/prpl/oscar/recent_buddies", FALSE);
--
-- purple_prefs_remove("/plugins/prpl/oscar/show_idle");
-- purple_prefs_remove("/plugins/prpl/oscar/always_use_rv_proxy");
--
-- /* protocol handler */
-- /* TODO: figure out a good instance to use here */
-- purple_signal_connect(purple_get_core(), "uri-handler", &init,
-- PURPLE_CALLBACK(oscar_uri_handler), NULL);
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/oscarcommon.h pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oscarcommon.h
---- pidgin-2.10.7/libpurple/protocols/oscar/oscarcommon.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oscarcommon.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,106 +0,0 @@
--/* purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--/* oscarcommon.h contains prototypes for the prpl functions used by libaim.c
-- * and libicq.c
-- */
--
--#include "internal.h"
--
--#include "accountopt.h"
--#include "prpl.h"
--#include "version.h"
--#include "notify.h"
--#include "status.h"
--
--#define AIM_DEFAULT_LOGIN_SERVER "login.oscar.aol.com"
--#define AIM_ALT_LOGIN_SERVER "login.messaging.aol.com"
--#define AIM_DEFAULT_SSL_LOGIN_SERVER "slogin.oscar.aol.com"
--#define ICQ_DEFAULT_LOGIN_SERVER "login.icq.com"
--#define ICQ_DEFAULT_SSL_LOGIN_SERVER "slogin.icq.com"
--
--#define OSCAR_DEFAULT_LOGIN_PORT 5190
--
--#define OSCAR_OPPORTUNISTIC_ENCRYPTION "opportunistic_encryption"
--#define OSCAR_REQUIRE_ENCRYPTION "require_encryption"
--#define OSCAR_NO_ENCRYPTION "no_encryption"
--
--#ifndef _WIN32
--#define OSCAR_DEFAULT_CUSTOM_ENCODING "ISO-8859-1"
--#else
--#define OSCAR_DEFAULT_CUSTOM_ENCODING oscar_get_locale_charset()
--#endif
--#define OSCAR_DEFAULT_AUTHORIZATION TRUE
--#define OSCAR_DEFAULT_HIDE_IP TRUE
--#define OSCAR_DEFAULT_WEB_AWARE FALSE
--#define OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY FALSE
--#define OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS TRUE
--#define OSCAR_DEFAULT_USE_CLIENTLOGIN TRUE
--#define OSCAR_DEFAULT_ENCRYPTION OSCAR_OPPORTUNISTIC_ENCRYPTION
--
--#ifdef _WIN32
--const char *oscar_get_locale_charset(void);
--#endif
--PurpleMood* oscar_get_purple_moods(PurpleAccount *account);
--const char *oscar_list_icon_icq(PurpleAccount *a, PurpleBuddy *b);
--const char *oscar_list_icon_aim(PurpleAccount *a, PurpleBuddy *b);
--const char* oscar_list_emblem(PurpleBuddy *b);
--char *oscar_status_text(PurpleBuddy *b);
--void oscar_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full);
--GList *oscar_status_types(PurpleAccount *account);
--GList *oscar_blist_node_menu(PurpleBlistNode *node);
--GList *oscar_chat_info(PurpleConnection *gc);
--GHashTable *oscar_chat_info_defaults(PurpleConnection *gc, const char *chat_name);
--void oscar_login(PurpleAccount *account);
--void oscar_close(PurpleConnection *gc);
--int oscar_send_im(PurpleConnection *gc, const char *name, const char *message, PurpleMessageFlags imflags);
--void oscar_set_info(PurpleConnection *gc, const char *rawinfo);
--unsigned int oscar_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state);
--void oscar_get_info(PurpleConnection *gc, const char *name);
--void oscar_set_status(PurpleAccount *account, PurpleStatus *status);
--void oscar_set_idle(PurpleConnection *gc, int time);
--void oscar_change_passwd(PurpleConnection *gc, const char *old, const char *new);
--void oscar_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *msg);
--void oscar_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
--void oscar_add_permit(PurpleConnection *gc, const char *who);
--void oscar_add_deny(PurpleConnection *gc, const char *who);
--void oscar_rem_permit(PurpleConnection *gc, const char *who);
--void oscar_rem_deny(PurpleConnection *gc, const char *who);
--void oscar_join_chat(PurpleConnection *gc, GHashTable *data);
--char *oscar_get_chat_name(GHashTable *data);
--void oscar_chat_invite(PurpleConnection *gc, int id, const char *message, const char *name);
--void oscar_chat_leave(PurpleConnection *gc, int id);
--int oscar_send_chat(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags);
--void oscar_keepalive(PurpleConnection *gc);
--void oscar_alias_buddy(PurpleConnection *gc, const char *name, const char *alias);
--void oscar_move_buddy(PurpleConnection *gc, const char *name, const char *old_group, const char *new_group);
--void oscar_rename_group(PurpleConnection *gc, const char *old_name, PurpleGroup *group, GList *moved_buddies);
--void oscar_convo_closed(PurpleConnection *gc, const char *who);
--const char *oscar_normalize(const PurpleAccount *account, const char *str);
--void oscar_set_icon(PurpleConnection *gc, PurpleStoredImage *img);
--void oscar_remove_group(PurpleConnection *gc, PurpleGroup *group);
--gboolean oscar_can_receive_file(PurpleConnection *gc, const char *who);
--void oscar_send_file(PurpleConnection *gc, const char *who, const char *file);
--PurpleXfer *oscar_new_xfer(PurpleConnection *gc, const char *who);
--gboolean oscar_offline_message(const PurpleBuddy *buddy);
--GList *oscar_actions(PurplePlugin *plugin, gpointer context);
--void oscar_init(PurplePlugin *plugin, gboolean is_icq);
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/oscar_data.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oscar_data.c
---- pidgin-2.10.7/libpurple/protocols/oscar/oscar_data.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oscar_data.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,157 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--#include "oscar.h"
--
--typedef struct _SnacHandler SnacHandler;
--
--struct _SnacHandler
--{
-- guint16 family;
-- guint16 subtype;
-- aim_rxcallback_t handler;
-- guint16 flags;
--};
--
--/**
-- * Allocates a new OscarData and initializes it with default values.
-- */
--OscarData *
--oscar_data_new(void)
--{
-- OscarData *od;
-- aim_module_t *cur;
-- GString *msg;
--
-- od = g_new0(OscarData, 1);
--
-- aim_initsnachash(od);
-- od->snacid_next = 0x00000001;
-- od->buddyinfo = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-- od->handlerlist = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
--
-- /*
-- * Register all the modules for this session...
-- */
-- aim__registermodule(od, misc_modfirst); /* load the catch-all first */
-- aim__registermodule(od, service_modfirst);
-- aim__registermodule(od, locate_modfirst);
-- aim__registermodule(od, buddylist_modfirst);
-- aim__registermodule(od, msg_modfirst);
-- aim__registermodule(od, admin_modfirst);
-- aim__registermodule(od, popups_modfirst);
-- aim__registermodule(od, bos_modfirst);
-- aim__registermodule(od, search_modfirst);
-- aim__registermodule(od, stats_modfirst);
-- aim__registermodule(od, chatnav_modfirst);
-- aim__registermodule(od, chat_modfirst);
-- aim__registermodule(od, bart_modfirst);
-- /* missing 0x11 - 0x12 */
-- aim__registermodule(od, ssi_modfirst);
-- /* missing 0x14 */
-- aim__registermodule(od, icq_modfirst);
-- /* missing 0x16 */
-- /* auth_modfirst is only needed if we're connecting with the old-style BUCP login */
-- aim__registermodule(od, auth_modfirst);
-- aim__registermodule(od, email_modfirst);
--
-- msg = g_string_new("Registered modules: ");
-- for (cur = od->modlistv; cur; cur = cur->next) {
-- g_string_append_printf(
-- msg,
-- "%s (family=0x%04x, version=0x%04x, toolid=0x%04x, toolversion=0x%04x), ",
-- cur->name,
-- cur->family,
-- cur->version,
-- cur->toolid,
-- cur->toolversion);
-- }
-- purple_debug_misc("oscar", "%s\n", msg->str);
-- g_string_free(msg, TRUE);
--
-- return od;
--}
--
--/**
-- * Logoff and deallocate a session.
-- *
-- * @param od Session to kill
-- */
--void
--oscar_data_destroy(OscarData *od)
--{
-- aim_cleansnacs(od, -1);
--
-- /* Only used when connecting with clientLogin */
-- if (od->url_data != NULL)
-- purple_util_fetch_url_cancel(od->url_data);
--
-- while (od->requesticon)
-- {
-- g_free(od->requesticon->data);
-- od->requesticon = g_slist_delete_link(od->requesticon, od->requesticon);
-- }
-- g_free(od->email);
-- g_free(od->newp);
-- g_free(od->oldp);
-- if (od->getblisttimer > 0)
-- purple_timeout_remove(od->getblisttimer);
-- while (od->oscar_connections != NULL)
-- flap_connection_destroy(od->oscar_connections->data,
-- OSCAR_DISCONNECT_DONE, NULL);
--
-- while (od->peer_connections != NULL)
-- peer_connection_destroy(od->peer_connections->data,
-- OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);
--
-- aim__shutdownmodules(od);
--
-- g_hash_table_destroy(od->buddyinfo);
-- g_hash_table_destroy(od->handlerlist);
--
-- g_free(od);
--}
--
--void
--oscar_data_addhandler(OscarData *od, guint16 family, guint16 subtype, aim_rxcallback_t newhandler, guint16 flags)
--{
-- SnacHandler *snac_handler;
--
-- snac_handler = g_new0(SnacHandler, 1);
--
-- snac_handler->family = family;
-- snac_handler->subtype = subtype;
-- snac_handler->flags = flags;
-- snac_handler->handler = newhandler;
--
-- g_hash_table_insert(od->handlerlist,
-- GUINT_TO_POINTER((family << 16) + subtype),
-- snac_handler);
--}
--
--aim_rxcallback_t
--aim_callhandler(OscarData *od, guint16 family, guint16 subtype)
--{
-- SnacHandler *snac_handler;
--
-- snac_handler = g_hash_table_lookup(od->handlerlist, GUINT_TO_POINTER((family << 16) + subtype));
--
-- return snac_handler ? snac_handler->handler : NULL;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/oscar.h pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oscar.h
---- pidgin-2.10.7/libpurple/protocols/oscar/oscar.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oscar.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1350 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Main libfaim header. Must be included in client for prototypes/macros.
-- *
-- * "come on, i turned a chick lesbian; i think this is the hackish equivalent"
-- * -- Josh Myer
-- *
-- */
--
--#ifndef _OSCAR_H_
--#define _OSCAR_H_
--
--#include "internal.h"
--#include "circbuffer.h"
--#include "debug.h"
--#include "eventloop.h"
--#include "proxy.h"
--#include "sslconn.h"
--
--#include <stdio.h>
--#include <string.h>
--#include <fcntl.h>
--#include <sys/types.h>
--#include <stdlib.h>
--#include <stdarg.h>
--#include <errno.h>
--#include <time.h>
--
--#ifndef _WIN32
--#include <sys/time.h>
--#include <unistd.h>
--#include <netdb.h>
--#include <netinet/in.h>
--#include <sys/socket.h>
--#else
--#include "libc_interface.h"
--#endif
--
--typedef struct _ByteStream ByteStream;
--typedef struct _ClientInfo ClientInfo;
--typedef struct _FlapConnection FlapConnection;
--typedef struct _FlapFrame FlapFrame;
--typedef struct _IcbmArgsCh2 IcbmArgsCh2;
--typedef struct _IcbmCookie IcbmCookie;
--typedef struct _OscarData OscarData;
--typedef struct _QueuedSnac QueuedSnac;
--
--typedef guint32 aim_snacid_t;
--
--#include "snactypes.h"
--
--#ifdef __cplusplus
--extern "C" {
--#endif
--
--#define FAIM_SNAC_HASH_SIZE 16
--
--/*
-- * Current Maximum Length for usernames (not including NULL)
-- *
-- * Currently only names up to 16 characters can be registered
-- * however it is apparently legal for them to be larger.
-- */
--#define MAXSNLEN 97
--
--/*
-- * Current Maximum Length for Instant Messages
-- *
-- * This was found basically by experiment, but not wholly
-- * accurate experiment. It should not be regarded
-- * as completely correct. But its a decent approximation.
-- *
-- * Note that although we can send this much, its impossible
-- * for WinAIM clients (up through the latest (4.0.1957)) to
-- * send any more than 1kb. Amaze all your windows friends
-- * with utterly oversized instant messages!
-- */
--#define MAXMSGLEN 2544
--
--/*
-- * Maximum size of a Buddy Icon.
-- */
--#define MAXICONLEN 7168
--#define AIM_ICONIDENT "AVT1picture.id"
--
--/*
-- * Found by trial and error.
-- */
--#define MAXAVAILMSGLEN 251
--
--/**
-- * Maximum length for the password of an ICQ account
-- */
--#define MAXICQPASSLEN 8
--
--#define AIM_MD5_STRING "AOL Instant Messenger (SM)"
--
--/*
-- * Client info. Filled in by the client and passed in to
-- * aim_send_login(). The information ends up getting passed to OSCAR
-- * through the initial login command.
-- *
-- */
--struct _ClientInfo
--{
-- const char *clientstring;
-- guint16 clientid;
-- guint16 major;
-- guint16 minor;
-- guint16 point;
-- guint16 build;
-- guint32 distrib;
-- const char *country; /* two-letter abbrev */
-- const char *lang; /* two-letter abbrev */
--};
--
--/*
-- * We need to use the major-minor-micro versions from the official
-- * AIM and ICQ programs here or AOL won't let us use certain features.
-- *
-- * 0x00000611 is the distid given to us by AOL for use as the default
-- * libpurple distid.
-- */
--#define CLIENTINFO_PURPLE_AIM { \
-- NULL, \
-- 0x0109, \
-- 0x0005, 0x0001, \
-- 0x0000, 0x0bdc, \
-- 0x00000611, \
-- "us", "en", \
--}
--
--#define CLIENTINFO_PURPLE_ICQ { \
-- NULL, \
-- 0x010a, \
-- 0x0014, 0x0034, \
-- 0x0000, 0x0c18, \
-- 0x00000611, \
-- "us", "en", \
--}
--
--typedef enum
--{
-- OSCAR_DISCONNECT_DONE, /* not considered an error */
-- OSCAR_DISCONNECT_LOCAL_CLOSED, /* peer connections only, not considered an error */
-- OSCAR_DISCONNECT_REMOTE_CLOSED,
-- OSCAR_DISCONNECT_REMOTE_REFUSED, /* peer connections only */
-- OSCAR_DISCONNECT_LOST_CONNECTION,
-- OSCAR_DISCONNECT_INVALID_DATA,
-- OSCAR_DISCONNECT_COULD_NOT_CONNECT,
-- OSCAR_DISCONNECT_RETRYING /* peer connections only */
--} OscarDisconnectReason;
--
--#define OSCAR_CAPABILITY_BUDDYICON 0x0000000000000001LL
--#define OSCAR_CAPABILITY_TALK 0x0000000000000002LL
--#define OSCAR_CAPABILITY_DIRECTIM 0x0000000000000004LL
--#define OSCAR_CAPABILITY_CHAT 0x0000000000000008LL
--#define OSCAR_CAPABILITY_GETFILE 0x0000000000000010LL
--#define OSCAR_CAPABILITY_SENDFILE 0x0000000000000020LL
--#define OSCAR_CAPABILITY_GAMES 0x0000000000000040LL
--#define OSCAR_CAPABILITY_ADDINS 0x0000000000000080LL
--#define OSCAR_CAPABILITY_SENDBUDDYLIST 0x0000000000000100LL
--#define OSCAR_CAPABILITY_GAMES2 0x0000000000000200LL
--#define OSCAR_CAPABILITY_ICQ_DIRECT 0x0000000000000400LL
--#define OSCAR_CAPABILITY_APINFO 0x0000000000000800LL
--#define OSCAR_CAPABILITY_ICQRTF 0x0000000000001000LL
--#define OSCAR_CAPABILITY_EMPTY 0x0000000000002000LL
--#define OSCAR_CAPABILITY_ICQSERVERRELAY 0x0000000000004000LL
--#define OSCAR_CAPABILITY_UNICODEOLD 0x0000000000008000LL
--#define OSCAR_CAPABILITY_TRILLIANCRYPT 0x0000000000010000LL
--#define OSCAR_CAPABILITY_UNICODE 0x0000000000020000LL
--#define OSCAR_CAPABILITY_INTEROPERATE 0x0000000000040000LL
--#define OSCAR_CAPABILITY_SHORTCAPS 0x0000000000080000LL
--#define OSCAR_CAPABILITY_HIPTOP 0x0000000000100000LL
--#define OSCAR_CAPABILITY_SECUREIM 0x0000000000200000LL
--#define OSCAR_CAPABILITY_SMS 0x0000000000400000LL
--#define OSCAR_CAPABILITY_VIDEO 0x0000000000800000LL
--#define OSCAR_CAPABILITY_ICHATAV 0x0000000001000000LL
--#define OSCAR_CAPABILITY_LIVEVIDEO 0x0000000002000000LL
--#define OSCAR_CAPABILITY_CAMERA 0x0000000004000000LL
--#define OSCAR_CAPABILITY_ICHAT_SCREENSHARE 0x0000000008000000LL
--#define OSCAR_CAPABILITY_TYPING 0x0000000010000000LL
--#define OSCAR_CAPABILITY_NEWCAPS 0x0000000020000000LL
--#define OSCAR_CAPABILITY_XTRAZ 0x0000000040000000LL
--#define OSCAR_CAPABILITY_GENERICUNKNOWN 0x0000000080000000LL
--#define OSCAR_CAPABILITY_HTML_MSGS 0x0000000100000000LL
--#define OSCAR_CAPABILITY_LAST 0x0000000200000000LL
--
--#define OSCAR_STATUS_ID_INVISIBLE "invisible"
--#define OSCAR_STATUS_ID_OFFLINE "offline"
--#define OSCAR_STATUS_ID_AVAILABLE "available"
--#define OSCAR_STATUS_ID_AWAY "away"
--#define OSCAR_STATUS_ID_DND "dnd"
--#define OSCAR_STATUS_ID_NA "na"
--#define OSCAR_STATUS_ID_OCCUPIED "occupied"
--#define OSCAR_STATUS_ID_FREE4CHAT "free4chat"
--#define OSCAR_STATUS_ID_CUSTOM "custom"
--#define OSCAR_STATUS_ID_MOBILE "mobile"
--#define OSCAR_STATUS_ID_EVIL "evil"
--#define OSCAR_STATUS_ID_DEPRESSION "depression"
--#define OSCAR_STATUS_ID_ATHOME "athome"
--#define OSCAR_STATUS_ID_ATWORK "atwork"
--#define OSCAR_STATUS_ID_LUNCH "lunch"
--
--/*
-- * Byte Stream type. Sort of.
-- *
-- * Use of this type serves a couple purposes:
-- * - Buffer/buflen pairs are passed all around everywhere. This turns
-- * that into one value, as well as abstracting it slightly.
-- * - Through the abstraction, it is possible to enable bounds checking
-- * for robustness at the cost of performance. But a clean failure on
-- * weird packets is much better than a segfault.
-- * - I like having variables named "bs".
-- *
-- * Don't touch the insides of this struct. Or I'll have to kill you.
-- *
-- */
--struct _ByteStream
--{
-- guint8 *data;
-- size_t len;
-- size_t offset;
--};
--
--struct _QueuedSnac
--{
-- guint16 family;
-- guint16 subtype;
-- FlapFrame *frame;
--};
--
--struct _FlapFrame
--{
-- guint8 channel;
-- guint16 seqnum;
-- ByteStream data; /* payload stream */
--};
--
--struct _FlapConnection
--{
-- OscarData *od; /**< Pointer to parent session. */
-- gboolean connected;
-- time_t lastactivity; /**< Time of last transmit. */
-- guint destroy_timeout;
-- OscarDisconnectReason disconnect_reason;
-- gchar *error_message;
-- guint16 disconnect_code;
--
-- /* A few variables that are only used when connecting */
-- PurpleProxyConnectData *connect_data;
-- guint16 cookielen;
-- guint8 *cookie;
-- gpointer new_conn_data;
--
-- int fd;
-- PurpleSslConnection *gsc;
-- guint8 header[6];
-- gssize header_received;
-- FlapFrame buffer_incoming;
-- PurpleCircBuffer *buffer_outgoing;
-- guint watcher_incoming;
-- guint watcher_outgoing;
--
-- guint16 type;
-- guint16 subtype;
-- guint16 seqnum_out; /**< The sequence number of most recently sent packet. */
-- guint16 seqnum_in; /**< The sequence number of most recently received packet. */
-- GSList *groups;
-- GSList *rateclasses; /* Contains nodes of struct rateclass. */
-- struct rateclass *default_rateclass;
-- GHashTable *rateclass_members; /* Key is family and subtype, value is pointer to the rateclass struct to use. */
--
-- GQueue *queued_snacs; /**< Contains QueuedSnacs. */
-- GQueue *queued_lowpriority_snacs; /**< Contains QueuedSnacs to send only once queued_snacs is empty */
-- guint queued_timeout;
--
-- void *internal; /* internal conn-specific libfaim data */
--};
--
--struct _IcbmCookie
--{
-- guchar cookie[8];
-- int type;
-- void *data;
-- time_t addtime;
-- struct _IcbmCookie *next;
--};
--
--#include "peer.h"
--
--/*
-- * AIM Session: The main client-data interface.
-- *
-- */
--struct _OscarData
--{
-- /** Only used when connecting with clientLogin */
-- PurpleUtilFetchUrlData *url_data;
--
-- gboolean iconconnecting;
-- gboolean set_icon;
--
-- GSList *create_rooms;
--
-- gboolean conf;
-- gboolean reqemail;
-- gboolean setemail;
-- char *email;
-- gboolean setnick;
-- char *newformatting;
-- gboolean chpass;
-- char *oldp;
-- char *newp;
--
-- GSList *oscar_chats;
-- GHashTable *buddyinfo;
-- GSList *requesticon;
--
-- gboolean use_ssl;
-- gboolean icq;
-- guint getblisttimer;
--
-- struct {
-- guint maxwatchers; /* max users who can watch you */
-- guint maxbuddies; /* max users you can watch */
-- guint maxgroups; /* max groups in server list */
-- guint maxpermits; /* max users on permit list */
-- guint maxdenies; /* max users on deny list */
-- guint maxsiglen; /* max size (bytes) of profile */
-- guint maxawaymsglen; /* max size (bytes) of posted away message */
-- } rights;
--
-- PurpleConnection *gc;
--
-- void *modlistv;
--
-- /*
-- * Outstanding snac handling
-- *
-- * TODO: Should these be per-connection? -mid
-- */
-- void *snac_hash[FAIM_SNAC_HASH_SIZE];
-- aim_snacid_t snacid_next;
--
-- /*
-- * TODO: Data specific to a certain family should go into a
-- * hashtable and the core parts of libfaim shouldn't
-- * need to know about them.
-- */
--
-- IcbmCookie *msgcookies;
-- GSList *icq_info;
--
-- /** Only used when connecting with the old-style BUCP login. */
-- struct aim_authresp_info *authinfo;
-- struct aim_emailinfo *emailinfo;
--
-- struct {
-- struct aim_userinfo_s *userinfo;
-- } locate;
--
-- struct {
-- gboolean have_rights;
-- } bos;
--
-- /* Server-stored information (ssi) */
-- struct {
-- gboolean received_data;
-- guint16 numitems;
-- struct aim_ssi_item *official;
-- struct aim_ssi_item *local;
-- struct aim_ssi_tmp *pending;
-- time_t timestamp;
-- gboolean waiting_for_ack;
-- gboolean in_transaction;
-- } ssi;
--
-- /** Contains pointers to handler functions for each family/subtype. */
-- GHashTable *handlerlist;
--
-- /** A linked list containing FlapConnections. */
-- GSList *oscar_connections;
-- guint16 default_port;
--
-- /** A linked list containing PeerConnections. */
-- GSList *peer_connections;
--};
--
--/* Valid for calling aim_icq_setstatus() and for aim_userinfo_t->icqinfo.status */
--#define AIM_ICQ_STATE_NORMAL 0x00000000
--#define AIM_ICQ_STATE_AWAY 0x00000001
--#define AIM_ICQ_STATE_DND 0x00000002
--#define AIM_ICQ_STATE_OUT 0x00000004
--#define AIM_ICQ_STATE_BUSY 0x00000010
--#define AIM_ICQ_STATE_CHAT 0x00000020
--#define AIM_ICQ_STATE_INVISIBLE 0x00000100
--#define AIM_ICQ_STATE_EVIL 0x00003000
--#define AIM_ICQ_STATE_DEPRESSION 0x00004000
--#define AIM_ICQ_STATE_ATHOME 0x00005000
--#define AIM_ICQ_STATE_ATWORK 0x00006000
--#define AIM_ICQ_STATE_LUNCH 0x00002001
--#define AIM_ICQ_STATE_EVIL 0x00003000
--#define AIM_ICQ_STATE_WEBAWARE 0x00010000
--#define AIM_ICQ_STATE_HIDEIP 0x00020000
--#define AIM_ICQ_STATE_BIRTHDAY 0x00080000
--#define AIM_ICQ_STATE_ICQHOMEPAGE 0x00200000
--#define AIM_ICQ_STATE_DIRECTREQUIREAUTH 0x10000000
--
--/**
-- * Only used when connecting with the old-style BUCP login.
-- */
--struct aim_clientrelease
--{
-- char *name;
-- guint32 build;
-- char *url;
-- char *info;
--};
--
--/**
-- * Only used when connecting with the old-style BUCP login.
-- */
--struct aim_authresp_info
--{
-- char *bn;
-- guint16 errorcode;
-- char *errorurl;
-- guint16 regstatus;
-- char *email;
-- char *bosip;
-- guint16 cookielen;
-- guint8 *cookie;
-- char *chpassurl;
-- struct aim_clientrelease latestrelease;
-- struct aim_clientrelease latestbeta;
--};
--
--/* Callback data for redirect. */
--struct aim_redirect_data
--{
-- guint16 group;
-- const char *ip;
-- guint16 cookielen;
-- const guint8 *cookie;
-- const char *ssl_cert_cn;
-- guint8 use_ssl;
-- struct { /* group == SNAC_FAMILY_CHAT */
-- guint16 exchange;
-- const char *room;
-- guint16 instance;
-- } chat;
--};
--
--int oscar_connect_to_bos(PurpleConnection *gc, OscarData *od, const char *host, guint16 port, guint8 *cookie, guint16 cookielen, const char *tls_certname);
--
--/* family_auth.c */
--
--/**
-- * Only used when connecting with the old-style BUCP login.
-- */
--int aim_request_login(OscarData *od, FlapConnection *conn, const char *bn);
--
--/**
-- * Only used when connecting with the old-style BUCP login.
-- */
--int aim_send_login(OscarData *od, FlapConnection *conn, const char *bn, const char *password, gboolean truncate_pass, ClientInfo *ci, const char *key, gboolean allow_multiple_logins);
--
--/**
-- * Only used when connecting with the old-style BUCP login.
-- */
--/* 0x000b */ int aim_auth_securid_send(OscarData *od, const char *securid);
--
--/**
-- * Only used when connecting with clientLogin.
-- */
--void send_client_login(OscarData *od, const char *username);
--
--/* flap_connection.c */
--FlapConnection *flap_connection_new(OscarData *, int type);
--void flap_connection_close(OscarData *od, FlapConnection *conn);
--void flap_connection_destroy(FlapConnection *conn, OscarDisconnectReason reason, const gchar *error_message);
--void flap_connection_schedule_destroy(FlapConnection *conn, OscarDisconnectReason reason, const gchar *error_message);
--FlapConnection *flap_connection_findbygroup(OscarData *od, guint16 group);
--FlapConnection *flap_connection_getbytype(OscarData *, int type);
--FlapConnection *flap_connection_getbytype_all(OscarData *, int type);
--void flap_connection_recv_cb(gpointer data, gint source, PurpleInputCondition cond);
--void flap_connection_recv_cb_ssl(gpointer data, PurpleSslConnection *gsc, PurpleInputCondition cond);
--
--void flap_connection_send(FlapConnection *conn, FlapFrame *frame);
--void flap_connection_send_version(OscarData *od, FlapConnection *conn);
--void flap_connection_send_version_with_cookie(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy);
--void flap_connection_send_version_with_cookie_and_clientinfo(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy, ClientInfo *ci, gboolean allow_multiple_login);
--void flap_connection_send_snac(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, aim_snacid_t snacid, ByteStream *data);
--void flap_connection_send_snac_with_priority(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, aim_snacid_t snacid, ByteStream *data, gboolean high_priority);
--void flap_connection_send_keepalive(OscarData *od, FlapConnection *conn);
--FlapFrame *flap_frame_new(OscarData *od, guint16 channel, int datalen);
--
--/* oscar_data.c */
--typedef int (*aim_rxcallback_t)(OscarData *od, FlapConnection *conn, FlapFrame *frame, ...);
--
--OscarData *oscar_data_new(void);
--void oscar_data_destroy(OscarData *);
--void oscar_data_addhandler(OscarData *od, guint16 family, guint16 subtype, aim_rxcallback_t newhandler, guint16 flags);
--aim_rxcallback_t aim_callhandler(OscarData *od, guint16 family, guint16 subtype);
--
--/* 0x0001 - family_oservice.c */
--/* 0x0002 */ void aim_srv_clientready(OscarData *od, FlapConnection *conn);
--/* 0x0004 */ void aim_srv_requestnew(OscarData *od, guint16 serviceid);
--/* 0x0006 */ void aim_srv_reqrates(OscarData *od, FlapConnection *conn);
--/* 0x0008 */ void aim_srv_rates_addparam(OscarData *od, FlapConnection *conn);
--/* 0x000e */ void aim_srv_reqpersonalinfo(OscarData *od, FlapConnection *conn);
--/* 0x0011 */ void aim_srv_setidle(OscarData *od, guint32 idletime);
--/* 0x0017 */ void aim_srv_setversions(OscarData *od, FlapConnection *conn);
--/* 0x001e */ int aim_srv_setextrainfo(OscarData *od, gboolean seticqstatus, guint32 icqstatus, gboolean setstatusmsg, const char *statusmsg, const char *itmsurl);
--void aim_srv_set_dc_info(OscarData *od);
--
--
--void aim_bos_reqrights(OscarData *od, FlapConnection *conn);
--
--#define AIM_RATE_CODE_LIMIT 0x0003
--
--/* family_icbm.c */
--#define AIM_OFT_SUBTYPE_SEND_DIR 0x0002
--
--#define AIM_TRANSFER_DENY_DECLINE 0x0001
--
--#define AIM_IMPARAM_FLAG_CHANNEL_MSGS_ALLOWED 0x00000001
--#define AIM_IMPARAM_FLAG_MISSED_CALLS_ENABLED 0x00000002
--#define AIM_IMPARAM_FLAG_EVENTS_ALLOWED 0x00000008
--#define AIM_IMPARAM_FLAG_SMS_SUPPORTED 0x00000010
--#define AIM_IMPARAM_FLAG_OFFLINE_MSGS_ALLOWED 0x00000100
--
--/**
-- * This flag tells the server that we always send HTML in messages
-- * sent from an ICQ account to an ICQ account. (If this flag is
-- * not sent then plaintext is sent ICQ<-->ICQ (HTML is sent in all
-- * other cases)).
-- *
-- * If we send an HTML message to an old client that doesn't support
-- * HTML messages, then the oscar servers will merrily strip the HTML
-- * for us.
-- *
-- * All incoming IMs are treated as HTML.
-- */
--#define AIM_IMPARAM_FLAG_USE_HTML_FOR_ICQ 0x00000400
--
--struct aim_icbmparameters
--{
-- guint16 maxchan;
-- guint32 flags; /* AIM_IMPARAM_FLAG_ */
-- guint16 maxmsglen; /* message size that you will accept */
-- guint16 maxsenderwarn; /* this and below are *10 (999=99.9%) */
-- guint16 maxrecverwarn;
-- guint32 minmsginterval; /* in milliseconds? */
--};
--
--/*
-- * TODO: Should probably combine this with struct chat_connection.
-- */
--struct aim_chat_roominfo
--{
-- guint16 exchange;
-- char *name;
-- guint8 namelen;
-- guint16 instance;
--};
--
--struct chat_connection
--{
-- char *name;
-- char *show; /* AOL did something funny to us */
-- guint16 exchange;
-- guint16 instance;
-- FlapConnection *conn;
-- int id;
-- PurpleConnection *gc;
-- PurpleConversation *conv;
-- int maxlen;
-- int maxvis;
--};
--
--/*
-- * All this chat struct stuff should be in family_chat.c
-- */
--void oscar_chat_destroy(struct chat_connection *cc);
--
--#define AIM_IMFLAGS_AWAY 0x0001 /* mark as an autoreply */
--#define AIM_IMFLAGS_ACK 0x0002 /* request a receipt notice */
--#define AIM_IMFLAGS_BUDDYREQ 0x0010 /* buddy icon requested */
--#define AIM_IMFLAGS_HASICON 0x0020 /* already has icon */
--#define AIM_IMFLAGS_SUBENC_MACINTOSH 0x0040 /* damn that Steve Jobs! */
--#define AIM_IMFLAGS_CUSTOMFEATURES 0x0080 /* features field present */
--#define AIM_IMFLAGS_OFFLINE 0x0800 /* send to offline user */
--#define AIM_IMFLAGS_TYPINGNOT 0x1000 /* typing notification */
--
--#define AIM_CHARSET_ASCII 0x0000 /* ISO 646 */
--#define AIM_CHARSET_UNICODE 0x0002 /* ISO 10646 (UTF-16/UCS-2BE) */
--#define AIM_CHARSET_LATIN_1 0x0003 /* ISO 8859-1 */
--
--/*
-- * Arguments to aim_send_im_ext().
-- *
-- * This is really complicated. But immensely versatile.
-- *
-- */
--struct aim_sendimext_args
--{
-- /* These are _required_ */
-- const char *destbn;
-- guint32 flags; /* often 0 */
--
-- const char *msg;
-- gsize msglen;
--
-- /* Only used if AIM_IMFLAGS_HASICON is set */
-- guint32 iconlen;
-- time_t iconstamp;
-- guint32 iconsum;
--
-- guint16 featureslen;
-- guint8 *features;
--
-- guint16 charset;
--};
--
--/*
-- * This information is provided in the Incoming ICBM callback for
-- * Channel 1 ICBM's.
-- */
--struct aim_incomingim_ch1_args
--{
-- guint32 icbmflags; /* some flags apply only to ->msg, not all mpmsg */
-- time_t timestamp; /* Only set for offline messages */
--
-- gchar *msg;
--
-- /* Only provided if AIM_IMFLAGS_HASICON is set */
-- time_t iconstamp;
-- guint32 iconlen;
-- guint16 iconsum;
--};
--
--/* Valid values for channel 2 args->status */
--#define AIM_RENDEZVOUS_PROPOSE 0x0000
--#define AIM_RENDEZVOUS_CANCEL 0x0001
--#define AIM_RENDEZVOUS_CONNECTED 0x0002
--
--struct _IcbmArgsCh2
--{
-- guint16 status;
-- guchar cookie[8];
-- guint64 type; /* One of the OSCAR_CAPABILITY_ constants */
-- const char *proxyip;
-- const char *clientip;
-- const char *verifiedip;
-- guint16 port;
-- gboolean use_proxy;
-- guint16 errorcode;
-- const char *msg; /* invite message or file description */
-- guint16 msglen;
-- const char *encoding;
-- const char *language;
-- guint16 requestnumber;
-- union {
-- struct {
-- guint32 checksum;
-- guint32 length;
-- time_t timestamp;
-- guint8 *icon;
-- } icon;
-- struct {
-- struct aim_chat_roominfo roominfo;
-- } chat;
-- struct {
-- guint8 msgtype;
-- const char *msg;
-- } rtfmsg;
-- struct {
-- guint16 subtype;
-- guint16 totfiles;
-- guint32 totsize;
-- char *filename;
-- } sendfile;
-- } info;
-- void *destructor; /* used internally only */
--};
--
--struct aim_incomingim_ch4_args
--{
-- guint32 uin; /* Of the sender of the ICBM */
-- guint8 type;
-- guint8 flags;
-- gchar *msg; /* Reason for auth request, deny, or accept */
-- int msglen;
--};
--
--/* SNAC sending functions */
--/* 0x0002 */ int aim_im_setparams(OscarData *od, struct aim_icbmparameters *params);
--/* 0x0004 */ int aim_im_reqparams(OscarData *od);
--/* 0x0006 */ int aim_im_sendch1_ext(OscarData *od, struct aim_sendimext_args *args);
--/* 0x0006 */ int aim_im_sendch1(OscarData *, const char *destbn, guint16 flags, const char *msg);
--/* 0x0006 */ int aim_im_sendch2_chatinvite(OscarData *od, const char *bn, const char *msg, guint16 exchange, const char *roomname, guint16 instance);
--/* 0x0006 */ int aim_im_sendch2_icon(OscarData *od, const char *bn, const guint8 *icon, int iconlen, time_t stamp, guint16 iconsum);
--
--/* 0x0006 */ void aim_im_sendch2_cancel(PeerConnection *peer_conn);
--/* 0x0006 */ void aim_im_sendch2_connected(PeerConnection *peer_conn);
--/* 0x0006 */ void aim_im_sendch2_odc_requestdirect(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 port, guint16 requestnumber);
--/* 0x0006 */ void aim_im_sendch2_odc_requestproxy(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 pin, guint16 requestnumber);
--/* 0x0006 */ void aim_im_sendch2_sendfile_requestdirect(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 port, guint16 requestnumber, const gchar *filename, guint32 size, guint16 numfiles);
--/* 0x0006 */ void aim_im_sendch2_sendfile_requestproxy(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 pin, guint16 requestnumber, const gchar *filename, guint32 size, guint16 numfiles);
--
--/* 0x000b */ int aim_im_denytransfer(OscarData *od, const char *bn, const guchar *cookie, guint16 code);
--/* 0x0010 */ int aim_im_reqofflinemsgs(OscarData *od);
--/* 0x0014 */ int aim_im_sendmtn(OscarData *od, guint16 type1, const char *bn, guint16 type2);
--/* 0x000b */ int icq_relay_xstatus (OscarData *od, const char *sn, const guchar* cookie);
--void aim_icbm_makecookie(guchar* cookie);
--void aim_im_send_icq_confirmation(OscarData *od, const char *bn, const guchar *cookie);
--
--/* 0x0002 - family_locate.c */
--/*
-- * AIM User Info, Standard Form.
-- */
--#define AIM_FLAG_ADMINISTRATOR 0x0002
--#define AIM_FLAG_AOL 0x0004
--#define AIM_FLAG_AWAY 0x0020
--#define AIM_FLAG_WIRELESS 0x0080
--#define AIM_FLAG_ICQ 0x0040
--#define AIM_FLAG_ACTIVEBUDDY 0x0400
--
--#define AIM_USERINFO_PRESENT_FLAGS 0x00000001
--#define AIM_USERINFO_PRESENT_MEMBERSINCE 0x00000002
--#define AIM_USERINFO_PRESENT_ONLINESINCE 0x00000004
--#define AIM_USERINFO_PRESENT_IDLE 0x00000008
--#define AIM_USERINFO_PRESENT_ICQEXTSTATUS 0x00000010
--#define AIM_USERINFO_PRESENT_ICQIPADDR 0x00000020
--#define AIM_USERINFO_PRESENT_ICQDATA 0x00000040
--#define AIM_USERINFO_PRESENT_CAPABILITIES 0x00000080
--#define AIM_USERINFO_PRESENT_SESSIONLEN 0x00000100
--#define AIM_USERINFO_PRESENT_CREATETIME 0x00000200
--
--struct userinfo_node
--{
-- char *bn;
-- struct userinfo_node *next;
--};
--
--typedef struct aim_userinfo_s
--{
-- char *bn;
-- guint16 warnlevel; /* evil percent * 10 (999 = 99.9%) */
-- guint16 idletime; /* in seconds */
-- guint16 flags;
-- guint32 createtime; /* time_t */
-- guint32 membersince; /* time_t */
-- guint32 onlinesince; /* time_t */
-- guint32 sessionlen; /* in seconds */
-- guint64 capabilities;
-- struct {
-- guint32 status;
-- guint32 ipaddr;
-- guint8 crap[0x25]; /* until we figure it out... */
-- } icqinfo;
-- guint32 present;
--
-- guint8 iconcsumtype;
-- guint16 iconcsumlen;
-- guint8 *iconcsum;
--
-- char *info;
-- char *info_encoding;
-- guint16 info_len;
--
-- char *status;
-- char *status_encoding;
-- guint16 status_len;
--
-- char *itmsurl;
-- char *itmsurl_encoding;
-- guint16 itmsurl_len;
--
-- char *away;
-- char *away_encoding;
-- guint16 away_len;
--
-- struct aim_userinfo_s *next;
--} aim_userinfo_t;
--
--#define AIM_SENDMEMBLOCK_FLAG_ISREQUEST 0
--#define AIM_SENDMEMBLOCK_FLAG_ISHASH 1
--
--int aim_sendmemblock(OscarData *od, FlapConnection *conn, guint32 offset, guint32 len, const guint8 *buf, guint8 flag);
--
--struct aim_invite_priv
--{
-- char *bn;
-- char *roomname;
-- guint16 exchange;
-- guint16 instance;
--};
--
--#define AIM_COOKIETYPE_CHAT 0x01
--#define AIM_COOKIETYPE_INVITE 0x02
--
--aim_userinfo_t *aim_locate_finduserinfo(OscarData *od, const char *bn);
--void aim_locate_dorequest(OscarData *od);
--
--/* 0x0002 */ int aim_locate_reqrights(OscarData *od);
--/* 0x0004 */ int aim_locate_setcaps(OscarData *od, guint64 caps);
--/* 0x0004 */ int aim_locate_setprofile(OscarData *od, const char *profile_encoding, const gchar *profile, const int profile_len, const char *awaymsg_encoding, const gchar *awaymsg, const int awaymsg_len);
--/* 0x0015 */ int aim_locate_getinfoshort(OscarData *od, const char *bn, guint32 flags);
--
--guint64 aim_locate_getcaps(OscarData *od, ByteStream *bs, int len);
--guint64 aim_locate_getcaps_short(OscarData *od, ByteStream *bs, int len);
--void aim_info_free(aim_userinfo_t *);
--int aim_info_extract(OscarData *od, ByteStream *bs, aim_userinfo_t *);
--int aim_putuserinfo(ByteStream *bs, aim_userinfo_t *info);
--PurpleMood* icq_get_purple_moods(PurpleAccount *account);
--const char* icq_get_custom_icon_description(const char *mood);
--guint8* icq_get_custom_icon_data(const char *mood);
--int icq_im_xstatus_request(OscarData *od, const char *sn);
--
--/* 0x0003 - family_buddy.c */
--/* 0x0002 */ void aim_buddylist_reqrights(OscarData *, FlapConnection *);
--
--
--/* 0x000a - family_userlookup.c */
--int aim_search_address(OscarData *, const char *);
--
--struct aim_chat_exchangeinfo
--{
-- guint16 number;
-- guint16 flags;
-- char *name;
-- char *charset1;
-- char *lang1;
-- char *charset2;
-- char *lang2;
--};
--
--#define AIM_CHATFLAGS_NOREFLECT 0x0001
--#define AIM_CHATFLAGS_AWAY 0x0002
--int aim_chat_send_im(OscarData *od, FlapConnection *conn, guint16 flags, const gchar *msg, int msglen, const char *encoding, const char *language);
--int aim_chat_join(OscarData *od, guint16 exchange, const char *roomname, guint16 instance);
--
--void aim_chatnav_reqrights(OscarData *od, FlapConnection *conn);
--
--int aim_chatnav_createroom(OscarData *od, FlapConnection *conn, const char *name, guint16 exchange);
--
--
--/* 0x0010 - family_bart.c */
--int aim_bart_upload(OscarData *od, const guint8 *icon, guint16 iconlen);
--int aim_bart_request(OscarData *od, const char *bn, guint8 iconcsumtype, const guint8 *iconstr, guint16 iconstrlen);
--
--
--
--/* 0x0013 - family_feedbag.c */
--#define AIM_SSI_TYPE_BUDDY 0x0000
--#define AIM_SSI_TYPE_GROUP 0x0001
--#define AIM_SSI_TYPE_PERMIT 0x0002
--#define AIM_SSI_TYPE_DENY 0x0003
--#define AIM_SSI_TYPE_PDINFO 0x0004
--#define AIM_SSI_TYPE_PRESENCEPREFS 0x0005
--#define AIM_SSI_TYPE_ICQDENY 0x000e
--#define AIM_SSI_TYPE_ICONINFO 0x0014
--
--/* These flags are set in the 0x00c9 TLV of SSI type 0x0005 */
--#define AIM_SSI_PRESENCE_FLAG_SHOWIDLE 0x00000400
--#define AIM_SSI_PRESENCE_FLAG_NORECENTBUDDIES 0x00020000
--
--struct aim_ssi_item
--{
-- char *name;
-- guint16 gid;
-- guint16 bid;
-- guint16 type;
-- GSList *data;
-- struct aim_ssi_item *next;
--};
--
--struct aim_ssi_tmp
--{
-- guint16 action;
-- guint16 ack;
-- char *name;
-- struct aim_ssi_item *item;
-- struct aim_ssi_tmp *next;
--};
--
--/* These build the actual SNACs and queue them to be sent */
--/* 0x0002 */ int aim_ssi_reqrights(OscarData *od);
--/* 0x0004 */ int aim_ssi_reqdata(OscarData *od);
--/* 0x0007 */ int aim_ssi_enable(OscarData *od);
--/* 0x0011 */ int aim_ssi_modbegin(OscarData *od);
--/* 0x0012 */ int aim_ssi_modend(OscarData *od);
--/* 0x0018 */ int aim_ssi_sendauthrequest(OscarData *od, const char *bn, const char *msg);
--/* 0x001a */ int aim_ssi_sendauthreply(OscarData *od, const char *bn, guint8 reply, const char *msg);
--
--/* Client functions for retrieving SSI data */
--struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid);
--struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *bn, guint16 type);
--struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *bn);
--char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *bn);
--int aim_ssi_getpermdeny(struct aim_ssi_item *list);
--guint32 aim_ssi_getpresence(struct aim_ssi_item *list);
--char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *bn);
--char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *bn);
--gboolean aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *bn);
--
--/* Client functions for changing SSI data */
--int aim_ssi_addbuddy(OscarData *od, const char *name, const char *group, GSList *tlvlist, const char *alias, const char *comment, const char *smsnum, gboolean needauth);
--int aim_ssi_delbuddy(OscarData *od, const char *name, const char *group);
--int aim_ssi_delgroup(OscarData *od, const char *group);
--int aim_ssi_movebuddy(OscarData *od, const char *oldgn, const char *newgn, const char *bn);
--int aim_ssi_aliasbuddy(OscarData *od, const char *gn, const char *bn, const char *alias);
--int aim_ssi_editcomment(OscarData *od, const char *gn, const char *bn, const char *alias);
--int aim_ssi_rename_group(OscarData *od, const char *oldgn, const char *newgn);
--int aim_ssi_cleanlist(OscarData *od);
--int aim_ssi_deletelist(OscarData *od);
--int aim_ssi_setpermdeny(OscarData *od, guint8 permdeny);
--int aim_ssi_setpresence(OscarData *od, guint32 presence);
--int aim_ssi_seticon(OscarData *od, const guint8 *iconsum, guint8 iconsumlen);
--int aim_ssi_delicon(OscarData *od);
--int aim_ssi_add_to_private_list(OscarData *od, const char* name, guint16 list_type);
--int aim_ssi_del_from_private_list(OscarData* od, const char* name, guint16 list_type);
--
--guint16 aim_ssi_getdenyentrytype(OscarData* od);
--
--struct aim_icq_info
--{
-- guint16 reqid;
--
-- /* simple */
-- guint32 uin;
--
-- /* general and "home" information (0x00c8) */
-- char *nick;
-- char *first;
-- char *last;
-- char *email;
-- char *homecity;
-- char *homestate;
-- char *homephone;
-- char *homefax;
-- char *homeaddr;
-- char *mobile;
-- char *homezip;
-- guint16 homecountry;
--/* guint8 timezone;
-- guint8 hideemail; */
--
-- /* personal (0x00dc) */
-- guint8 age;
-- guint8 unknown;
-- guint8 gender;
-- char *personalwebpage;
-- guint16 birthyear;
-- guint8 birthmonth;
-- guint8 birthday;
-- guint8 language1;
-- guint8 language2;
-- guint8 language3;
--
-- /* work (0x00d2) */
-- char *workcity;
-- char *workstate;
-- char *workphone;
-- char *workfax;
-- char *workaddr;
-- char *workzip;
-- guint16 workcountry;
-- char *workcompany;
-- char *workdivision;
-- char *workposition;
-- char *workwebpage;
--
-- /* additional personal information (0x00e6) */
-- char *info;
--
-- /* email (0x00eb) */
-- guint16 numaddresses;
-- char **email2;
--
-- /* status note info */
-- guint8 icbm_cookie[8];
-- char *status_note_title;
--
-- gboolean for_auth_request;
-- char *auth_request_reason;
--};
--
--int aim_icq_setsecurity(OscarData *od, gboolean auth_required, gboolean webaware);
--int aim_icq_changepasswd(OscarData *od, const char *passwd);
--int aim_icq_getalias(OscarData *od, const char *uin, gboolean for_auth_request, char *auth_request_reason);
--int aim_icq_getallinfo(OscarData *od, const char *uin);
--int aim_icq_sendsms(OscarData *od, const char *name, const char *msg, const char *alias);
--
--
--/* 0x0017 - family_auth.c */
--void aim_sendcookie(OscarData *, FlapConnection *, const guint16 length, const guint8 *);
--void aim_admin_changepasswd(OscarData *, FlapConnection *, const char *newpw, const char *curpw);
--void aim_admin_reqconfirm(OscarData *od, FlapConnection *conn);
--void aim_admin_getinfo(OscarData *od, FlapConnection *conn, guint16 info);
--void aim_admin_setemail(OscarData *od, FlapConnection *conn, const char *newemail);
--void aim_admin_setnick(OscarData *od, FlapConnection *conn, const char *newnick);
--
--
--
--/* 0x0018 - family_alert.c */
--struct aim_emailinfo
--{
-- guint8 *cookie16;
-- guint8 *cookie8;
-- char *url;
-- guint16 nummsgs;
-- guint8 unread;
-- char *domain;
-- guint16 flag;
-- struct aim_emailinfo *next;
--};
--
--int aim_email_sendcookies(OscarData *od);
--int aim_email_activate(OscarData *od);
--
--
--
--/* tlv.c - TLV handling */
--
--/* TLV structure */
--typedef struct aim_tlv_s
--{
-- guint16 type;
-- guint16 length;
-- guint8 *value;
--} aim_tlv_t;
--
--/* TLV handling functions */
--char *aim_tlv_getvalue_as_string(aim_tlv_t *tlv);
--
--aim_tlv_t *aim_tlv_gettlv(GSList *list, const guint16 type, const int nth);
--int aim_tlv_getlength(GSList *list, const guint16 type, const int nth);
--char *aim_tlv_getstr(GSList *list, const guint16 type, const int nth);
--guint8 aim_tlv_get8(GSList *list, const guint16 type, const int nth);
--guint16 aim_tlv_get16(GSList *list, const guint16 type, const int nth);
--guint32 aim_tlv_get32(GSList *list, const guint16 type, const int nth);
--
--/* TLV list handling functions */
--GSList *aim_tlvlist_read(ByteStream *bs);
--GSList *aim_tlvlist_readnum(ByteStream *bs, guint16 num);
--GSList *aim_tlvlist_readlen(ByteStream *bs, guint16 len);
--GSList *aim_tlvlist_copy(GSList *orig);
--
--int aim_tlvlist_count(GSList *list);
--int aim_tlvlist_size(GSList *list);
--int aim_tlvlist_cmp(GSList *one, GSList *two);
--int aim_tlvlist_write(ByteStream *bs, GSList **list);
--void aim_tlvlist_free(GSList *list);
--
--int aim_tlvlist_add_raw(GSList **list, const guint16 type, const guint16 length, const guint8 *value);
--int aim_tlvlist_add_noval(GSList **list, const guint16 type);
--int aim_tlvlist_add_8(GSList **list, const guint16 type, const guint8 value);
--int aim_tlvlist_add_16(GSList **list, const guint16 type, const guint16 value);
--int aim_tlvlist_add_32(GSList **list, const guint16 type, const guint32 value);
--int aim_tlvlist_add_str(GSList **list, const guint16 type, const char *value);
--int aim_tlvlist_add_caps(GSList **list, const guint16 type, const guint64 caps, const char *mood);
--int aim_tlvlist_add_userinfo(GSList **list, guint16 type, aim_userinfo_t *userinfo);
--int aim_tlvlist_add_chatroom(GSList **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance);
--int aim_tlvlist_add_frozentlvlist(GSList **list, guint16 type, GSList **tl);
--
--int aim_tlvlist_replace_raw(GSList **list, const guint16 type, const guint16 lenth, const guint8 *value);
--int aim_tlvlist_replace_str(GSList **list, const guint16 type, const char *str);
--int aim_tlvlist_replace_noval(GSList **list, const guint16 type);
--int aim_tlvlist_replace_8(GSList **list, const guint16 type, const guint8 value);
--int aim_tlvlist_replace_16(GSList **list, const guint16 type, const guint16 value);
--int aim_tlvlist_replace_32(GSList **list, const guint16 type, const guint32 value);
--
--void aim_tlvlist_remove(GSList **list, const guint16 type);
--
--
--
--/* util.c */
--/* These are really ugly. You'd think this was LISP. I wish it was. */
--#define aimutil_put8(buf, data) ((*(buf) = (guint8)(data)&0xff),1)
--#define aimutil_get8(buf) ((*(buf))&0xff)
--#define aimutil_put16(buf, data) ( \
-- (*(buf) = (guint8)((data)>>8)&0xff), \
-- (*((buf)+1) = (guint8)(data)&0xff), \
-- 2)
--#define aimutil_get16(buf) ((((*(buf))<<8)&0xff00) + ((*((buf)+1)) & 0xff))
--#define aimutil_put32(buf, data) ( \
-- (*((buf)) = (guint8)((data)>>24)&0xff), \
-- (*((buf)+1) = (guint8)((data)>>16)&0xff), \
-- (*((buf)+2) = (guint8)((data)>>8)&0xff), \
-- (*((buf)+3) = (guint8)(data)&0xff), \
-- 4)
--#define aimutil_get32(buf) ((((*(buf))<<24)&0xff000000) + \
-- (((*((buf)+1))<<16)&0x00ff0000) + \
-- (((*((buf)+2))<< 8)&0x0000ff00) + \
-- (((*((buf)+3) )&0x000000ff)))
--
--/* Little-endian versions (damn ICQ) */
--#define aimutil_putle8(buf, data) ( \
-- (*(buf) = (guint8)(data) & 0xff), \
-- 1)
--#define aimutil_getle8(buf) ( \
-- (*(buf)) & 0xff \
-- )
--#define aimutil_putle16(buf, data) ( \
-- (*((buf)+0) = (guint8)((data) >> 0) & 0xff), \
-- (*((buf)+1) = (guint8)((data) >> 8) & 0xff), \
-- 2)
--#define aimutil_getle16(buf) ( \
-- (((*((buf)+0)) << 0) & 0x00ff) + \
-- (((*((buf)+1)) << 8) & 0xff00) \
-- )
--#define aimutil_putle32(buf, data) ( \
-- (*((buf)+0) = (guint8)((data) >> 0) & 0xff), \
-- (*((buf)+1) = (guint8)((data) >> 8) & 0xff), \
-- (*((buf)+2) = (guint8)((data) >> 16) & 0xff), \
-- (*((buf)+3) = (guint8)((data) >> 24) & 0xff), \
-- 4)
--#define aimutil_getle32(buf) ( \
-- (((*((buf)+0)) << 0) & 0x000000ff) + \
-- (((*((buf)+1)) << 8) & 0x0000ff00) + \
-- (((*((buf)+2)) << 16) & 0x00ff0000) + \
-- (((*((buf)+3)) << 24) & 0xff000000))
--
--const char *oscar_get_msgerr_reason(size_t reason);
--int oscar_get_ui_info_int(const char *str, int default_value);
--const char *oscar_get_ui_info_string(const char *str, const char *default_value);
--gchar *oscar_get_clientstring(void);
--
--guint16 aimutil_iconsum(const guint8 *buf, int buflen);
--
--gboolean oscar_util_valid_name(const char *bn);
--gboolean oscar_util_valid_name_icq(const char *bn);
--gboolean oscar_util_valid_name_sms(const char *bn);
--int oscar_util_name_compare(const char *bn1, const char *bn2);
--gchar *oscar_util_format_string(const char *str, const char *name);
--gchar *oscar_format_buddies(GSList *buddies, const gchar *no_buddies_message);
--
--typedef struct {
-- guint16 family;
-- guint16 subtype;
-- guint16 flags;
-- guint32 id;
--} aim_modsnac_t;
--
--#define AIM_MODULENAME_MAXLEN 16
--#define AIM_MODFLAG_MULTIFAMILY 0x0001
--typedef struct aim_module_s
--{
-- guint16 family;
-- guint16 version;
-- guint16 toolid;
-- guint16 toolversion;
-- guint16 flags;
-- char name[AIM_MODULENAME_MAXLEN+1];
-- int (*snachandler)(OscarData *od, FlapConnection *conn, struct aim_module_s *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs);
-- void (*shutdown)(OscarData *od, struct aim_module_s *mod);
-- void *priv;
-- struct aim_module_s *next;
--} aim_module_t;
--
--int aim__registermodule(OscarData *od, int (*modfirst)(OscarData *, aim_module_t *));
--void aim__shutdownmodules(OscarData *od);
--aim_module_t *aim__findmodulebygroup(OscarData *od, guint16 group);
--aim_module_t *aim__findmodule(OscarData *od, const char *name);
--
--int admin_modfirst(OscarData *od, aim_module_t *mod);
--int buddylist_modfirst(OscarData *od, aim_module_t *mod);
--int bos_modfirst(OscarData *od, aim_module_t *mod);
--int search_modfirst(OscarData *od, aim_module_t *mod);
--int stats_modfirst(OscarData *od, aim_module_t *mod);
--int auth_modfirst(OscarData *od, aim_module_t *mod);
--int msg_modfirst(OscarData *od, aim_module_t *mod);
--int misc_modfirst(OscarData *od, aim_module_t *mod);
--int chatnav_modfirst(OscarData *od, aim_module_t *mod);
--int chat_modfirst(OscarData *od, aim_module_t *mod);
--int locate_modfirst(OscarData *od, aim_module_t *mod);
--int service_modfirst(OscarData *od, aim_module_t *mod);
--int popups_modfirst(OscarData *od, aim_module_t *mod);
--int bart_modfirst(OscarData *od, aim_module_t *mod);
--int ssi_modfirst(OscarData *od, aim_module_t *mod);
--int icq_modfirst(OscarData *od, aim_module_t *mod);
--int email_modfirst(OscarData *od, aim_module_t *mod);
--
--void aim_genericreq_n(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype);
--void aim_genericreq_n_snacid(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype);
--void aim_genericreq_l(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype, guint32 *);
--
--/* bstream.c */
--int byte_stream_new(ByteStream *bs, size_t len);
--int byte_stream_init(ByteStream *bs, guint8 *data, size_t len);
--void byte_stream_destroy(ByteStream *bs);
--int byte_stream_bytes_left(ByteStream *bs);
--int byte_stream_curpos(ByteStream *bs);
--int byte_stream_setpos(ByteStream *bs, size_t off);
--void byte_stream_rewind(ByteStream *bs);
--int byte_stream_advance(ByteStream *bs, int n);
--guint8 byte_stream_get8(ByteStream *bs);
--guint16 byte_stream_get16(ByteStream *bs);
--guint32 byte_stream_get32(ByteStream *bs);
--guint8 byte_stream_getle8(ByteStream *bs);
--guint16 byte_stream_getle16(ByteStream *bs);
--guint32 byte_stream_getle32(ByteStream *bs);
--int byte_stream_getrawbuf(ByteStream *bs, guint8 *buf, size_t len);
--guint8 *byte_stream_getraw(ByteStream *bs, size_t len);
--char *byte_stream_getstr(ByteStream *bs, size_t len);
--int byte_stream_put8(ByteStream *bs, guint8 v);
--int byte_stream_put16(ByteStream *bs, guint16 v);
--int byte_stream_put32(ByteStream *bs, guint32 v);
--int byte_stream_putle8(ByteStream *bs, guint8 v);
--int byte_stream_putle16(ByteStream *bs, guint16 v);
--int byte_stream_putle32(ByteStream *bs, guint32 v);
--int byte_stream_putraw(ByteStream *bs, const guint8 *v, size_t len);
--int byte_stream_putstr(ByteStream *bs, const char *str);
--int byte_stream_putbs(ByteStream *bs, ByteStream *srcbs, size_t len);
--int byte_stream_putuid(ByteStream *bs, OscarData *od);
--int byte_stream_putcaps(ByteStream *bs, guint64 caps);
--
--/**
-- * Inserts a BART asset block into the given byte stream. The flags
-- * and length are set appropriately based on the value of data.
-- */
--void byte_stream_put_bart_asset(ByteStream *bs, guint16 type, ByteStream *data);
--
--/**
-- * A helper function that calls byte_stream_put_bart_asset with the
-- * appropriate data ByteStream given the datastr.
-- */
--void byte_stream_put_bart_asset_str(ByteStream *bs, guint16 type, const char *datastr);
--
--/*
-- * Generic SNAC structure. Rarely if ever used.
-- */
--typedef struct aim_snac_s {
-- aim_snacid_t id;
-- guint16 family;
-- guint16 type;
-- guint16 flags;
-- void *data;
-- time_t issuetime;
-- struct aim_snac_s *next;
--} aim_snac_t;
--
--/* snac.c */
--void aim_initsnachash(OscarData *od);
--aim_snacid_t aim_newsnac(OscarData *, aim_snac_t *newsnac);
--aim_snacid_t aim_cachesnac(OscarData *od, const guint16 family, const guint16 type, const guint16 flags, const void *data, const int datalen);
--aim_snac_t *aim_remsnac(OscarData *, aim_snacid_t id);
--void aim_cleansnacs(OscarData *, int maxage);
--int aim_putsnac(ByteStream *, guint16 family, guint16 type, aim_snacid_t id);
--
--struct chatsnacinfo {
-- guint16 exchange;
-- char name[128];
-- guint16 instance;
--};
--
--struct rateclass {
-- guint16 classid;
-- guint32 windowsize;
-- guint32 clear;
-- guint32 alert;
-- guint32 limit;
-- guint32 disconnect;
-- guint32 current;
-- guint32 max;
-- guint8 dropping_snacs;
--
-- struct timeval last; /**< The time when we last sent a SNAC of this rate class. */
--};
--
--int aim_cachecookie(OscarData *od, IcbmCookie *cookie);
--IcbmCookie *aim_uncachecookie(OscarData *od, guint8 *cookie, int type);
--IcbmCookie *aim_mkcookie(guint8 *, int, void *);
--IcbmCookie *aim_checkcookie(OscarData *, const unsigned char *, const int);
--int aim_freecookie(OscarData *od, IcbmCookie *cookie);
--int aim_cookie_free(OscarData *od, IcbmCookie *cookie);
--
--int aim_chat_readroominfo(ByteStream *bs, struct aim_chat_roominfo *outinfo);
--
--void flap_connection_destroy_chat(OscarData *od, FlapConnection *conn);
--
--/* userinfo.c - displaying user information */
--
--void oscar_user_info_append_status(PurpleConnection *gc, PurpleNotifyUserInfo *user_info, PurpleBuddy *b, aim_userinfo_t *userinfo, gboolean use_html_status);
--void oscar_user_info_append_extra_info(PurpleConnection *gc, PurpleNotifyUserInfo *user_info, PurpleBuddy *b, aim_userinfo_t *userinfo);
--void oscar_user_info_display_error(OscarData *od, guint16 error_reason, char *buddy);
--void oscar_user_info_display_icq(OscarData *od, struct aim_icq_info *info);
--void oscar_user_info_display_aim(OscarData *od, aim_userinfo_t *userinfo);
--
--/* authorization.c - OSCAR authorization requests */
--void oscar_auth_sendrequest(PurpleConnection *gc, const char *name, const char *msg);
--void oscar_auth_sendrequest_menu(PurpleBlistNode *node, gpointer ignored);
--void oscar_auth_recvrequest(PurpleConnection *gc, gchar *name, gchar *nick, gchar *reason);
--
--void oscar_set_aim_permdeny(PurpleConnection *gc);
--
--struct buddyinfo
--{
-- gboolean typingnot;
-- guint32 ipaddr;
--
-- unsigned long ico_me_len;
-- unsigned long ico_me_csum;
-- time_t ico_me_time;
-- gboolean ico_informed;
--
-- unsigned long ico_len;
-- unsigned long ico_csum;
-- time_t ico_time;
-- gboolean ico_need;
-- gboolean ico_sent;
--};
--
--struct name_data
--{
-- PurpleConnection *gc;
-- gchar *name;
-- gchar *nick;
--};
--
--void oscar_free_name_data(struct name_data *data);
--
--#ifdef __cplusplus
--}
--#endif
--
--#endif /* _OSCAR_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/peer.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/peer.c
---- pidgin-2.10.7/libpurple/protocols/oscar/peer.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/peer.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1136 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Functions dealing with peer connections. This includes the code
-- * used to establish a peer connection for both Oscar File transfer
-- * (OFT) and Oscar Direct Connect (ODC). (ODC is also referred to
-- * as DirectIM and IM Image.)
-- */
--
--#ifdef HAVE_CONFIG_H
--#include <config.h>
--#endif
--
--/* From the oscar PRPL */
--#include "oscar.h"
--#include "peer.h"
--
--/* From Purple */
--#include "conversation.h"
--#include "ft.h"
--#include "network.h"
--#include "notify.h"
--#include "request.h"
--#include "util.h"
--
--#ifndef _WIN32
--#include <stdio.h>
--#include <netdb.h>
--#include <sys/socket.h>
--#include <netinet/in.h>
--#include <arpa/inet.h> /* for inet_ntoa */
--#include <limits.h> /* for UINT_MAX */
--#endif
--
--#ifdef _WIN32
--#include "win32dep.h"
--#endif
--
--/*
-- * I really want to switch all our networking code to using IPv6 only,
-- * but that really isn't a good idea at all. Evan S. of Adium says
-- * OS X sets all connections as "AF_INET6/PF_INET6," even if there is
-- * nothing inherently IPv6 about them. And I feel like Linux kernel
-- * 2.6.5 is doing the same thing. So we REALLY should accept
-- * connections if they're showing up as IPv6. Old OSes (Solaris?)
-- * that might not have full IPv6 support yet will fail if we try
-- * to use PF_INET6 but it isn't defined. --Mark Doliner
-- */
--#ifndef PF_INET6
--#define PF_INET6 PF_INET
--#endif
--
--PeerConnection *
--peer_connection_find_by_type(OscarData *od, const char *bn, guint64 type)
--{
-- GSList *cur;
-- PeerConnection *conn;
--
-- for (cur = od->peer_connections; cur != NULL; cur = cur->next)
-- {
-- conn = cur->data;
-- if ((conn->type == type) && !oscar_util_name_compare(conn->bn, bn))
-- return conn;
-- }
--
-- return NULL;
--}
--
--/**
-- * @param cookie This must be exactly 8 characters.
-- */
--PeerConnection *
--peer_connection_find_by_cookie(OscarData *od, const char *bn, const guchar *cookie)
--{
-- GSList *cur;
-- PeerConnection *conn;
--
-- for (cur = od->peer_connections; cur != NULL; cur = cur->next)
-- {
-- conn = cur->data;
-- if (!memcmp(conn->cookie, cookie, 8) && !oscar_util_name_compare(conn->bn, bn))
-- return conn;
-- }
--
-- return NULL;
--}
--
--PeerConnection *
--peer_connection_new(OscarData *od, guint64 type, const char *bn)
--{
-- PeerConnection *conn;
-- PurpleAccount *account;
--
-- account = purple_connection_get_account(od->gc);
--
-- conn = g_new0(PeerConnection, 1);
-- conn->od = od;
-- conn->type = type;
-- conn->bn = g_strdup(bn);
-- conn->buffer_outgoing = purple_circ_buffer_new(0);
-- conn->listenerfd = -1;
-- conn->fd = -1;
-- conn->lastactivity = time(NULL);
-- conn->use_proxy |= purple_account_get_bool(account, "always_use_rv_proxy", FALSE);
--
-- if (type == OSCAR_CAPABILITY_DIRECTIM)
-- memcpy(conn->magic, "ODC2", 4);
-- else if (type == OSCAR_CAPABILITY_SENDFILE)
-- memcpy(conn->magic, "OFT2", 4);
--
-- od->peer_connections = g_slist_prepend(od->peer_connections, conn);
--
-- return conn;
--}
--
--static void
--peer_connection_close(PeerConnection *conn)
--{
-- if (conn->type == OSCAR_CAPABILITY_DIRECTIM)
-- peer_odc_close(conn);
-- else if (conn->type == OSCAR_CAPABILITY_SENDFILE)
-- peer_oft_close(conn);
--
-- if (conn->verified_connect_data != NULL)
-- {
-- purple_proxy_connect_cancel(conn->verified_connect_data);
-- conn->verified_connect_data = NULL;
-- }
--
-- if (conn->client_connect_data != NULL)
-- {
-- purple_proxy_connect_cancel(conn->client_connect_data);
-- conn->client_connect_data = NULL;
-- }
--
-- if (conn->listen_data != NULL)
-- {
-- purple_network_listen_cancel(conn->listen_data);
-- conn->listen_data = NULL;
-- }
--
-- if (conn->connect_timeout_timer != 0)
-- {
-- purple_timeout_remove(conn->connect_timeout_timer);
-- conn->connect_timeout_timer = 0;
-- }
--
-- if (conn->watcher_incoming != 0)
-- {
-- purple_input_remove(conn->watcher_incoming);
-- conn->watcher_incoming = 0;
-- }
-- if (conn->watcher_outgoing != 0)
-- {
-- purple_input_remove(conn->watcher_outgoing);
-- conn->watcher_outgoing = 0;
-- }
-- if (conn->listenerfd >= 0)
-- {
-- close(conn->listenerfd);
-- conn->listenerfd = -1;
-- }
-- if (conn->fd >= 0)
-- {
-- close(conn->fd);
-- conn->fd = -1;
-- }
--
-- g_free(conn->buffer_incoming.data);
-- conn->buffer_incoming.data = NULL;
-- conn->buffer_incoming.len = 0;
-- conn->buffer_incoming.offset = 0;
--
-- purple_circ_buffer_destroy(conn->buffer_outgoing);
-- conn->buffer_outgoing = purple_circ_buffer_new(0);
--
-- conn->flags &= ~PEER_CONNECTION_FLAG_IS_INCOMING;
--}
--
--static gboolean
--peer_connection_destroy_cb(gpointer data)
--{
-- PeerConnection *conn;
--
-- conn = data;
--
-- purple_request_close_with_handle(conn);
--
-- peer_connection_close(conn);
--
-- if (conn->checksum_data != NULL)
-- peer_oft_checksum_destroy(conn->checksum_data);
--
-- if (conn->xfer != NULL)
-- {
-- PurpleXferStatusType status;
-- conn->xfer->data = NULL;
-- status = purple_xfer_get_status(conn->xfer);
-- if ((status != PURPLE_XFER_STATUS_DONE) &&
-- (status != PURPLE_XFER_STATUS_CANCEL_LOCAL) &&
-- (status != PURPLE_XFER_STATUS_CANCEL_REMOTE))
-- {
-- if ((conn->disconnect_reason == OSCAR_DISCONNECT_REMOTE_CLOSED) ||
-- (conn->disconnect_reason == OSCAR_DISCONNECT_REMOTE_REFUSED))
-- purple_xfer_cancel_remote(conn->xfer);
-- else
-- purple_xfer_cancel_local(conn->xfer);
-- }
-- purple_xfer_unref(conn->xfer);
-- conn->xfer = NULL;
-- }
--
-- g_free(conn->bn);
-- g_free(conn->error_message);
-- g_free(conn->proxyip);
-- g_free(conn->clientip);
-- g_free(conn->verifiedip);
-- g_free(conn->xferdata.name);
-- purple_circ_buffer_destroy(conn->buffer_outgoing);
--
-- conn->od->peer_connections = g_slist_remove(conn->od->peer_connections, conn);
--
-- g_free(conn);
--
-- return FALSE;
--}
--
--void
--peer_connection_destroy(PeerConnection *conn, OscarDisconnectReason reason, const gchar *error_message)
--{
-- if (conn->destroy_timeout != 0)
-- purple_timeout_remove(conn->destroy_timeout);
-- conn->disconnect_reason = reason;
-- g_free(conn->error_message);
-- conn->error_message = g_strdup(error_message);
-- peer_connection_destroy_cb(conn);
--}
--
--void
--peer_connection_schedule_destroy(PeerConnection *conn, OscarDisconnectReason reason, const gchar *error_message)
--{
-- if (conn->destroy_timeout != 0)
-- /* Already taken care of */
-- return;
--
-- purple_debug_info("oscar", "Scheduling destruction of peer connection\n");
-- conn->disconnect_reason = reason;
-- g_free(conn->error_message);
-- conn->error_message = g_strdup(error_message);
-- conn->destroy_timeout = purple_timeout_add(0, peer_connection_destroy_cb, conn);
--}
--
--/*******************************************************************/
--/* Begin code for receiving data on a peer connection */
--/*******************************************************************/
--
--/**
-- * This should be used to read ODC and OFT framing info. It should
-- * NOT be used to read the payload sent across the connection (IMs,
-- * file data, etc), and it should NOT be used to read proxy negotiation
-- * headers.
-- *
-- * Unlike flap_connection_recv_cb(), this only reads one frame at a
-- * time. This is done so that the watcher can be changed during the
-- * handling of the frame. If the watcher is changed then this
-- * function will not read in any more data. This happens when
-- * reading the payload of a direct IM frame, or when we're
-- * receiving a file from the remote user. Once the data has been
-- * read, the watcher will be switched back to this function to
-- * continue reading the next frame.
-- */
--void
--peer_connection_recv_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- PeerConnection *conn;
-- gssize read;
--
-- conn = data;
--
-- /* Start reading a new ODC/OFT frame */
-- if (conn->buffer_incoming.data == NULL)
-- {
-- /* Read the first 6 bytes (magic string and frame length) */
-- read = recv(conn->fd, conn->header + conn->header_received,
-- 6 - conn->header_received, 0);
--
-- /* Check if the remote user closed the connection */
-- if (read == 0)
-- {
-- peer_connection_destroy(conn, OSCAR_DISCONNECT_REMOTE_CLOSED, NULL);
-- return;
-- }
--
-- /* If there was an error then close the connection */
-- if (read < 0)
-- {
-- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-- /* No worries */
-- return;
--
-- peer_connection_destroy(conn,
-- OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno));
-- return;
-- }
--
-- conn->lastactivity = time(NULL);
--
-- /* If we don't even have the first 6 bytes then do nothing */
-- conn->header_received += read;
-- if (conn->header_received < 6)
-- return;
--
-- /* All ODC/OFT frames must start with a magic string */
-- if (memcmp(conn->magic, conn->header, 4))
-- {
-- purple_debug_warning("oscar", "Expecting magic string to "
-- "be %c%c%c%c but received magic string %c%c%c%c. "
-- "Closing connection.\n",
-- conn->magic[0], conn->magic[1], conn->magic[2],
-- conn->magic[3], conn->header[0], conn->header[1],
-- conn->header[2], conn->header[3]);
-- peer_connection_destroy(conn, OSCAR_DISCONNECT_INVALID_DATA, NULL);
-- return;
-- }
--
-- /* Initialize a new temporary ByteStream for incoming data */
-- conn->buffer_incoming.len = aimutil_get16(&conn->header[4]) - 6;
-- conn->buffer_incoming.data = g_new(guint8, conn->buffer_incoming.len);
-- conn->buffer_incoming.offset = 0;
-- }
--
-- /* Read data into the temporary buffer until it is complete */
-- read = recv(conn->fd,
-- &conn->buffer_incoming.data[conn->buffer_incoming.offset],
-- conn->buffer_incoming.len - conn->buffer_incoming.offset,
-- 0);
--
-- /* Check if the remote user closed the connection */
-- if (read == 0)
-- {
-- peer_connection_destroy(conn, OSCAR_DISCONNECT_REMOTE_CLOSED, NULL);
-- return;
-- }
--
-- if (read < 0)
-- {
-- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-- /* No worries */
-- return;
--
-- peer_connection_destroy(conn,
-- OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno));
-- return;
-- }
--
-- conn->lastactivity = time(NULL);
-- conn->buffer_incoming.offset += read;
-- if (conn->buffer_incoming.offset < conn->buffer_incoming.len)
-- /* Waiting for more data to arrive */
-- return;
--
-- /* We have a complete ODC/OFT frame! Handle it and continue reading */
-- byte_stream_rewind(&conn->buffer_incoming);
-- if (conn->type == OSCAR_CAPABILITY_DIRECTIM)
-- {
-- peer_odc_recv_frame(conn, &conn->buffer_incoming);
-- }
-- else if (conn->type == OSCAR_CAPABILITY_SENDFILE)
-- {
-- peer_oft_recv_frame(conn, &conn->buffer_incoming);
-- }
--
-- g_free(conn->buffer_incoming.data);
-- conn->buffer_incoming.data = NULL;
--
-- conn->header_received = 0;
--}
--
--/*******************************************************************/
--/* End code for receiving data on a peer connection */
--/*******************************************************************/
--
--/*******************************************************************/
--/* Begin code for sending data on a peer connection */
--/*******************************************************************/
--
--static void
--send_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- PeerConnection *conn;
-- gsize writelen;
-- gssize wrotelen;
--
-- conn = data;
-- writelen = purple_circ_buffer_get_max_read(conn->buffer_outgoing);
--
-- if (writelen == 0)
-- {
-- purple_input_remove(conn->watcher_outgoing);
-- conn->watcher_outgoing = 0;
-- /*
-- * The buffer is currently empty, so reset the current input
-- * and output positions to the start of the buffer. We do
-- * this so that the next chunk of data that we put into the
-- * buffer can be read back out of the buffer in one fell swoop.
-- * Otherwise it gets fragmented and we have to read from the
-- * second half of the buffer than go back and read the rest of
-- * the chunk from the first half.
-- *
-- * We're using TCP, which is a stream based protocol, so this
-- * isn't supposed to matter. However, experience has shown
-- * that at least the proxy file transfer code in AIM 6.1.41.2
-- * requires that the entire OFT frame arrive all at once. If
-- * the frame is fragmented then AIM freaks out and aborts the
-- * file transfer. Somebody should teach those guys how to
-- * write good TCP code.
-- */
-- conn->buffer_outgoing->inptr = conn->buffer_outgoing->buffer;
-- conn->buffer_outgoing->outptr = conn->buffer_outgoing->buffer;
-- return;
-- }
--
-- wrotelen = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0);
-- if (wrotelen <= 0)
-- {
-- if (wrotelen < 0 && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
-- /* No worries */
-- return;
--
-- if (conn->ready)
-- {
-- purple_input_remove(conn->watcher_outgoing);
-- conn->watcher_outgoing = 0;
-- close(conn->fd);
-- conn->fd = -1;
-- peer_connection_schedule_destroy(conn,
-- OSCAR_DISCONNECT_LOST_CONNECTION, NULL);
-- }
-- else
-- {
-- /*
-- * This could happen when unable to send a negotiation
-- * frame to a peer proxy server.
-- */
-- peer_connection_trynext(conn);
-- }
-- return;
-- }
--
-- purple_circ_buffer_mark_read(conn->buffer_outgoing, wrotelen);
-- conn->lastactivity = time(NULL);
--}
--
--/**
-- * This should be called by OFT/ODC code to send a standard OFT or ODC
-- * frame across the peer connection along with some payload data. Or
-- * maybe a file. Anything, really.
-- */
--void
--peer_connection_send(PeerConnection *conn, ByteStream *bs)
--{
-- /* Add everything to our outgoing buffer */
-- purple_circ_buffer_append(conn->buffer_outgoing, bs->data, bs->len);
--
-- /* If we haven't already started writing stuff, then start the cycle */
-- if ((conn->watcher_outgoing == 0) && (conn->fd >= 0))
-- {
-- conn->watcher_outgoing = purple_input_add(conn->fd,
-- PURPLE_INPUT_WRITE, send_cb, conn);
-- send_cb(conn, conn->fd, 0);
-- }
--}
--
--/*******************************************************************/
--/* End code for sending data on a peer connection */
--/*******************************************************************/
--
--/*******************************************************************/
--/* Begin code for establishing a peer connection */
--/*******************************************************************/
--
--void
--peer_connection_finalize_connection(PeerConnection *conn)
--{
-- conn->watcher_incoming = purple_input_add(conn->fd,
-- PURPLE_INPUT_READ, peer_connection_recv_cb, conn);
--
-- if (conn->type == OSCAR_CAPABILITY_DIRECTIM)
-- {
-- /*
-- * If we are connecting to them then send our cookie so they
-- * can verify who we are. Note: This doesn't seem to be
-- * necessary, but it also doesn't seem to hurt.
-- */
-- if (!(conn->flags & PEER_CONNECTION_FLAG_IS_INCOMING))
-- peer_odc_send_cookie(conn);
-- }
-- else if (conn->type == OSCAR_CAPABILITY_SENDFILE)
-- {
-- if (purple_xfer_get_type(conn->xfer) == PURPLE_XFER_SEND)
-- {
-- peer_oft_send_prompt(conn);
-- }
-- }
--
-- /*
-- * Tell the remote user that we're connected (which may also imply
-- * that we've accepted their request).
-- */
-- if (!(conn->flags & PEER_CONNECTION_FLAG_IS_INCOMING))
-- aim_im_sendch2_connected(conn);
--}
--
--/**
-- * We tried to make an outgoing connection to a remote user. It
-- * either connected or failed to connect.
-- */
--static void
--peer_connection_common_established_cb(gpointer data, gint source, const gchar *error_message, gboolean verified)
--{
-- PeerConnection *conn;
--
-- conn = data;
--
-- if (verified)
-- conn->verified_connect_data = NULL;
-- else
-- conn->client_connect_data = NULL;
--
-- if (source < 0)
-- {
-- if ((conn->verified_connect_data == NULL) &&
-- (conn->client_connect_data == NULL))
-- {
-- /* Our parallel connection attemps have both failed. */
-- peer_connection_trynext(conn);
-- }
-- return;
-- }
--
-- purple_timeout_remove(conn->connect_timeout_timer);
-- conn->connect_timeout_timer = 0;
--
-- if (conn->client_connect_data != NULL)
-- {
-- purple_proxy_connect_cancel(conn->client_connect_data);
-- conn->client_connect_data = NULL;
-- }
--
-- if (conn->verified_connect_data != NULL)
-- {
-- purple_proxy_connect_cancel(conn->verified_connect_data);
-- conn->verified_connect_data = NULL;
-- }
--
-- conn->fd = source;
--
-- peer_connection_finalize_connection(conn);
--}
--
--static void
--peer_connection_verified_established_cb(gpointer data, gint source, const gchar *error_message)
--{
-- peer_connection_common_established_cb(data, source, error_message, TRUE);
--}
--
--static void
--peer_connection_client_established_cb(gpointer data, gint source, const gchar *error_message)
--{
-- peer_connection_common_established_cb(data, source, error_message, FALSE);
--}
--
--/**
-- * This is the watcher callback for any listening socket that is
-- * waiting for a peer to connect. When a peer connects we set the
-- * input watcher to start reading data from the peer.
-- *
-- * To make sure that the connection is with the intended person and
-- * not with a malicious middle man, we don't send anything until we've
-- * received a peer frame from the remote user and have verified that
-- * the cookie in the peer frame matches the cookie that was exchanged
-- * in the channel 2 ICBM.
-- */
--void
--peer_connection_listen_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- PeerConnection *conn;
-- OscarData *od;
-- PurpleConnection *gc;
-- struct sockaddr addr;
-- socklen_t addrlen = sizeof(addr);
-- int flags;
--
-- conn = data;
-- od = conn->od;
-- gc = od->gc;
--
-- purple_debug_info("oscar", "Accepting connection on listener socket.\n");
--
-- conn->fd = accept(conn->listenerfd, &addr, &addrlen);
-- if (conn->fd < 0)
-- {
-- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-- /* No connection yet--no worries */
-- /* TODO: Hmm, but they SHOULD be connected if we're here, right? */
-- return;
--
-- peer_connection_trynext(conn);
-- return;
-- }
--
-- if ((addr.sa_family != PF_INET) && (addr.sa_family != PF_INET6))
-- {
-- /* Invalid connection type?! Continue waiting. */
-- close(conn->fd);
-- return;
-- }
--
-- flags = fcntl(conn->fd, F_GETFL);
-- fcntl(conn->fd, F_SETFL, flags | O_NONBLOCK);
--#ifndef _WIN32
-- fcntl(conn->fd, F_SETFD, FD_CLOEXEC);
--#endif
--
-- purple_input_remove(conn->watcher_incoming);
--
-- peer_connection_finalize_connection(conn);
--}
--
--/**
-- * We've just opened a listener socket, so we send the remote
-- * user an ICBM and ask them to connect to us.
-- */
--static void
--peer_connection_establish_listener_cb(int listenerfd, gpointer data)
--{
-- PeerConnection *conn;
-- OscarData *od;
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- PurpleConversation *conv;
-- char *tmp;
-- FlapConnection *bos_conn;
-- const char *listener_ip;
-- const guchar *ip_atoi;
-- unsigned short listener_port;
--
-- conn = data;
-- conn->listen_data = NULL;
--
-- if (listenerfd < 0)
-- {
-- /* Could not open listener socket */
-- peer_connection_trynext(conn);
-- return;
-- }
--
-- od = conn->od;
-- gc = od->gc;
-- account = purple_connection_get_account(gc);
-- conn->listenerfd = listenerfd;
--
-- /* Watch for new connections on our listener socket */
-- conn->watcher_incoming = purple_input_add(conn->listenerfd,
-- PURPLE_INPUT_READ, peer_connection_listen_cb, conn);
--
-- /* Send the "please connect to me!" ICBM */
-- bos_conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
-- if (bos_conn == NULL)
-- {
-- /* Not good */
-- peer_connection_trynext(conn);
-- return;
-- }
--
-- if (bos_conn->gsc)
-- listener_ip = purple_network_get_my_ip(bos_conn->gsc->fd);
-- else
-- listener_ip = purple_network_get_my_ip(bos_conn->fd);
--
-- ip_atoi = purple_network_ip_atoi(listener_ip);
-- if (ip_atoi == NULL) {
-- /* Could not convert IP to 4 byte array--weird, but this does
-- happen for some users (#4829, Adium #15839). Maybe they're
-- connecting with IPv6...? Maybe through a proxy? */
-- purple_debug_error("oscar", "Can't ask peer to connect to us "
-- "because purple_network_ip_atoi(%s) returned NULL. "
-- "fd=%d. is_ssl=%d\n",
-- listener_ip ? listener_ip : "(null)",
-- bos_conn->gsc ? bos_conn->gsc->fd : bos_conn->fd,
-- bos_conn->gsc ? 1 : 0);
-- peer_connection_trynext(conn);
-- return;
-- }
--
-- listener_port = purple_network_get_port_from_fd(conn->listenerfd);
--
-- if (conn->type == OSCAR_CAPABILITY_DIRECTIM)
-- {
-- aim_im_sendch2_odc_requestdirect(od,
-- conn->cookie, conn->bn, ip_atoi,
-- listener_port, ++conn->lastrequestnumber);
--
-- /* Print a message to a local conversation window */
-- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn);
-- tmp = g_strdup_printf(_("Asking %s to connect to us at %s:%hu for "
-- "Direct IM."), conn->bn, listener_ip, listener_port);
-- purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));
-- g_free(tmp);
-- }
-- else if (conn->type == OSCAR_CAPABILITY_SENDFILE)
-- {
-- aim_im_sendch2_sendfile_requestdirect(od,
-- conn->cookie, conn->bn,
-- ip_atoi,
-- listener_port, ++conn->lastrequestnumber,
-- (const gchar *)conn->xferdata.name,
-- conn->xferdata.size, conn->xferdata.totfiles);
-- }
--}
--
--/**
-- * This is a callback function used when we're connecting to a peer
-- * using either the client IP or the verified IP and the connection
-- * took longer than 5 seconds to complete. We do this because
-- * waiting for the OS to time out the connection attempt is not
-- * practical--the default timeout on many OSes can be 3 minutes or
-- * more, and users are impatient.
-- *
-- * Worst case scenario: the user is connected to the Internet using
-- * a modem with severe lag. The peer connections fail and Purple falls
-- * back to using a proxied connection. The lower bandwidth
-- * limitations imposed by the proxied connection won't matter because
-- * the user is using a modem.
-- *
-- * I suppose this line of thinking is discriminatory against people
-- * with very high lag but decent throughput who are transferring
-- * large files. But we don't care about those people.
-- *
-- * I (Sean) changed the timeout from 15 to 5 seconds, as 60 seconds is
-- * too long for a user to wait to send a file. I'm also parallelizing
-- * requests when possible. The longest we should have to wait now is 10
-- * seconds. We shouldn't make it shorter than this.
-- */
--static gboolean
--peer_connection_tooktoolong(gpointer data)
--{
-- PeerConnection *conn;
--
-- conn = data;
--
-- purple_debug_info("oscar", "Peer connection timed out after 5 seconds. "
-- "Trying next method...\n");
--
-- peer_connection_trynext(conn);
--
-- /* Cancel this timer. It'll be added again, if needed. */
-- return FALSE;
--}
--
--/**
-- * Try to establish the given PeerConnection using a defined
-- * sequence of steps.
-- */
--void
--peer_connection_trynext(PeerConnection *conn)
--{
-- PurpleAccount *account;
--
-- account = purple_connection_get_account(conn->od->gc);
--
-- /*
-- * Close any remnants of a previous failed connection attempt.
-- */
-- peer_connection_close(conn);
--
-- /*
-- * 1. Attempt to connect to the remote user using their verifiedip and clientip.
-- * We try these at the same time and use whichever succeeds first, so we don't
-- * have to wait for a timeout.
-- */
-- if (!(conn->flags & PEER_CONNECTION_FLAG_TRIED_DIRECT) &&
-- (conn->verifiedip != NULL) && (conn->port != 0) && (!conn->use_proxy))
-- {
-- conn->flags |= PEER_CONNECTION_FLAG_TRIED_DIRECT;
--
-- if (conn->type == OSCAR_CAPABILITY_DIRECTIM)
-- {
-- gchar *tmp;
-- PurpleConversation *conv;
-- tmp = g_strdup_printf(_("Attempting to connect to %s:%hu."),
-- conn->verifiedip, conn->port);
-- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn);
-- purple_conversation_write(conv, NULL, tmp,
-- PURPLE_MESSAGE_SYSTEM, time(NULL));
-- g_free(tmp);
-- }
--
-- conn->verified_connect_data = purple_proxy_connect(NULL, account,
-- conn->verifiedip, conn->port,
-- peer_connection_verified_established_cb, conn);
--
-- if ((conn->verifiedip == NULL) ||
-- strcmp(conn->verifiedip, conn->clientip))
-- {
-- conn->client_connect_data = purple_proxy_connect(NULL, account,
-- conn->clientip, conn->port,
-- peer_connection_client_established_cb, conn);
-- }
--
-- if ((conn->verified_connect_data != NULL) ||
-- (conn->client_connect_data != NULL))
-- {
-- /* Connecting... */
-- conn->connect_timeout_timer = purple_timeout_add_seconds(5,
-- peer_connection_tooktoolong, conn);
-- return;
-- }
-- }
--
-- /*
-- * 2. Attempt to have the remote user connect to us (using both
-- * our verifiedip and our clientip).
-- */
-- if (!(conn->flags & PEER_CONNECTION_FLAG_TRIED_INCOMING) &&
-- (!conn->use_proxy))
-- {
-- conn->flags |= PEER_CONNECTION_FLAG_TRIED_INCOMING;
--
-- /*
-- * Remote user is connecting to us, so we'll need to verify
-- * that the user who connected is our friend.
-- */
-- conn->flags |= PEER_CONNECTION_FLAG_IS_INCOMING;
--
-- conn->listen_data = purple_network_listen_range(5190, 5290, SOCK_STREAM,
-- peer_connection_establish_listener_cb, conn);
-- if (conn->listen_data != NULL)
-- {
-- /* Opening listener socket... */
-- return;
-- }
-- }
--
-- /*
-- * 3. Attempt to have both users connect to an intermediate proxy
-- * server.
-- */
-- if (!(conn->flags & PEER_CONNECTION_FLAG_TRIED_PROXY))
-- {
-- conn->flags |= PEER_CONNECTION_FLAG_TRIED_PROXY;
--
-- /*
-- * If we initiate the proxy connection, then the remote user
-- * could be anyone, so we need to verify that the user who
-- * connected is our friend.
-- */
-- if (!conn->use_proxy)
-- conn->flags |= PEER_CONNECTION_FLAG_IS_INCOMING;
--
-- if (conn->type == OSCAR_CAPABILITY_DIRECTIM)
-- {
-- gchar *tmp;
-- PurpleConversation *conv;
-- tmp = g_strdup(_("Attempting to connect via proxy server."));
-- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn);
-- purple_conversation_write(conv, NULL, tmp,
-- PURPLE_MESSAGE_SYSTEM, time(NULL));
-- g_free(tmp);
-- }
--
-- conn->verified_connect_data = purple_proxy_connect(NULL, account,
-- (conn->proxyip != NULL)
-- ? conn->proxyip
-- : (conn->od->icq ? ICQ_PEER_PROXY_SERVER : AIM_PEER_PROXY_SERVER),
-- PEER_PROXY_PORT,
-- peer_proxy_connection_established_cb, conn);
-- if (conn->verified_connect_data != NULL)
-- {
-- /* Connecting... */
-- return;
-- }
-- }
--
-- /* Give up! */
-- peer_connection_destroy(conn, OSCAR_DISCONNECT_COULD_NOT_CONNECT, NULL);
--}
--
--/**
-- * Initiate a peer connection with someone.
-- */
--void
--peer_connection_propose(OscarData *od, guint64 type, const char *bn)
--{
-- PeerConnection *conn;
--
-- if (type == OSCAR_CAPABILITY_DIRECTIM)
-- {
-- conn = peer_connection_find_by_type(od, bn, type);
-- if (conn != NULL)
-- {
-- if (conn->ready)
-- {
-- PurpleAccount *account;
-- PurpleConversation *conv;
--
-- purple_debug_info("oscar", "Already have a direct IM "
-- "session with %s.\n", bn);
-- account = purple_connection_get_account(od->gc);
-- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-- bn, account);
-- if (conv != NULL)
-- purple_conversation_present(conv);
-- return;
-- }
--
-- /* Cancel the old connection and try again */
-- peer_connection_destroy(conn, OSCAR_DISCONNECT_RETRYING, NULL);
-- }
-- }
--
-- conn = peer_connection_new(od, type, bn);
-- conn->flags |= PEER_CONNECTION_FLAG_INITIATED_BY_ME;
-- conn->flags |= PEER_CONNECTION_FLAG_APPROVED;
-- aim_icbm_makecookie(conn->cookie);
--
-- peer_connection_trynext(conn);
--}
--
--/**
-- * Someone else wants to establish a peer connection with us,
-- * and we said yes.
-- */
--static void
--peer_connection_got_proposition_yes_cb(gpointer data, gint id)
--{
-- PeerConnection *conn;
--
-- conn = data;
--
-- conn->flags |= PEER_CONNECTION_FLAG_APPROVED;
-- peer_connection_trynext(conn);
--}
--
--/**
-- * Someone else wants to establish a peer connection with us,
-- * and we said no.
-- *
-- * "Well, one time my friend asked me if I wanted to play the
-- * piccolo. But I said no."
-- */
--static void
--peer_connection_got_proposition_no_cb(gpointer data, gint id)
--{
-- PeerConnection *conn;
--
-- conn = data;
--
-- aim_im_denytransfer(conn->od, conn->bn, conn->cookie,
-- AIM_TRANSFER_DENY_DECLINE);
-- peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);
--}
--
--/**
-- * Someone else wants to establish a peer connection with us.
-- */
--void
--peer_connection_got_proposition(OscarData *od, const gchar *bn, const gchar *message, IcbmArgsCh2 *args)
--{
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- PeerConnection *conn;
-- gchar *buf;
--
-- gc = od->gc;
-- account = purple_connection_get_account(gc);
--
-- /*
-- * If we have a connection with this same cookie then they are
-- * probably just telling us they weren't able to connect to us
-- * and we should try connecting to them, instead. Or they want
-- * to go through a proxy.
-- */
-- conn = peer_connection_find_by_cookie(od, bn, args->cookie);
-- if ((conn != NULL) && (conn->type == args->type))
-- {
-- purple_debug_info("oscar", "Remote user wants to try a "
-- "different connection method\n");
-- g_free(conn->proxyip);
-- g_free(conn->clientip);
-- g_free(conn->verifiedip);
-- if (args->use_proxy)
-- conn->proxyip = g_strdup(args->proxyip);
-- else
-- conn->proxyip = NULL;
-- conn->verifiedip = g_strdup(args->verifiedip);
-- conn->clientip = g_strdup(args->clientip);
-- conn->port = args->port;
-- conn->use_proxy |= args->use_proxy;
-- conn->lastrequestnumber++;
-- peer_connection_trynext(conn);
-- return;
-- }
--
-- /* If this is a direct IM, then close any existing session */
-- if (args->type == OSCAR_CAPABILITY_DIRECTIM)
-- {
-- conn = peer_connection_find_by_type(od, bn, args->type);
-- if (conn != NULL)
-- {
-- /* Close the old direct IM and start a new one */
-- purple_debug_info("oscar", "Received new direct IM request "
-- "from %s. Destroying old connection.\n", bn);
-- peer_connection_destroy(conn, OSCAR_DISCONNECT_REMOTE_CLOSED, NULL);
-- }
-- }
--
-- /* Check for proper arguments */
-- if (args->type == OSCAR_CAPABILITY_SENDFILE)
-- {
-- if ((args->info.sendfile.filename == NULL) ||
-- (args->info.sendfile.totsize == 0) ||
-- (args->info.sendfile.totfiles == 0))
-- {
-- purple_debug_warning("oscar",
-- "%s tried to send you a file with incomplete "
-- "information.\n", bn);
-- return;
-- }
-- }
--
-- conn = peer_connection_new(od, args->type, bn);
-- memcpy(conn->cookie, args->cookie, 8);
-- if (args->use_proxy)
-- conn->proxyip = g_strdup(args->proxyip);
-- conn->clientip = g_strdup(args->clientip);
-- conn->verifiedip = g_strdup(args->verifiedip);
-- conn->port = args->port;
-- conn->use_proxy |= args->use_proxy;
-- conn->lastrequestnumber++;
--
-- if (args->type == OSCAR_CAPABILITY_DIRECTIM)
-- {
-- buf = g_strdup_printf(_("%s has just asked to directly connect to %s"),
-- bn, purple_account_get_username(account));
--
-- purple_request_action(conn, NULL, buf,
-- _("This requires a direct connection between "
-- "the two computers and is necessary for IM "
-- "Images. Because your IP address will be "
-- "revealed, this may be considered a privacy "
-- "risk."),
-- PURPLE_DEFAULT_ACTION_NONE,
-- account, bn, NULL,
-- conn, 2,
-- _("C_onnect"), G_CALLBACK(peer_connection_got_proposition_yes_cb),
-- _("Cancel"), G_CALLBACK(peer_connection_got_proposition_no_cb));
-- }
-- else if (args->type == OSCAR_CAPABILITY_SENDFILE)
-- {
-- gchar *filename;
--
-- conn->xfer = purple_xfer_new(account, PURPLE_XFER_RECEIVE, bn);
-- if (conn->xfer)
-- {
-- conn->xfer->data = conn;
-- purple_xfer_ref(conn->xfer);
-- purple_xfer_set_size(conn->xfer, args->info.sendfile.totsize);
--
-- /* Set the file name */
-- if (g_utf8_validate(args->info.sendfile.filename, -1, NULL))
-- filename = g_strdup(args->info.sendfile.filename);
-- else
-- filename = purple_utf8_salvage(args->info.sendfile.filename);
--
-- if (args->info.sendfile.subtype == AIM_OFT_SUBTYPE_SEND_DIR)
-- {
-- /*
-- * If they are sending us a directory then the last character
-- * of the file name will be an asterisk. We don't want to
-- * save stuff to a directory named "*" so we remove the
-- * asterisk from the file name.
-- */
-- char *tmp = strrchr(filename, '\\');
-- if ((tmp != NULL) && (tmp[1] == '*'))
-- tmp[0] = '\0';
-- }
-- purple_xfer_set_filename(conn->xfer, filename);
-- g_free(filename);
--
-- /*
-- * Set the message, unless this is the dummy message from an
-- * ICQ client or an empty message from an AIM client.
-- * TODO: Maybe we should strip HTML and then see if strlen>0?
-- */
-- if ((message != NULL) &&
-- (g_ascii_strncasecmp(message, "<ICQ_COOL_FT>", 13) != 0) &&
-- (g_ascii_strcasecmp(message, "<HTML>") != 0))
-- {
-- purple_xfer_set_message(conn->xfer, message);
-- }
--
-- /* Setup our I/O op functions */
-- purple_xfer_set_init_fnc(conn->xfer, peer_oft_recvcb_init);
-- purple_xfer_set_end_fnc(conn->xfer, peer_oft_recvcb_end);
-- purple_xfer_set_request_denied_fnc(conn->xfer, peer_oft_cb_generic_cancel);
-- purple_xfer_set_cancel_recv_fnc(conn->xfer, peer_oft_cb_generic_cancel);
-- purple_xfer_set_ack_fnc(conn->xfer, peer_oft_recvcb_ack_recv);
--
-- /* Now perform the request */
-- purple_xfer_request(conn->xfer);
-- }
-- }
--}
--
--/*******************************************************************/
--/* End code for establishing a peer connection */
--/*******************************************************************/
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/peer.h pidgin-2.10.7-nonprism/libpurple/protocols/oscar/peer.h
---- pidgin-2.10.7/libpurple/protocols/oscar/peer.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/peer.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,282 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * OFT and ODC Services
-- */
--
--#ifndef _PEER_H_
--#define _PEER_H_
--
--#include "ft.h"
--#include "network.h"
--#include "proxy.h"
--
--typedef struct _ChecksumData ChecksumData;
--typedef struct _OdcFrame OdcFrame;
--typedef struct _OftFrame OftFrame;
--typedef struct _ProxyFrame ProxyFrame;
--typedef struct _PeerConnection PeerConnection;
--
--#define PEER_CONNECTION_FLAG_INITIATED_BY_ME 0x0001
--#define PEER_CONNECTION_FLAG_APPROVED 0x0002
--#define PEER_CONNECTION_FLAG_TRIED_DIRECT 0x0004
--#define PEER_CONNECTION_FLAG_TRIED_INCOMING 0x0008
--#define PEER_CONNECTION_FLAG_TRIED_PROXY 0x0010
--#define PEER_CONNECTION_FLAG_IS_INCOMING 0x0020
--
--#define PEER_TYPE_PROMPT 0x0101 /* "I am going to send you this file, is that ok?" */
--#define PEER_TYPE_RESUMEACCEPT 0x0106 /* We are accepting the resume */
--#define PEER_TYPE_ACK 0x0202 /* "Yes, it is ok for you to send me that file" */
--#define PEER_TYPE_DONE 0x0204 /* "I received that file with no problems" or "I already have that file, great!" */
--#define PEER_TYPE_RESUME 0x0205 /* Resume transferring, sent by whoever receives */
--#define PEER_TYPE_RESUMEACK 0x0207 /* Our resume accept was ACKed */
--
--#define PEER_TYPE_GETFILE_REQUESTLISTING 0x1108 /* "I have a listing.txt file, do you want it?" */
--#define PEER_TYPE_GETFILE_RECEIVELISTING 0x1209 /* "Yes, please send me your listing.txt file" */
--#define PEER_TYPE_GETFILE_RECEIVEDLISTING 0x120a /* received corrupt listing.txt file? I'm just guessing about this one... */
--#define PEER_TYPE_GETFILE_ACKLISTING 0x120b /* "I received the listing.txt file successfully" */
--#define PEER_TYPE_GETFILE_REQUESTFILE 0x120c /* "Please send me this file" */
--
--/*
-- * For peer proxying
-- */
--#define AIM_PEER_PROXY_SERVER "ars.oscar.aol.com"
--#define ICQ_PEER_PROXY_SERVER "ars.icq.com"
--#define PEER_PROXY_PORT 5190 /* The port we should always connect to */
--#define PEER_PROXY_PACKET_VERSION 0x044a
--
--/* Thanks to Keith Lea and the Joust project for documenting these */
--#define PEER_PROXY_TYPE_ERROR 0x0001
--#define PEER_PROXY_TYPE_CREATE 0x0002
--#define PEER_PROXY_TYPE_CREATED 0x0003
--#define PEER_PROXY_TYPE_JOIN 0x0004
--#define PEER_PROXY_TYPE_READY 0x0005
--
--struct _OdcFrame
--{
-- /* guchar magic[4]; */ /* 0 */
-- /* guint16 length; */ /* 4 */
-- guint16 type; /* 6 */
-- guint16 subtype; /* 8 */
-- /* Unknown */ /* 10 */
-- guchar cookie[8]; /* 12 */
-- /* Unknown */
-- /* guint32 payloadlength; */ /* 28 */
-- guint16 encoding; /* 32 */
-- /* Unknown */
-- guint16 flags; /* 38 */
-- /* Unknown */
-- guchar bn[32]; /* 44 */
-- /* Unknown */
-- ByteStream payload; /* 76 */
--};
--
--struct _OftFrame
--{
-- /* guchar magic[4]; */ /* 0 */
-- /* guint16 length; */ /* 4 */
-- guint16 type; /* 6 */
-- guchar cookie[8]; /* 8 */
-- guint16 encrypt; /* 16 */
-- guint16 compress; /* 18 */
-- guint16 totfiles; /* 20 */
-- guint16 filesleft; /* 22 */
-- guint16 totparts; /* 24 */
-- guint16 partsleft; /* 26 */
-- guint32 totsize; /* 28 */
-- guint32 size; /* 32 */
-- guint32 modtime; /* 36 */
-- guint32 checksum; /* 40 */
-- guint32 rfrcsum; /* 44 */
-- guint32 rfsize; /* 48 */
-- guint32 cretime; /* 52 */
-- guint32 rfcsum; /* 56 */
-- guint32 nrecvd; /* 60 */
-- guint32 recvcsum; /* 64 */
-- guchar idstring[32]; /* 68 */
-- guint8 flags; /* 100 */
-- guint8 lnameoffset; /* 101 */
-- guint8 lsizeoffset; /* 102 */
-- guchar dummy[69]; /* 103 */
-- guchar macfileinfo[16]; /* 172 */
-- guint16 nencode; /* 188 */
-- guint16 nlanguage; /* 190 */
-- guchar *name; /* 192 */
-- size_t name_length;
-- /* Payload? */ /* 256 */
--};
--
--struct _ProxyFrame
--{
-- /* guint16 length; */ /* 0 */
-- guint16 version; /* 2 */
-- guint16 type; /* 4 */
-- guint32 unknown; /* 6 */
-- guint16 flags; /* 10 */
-- ByteStream payload; /* 12 */
--};
--
--struct _PeerConnection
--{
-- OscarData *od;
-- guint64 type;
-- char *bn;
-- guchar magic[4];
-- guchar cookie[8];
-- guint16 lastrequestnumber;
--
-- gboolean ready;
-- int flags; /**< Bitmask of PEER_CONNECTION_FLAG_ */
-- time_t lastactivity; /**< Time of last transmit. */
-- guint destroy_timeout;
-- OscarDisconnectReason disconnect_reason;
-- char *error_message;
--
-- /**
-- * A pointer to either an OdcFrame or an OftFrame.
-- */
-- gpointer frame;
--
-- /**
-- * This is only used when the peer connection is being established.
-- */
-- PurpleProxyConnectData *client_connect_data;
-- PurpleProxyConnectData *verified_connect_data;
--
-- /**
-- * This is only used when the peer connection is being established.
-- */
-- PurpleNetworkListenData *listen_data;
--
--
-- /**
-- * This is only used when the peer connection is being established.
-- */
-- guint connect_timeout_timer;
--
-- /**
-- * This is only used while the remote user is attempting to
-- * connect to us.
-- */
-- int listenerfd;
--
-- int fd;
-- guint8 header[6];
-- gssize header_received;
-- guint8 proxy_header[12];
-- gssize proxy_header_received;
-- ByteStream buffer_incoming;
-- PurpleCircBuffer *buffer_outgoing;
-- guint watcher_incoming;
-- guint watcher_outgoing;
--
-- /**
-- * IP address of the proxy server, if applicable.
-- */
-- gchar *proxyip;
--
-- /**
-- * IP address of the remote user from THEIR point of view.
-- */
-- gchar *clientip;
--
-- /**
-- * IP address of the remote user from the oscar server's
-- * point of view.
-- */
-- gchar *verifiedip;
--
-- guint16 port;
-- gboolean use_proxy;
--
-- /**
-- * Checksumming
-- */
-- ChecksumData *checksum_data;
--
-- /* TODOFT */
-- PurpleXfer *xfer;
-- OftFrame xferdata;
-- guint sending_data_timer;
--};
--
--/*
-- * For all peer connections
-- */
--
--/**
-- * Create a new PeerConnection structure and initialize it with some
-- * sane defaults.
-- *
-- * @param type The type of the peer connection. One of
-- * OSCAR_CAPABILITY_DIRECTIM or OSCAR_CAPABILITY_SENDFILE.
-- */
--PeerConnection *peer_connection_new(OscarData *od, guint64 type, const char *bn);
--
--void peer_connection_destroy(PeerConnection *conn, OscarDisconnectReason reason, const gchar *error_message);
--void peer_connection_schedule_destroy(PeerConnection *conn, OscarDisconnectReason reason, const gchar *error_message);
--PeerConnection *peer_connection_find_by_type(OscarData *od, const char *bn, guint64 type);
--PeerConnection *peer_connection_find_by_cookie(OscarData *od, const char *bn, const guchar *cookie);
--
--void peer_connection_listen_cb(gpointer data, gint source, PurpleInputCondition cond);
--void peer_connection_recv_cb(gpointer data, gint source, PurpleInputCondition cond);
--void peer_connection_send(PeerConnection *conn, ByteStream *bs);
--
--void peer_connection_trynext(PeerConnection *conn);
--void peer_connection_finalize_connection(PeerConnection *conn);
--void peer_connection_propose(OscarData *od, guint64 type, const char *bn);
--void peer_connection_got_proposition(OscarData *od, const gchar *bn, const gchar *message, IcbmArgsCh2 *args);
--
--/*
-- * For ODC
-- */
--void peer_odc_close(PeerConnection *conn);
--void peer_odc_recv_frame(PeerConnection *conn, ByteStream *bs);
--void peer_odc_send_cookie(PeerConnection *conn);
--void peer_odc_send_typing(PeerConnection *conn, PurpleTypingState typing);
--void peer_odc_send_im(PeerConnection *conn, const char *msg, int len, int encoding, gboolean autoreply);
--
--/*
-- * For OFT
-- */
--void peer_oft_close(PeerConnection *conn);
--void peer_oft_recv_frame(PeerConnection *conn, ByteStream *bs);
--void peer_oft_send_prompt(PeerConnection *conn);
--void peer_oft_checksum_destroy(ChecksumData *checksum_data);
--
--/* Xfer callbacks for receiving a file */
--void peer_oft_recvcb_init(PurpleXfer *xfer);
--void peer_oft_recvcb_end(PurpleXfer *xfer);
--void peer_oft_recvcb_ack_recv(PurpleXfer *xfer, const guchar *buffer, size_t size);
--
--/* Xfer callbacks for sending a file */
--void peer_oft_sendcb_init(PurpleXfer *xfer);
--void peer_oft_sendcb_ack(PurpleXfer *xfer, const guchar *buffer, size_t size);
--
--/* Xfer callbacks for both sending and receiving */
--void peer_oft_cb_generic_cancel(PurpleXfer *xfer);
--
--/*
-- * For peer proxying
-- */
--void peer_proxy_connection_established_cb(gpointer data, gint source, const gchar *error_message);
--
--#endif /* _PEER_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/peer_proxy.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/peer_proxy.c
---- pidgin-2.10.7/libpurple/protocols/oscar/peer_proxy.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/peer_proxy.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,355 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--#ifdef HAVE_CONFIG_H
--#include <config.h>
--#endif
--
--#include "oscar.h"
--#include "peer.h"
--
--static void
--peer_proxy_send(PeerConnection *conn, ProxyFrame *frame)
--{
-- size_t length;
-- ByteStream bs;
--
-- purple_debug_info("oscar", "Outgoing peer proxy frame with "
-- "type=0x%04hx, unknown=0x%08x, flags=0x%04hx, and "
-- "payload length=%" G_GSIZE_FORMAT "\n",
-- frame->type, frame->unknown,
-- frame->flags, frame->payload.len);
--
-- length = 12 + frame->payload.len;
-- byte_stream_new(&bs, length);
-- byte_stream_put16(&bs, length - 2);
-- byte_stream_put16(&bs, PEER_PROXY_PACKET_VERSION);
-- byte_stream_put16(&bs, frame->type);
-- byte_stream_put32(&bs, frame->unknown);
-- byte_stream_put16(&bs, frame->flags);
-- byte_stream_putraw(&bs, frame->payload.data, frame->payload.len);
--
-- peer_connection_send(conn, &bs);
--
-- byte_stream_destroy(&bs);
--}
--
--/**
-- * Create a rendezvous "init send" packet and send it on its merry way.
-- * This is the first packet sent to the proxy server by the first client
-- * to indicate that this will be a proxied connection
-- *
-- * @param conn The peer connection.
-- */
--static void
--peer_proxy_send_create_new_conn(PeerConnection *conn)
--{
-- ProxyFrame frame;
-- PurpleAccount *account;
-- const gchar *bn;
-- guint8 bn_length;
--
-- memset(&frame, 0, sizeof(ProxyFrame));
-- frame.type = PEER_PROXY_TYPE_CREATE;
-- frame.flags = 0x0000;
--
-- account = purple_connection_get_account(conn->od->gc);
-- bn = purple_account_get_username(account);
-- bn_length = strlen(bn);
-- byte_stream_new(&frame.payload, 1 + bn_length + 8 + 20);
-- byte_stream_put8(&frame.payload, bn_length);
-- byte_stream_putraw(&frame.payload, (const guint8 *)bn, bn_length);
-- byte_stream_putraw(&frame.payload, conn->cookie, 8);
--
-- byte_stream_put16(&frame.payload, 0x0001); /* Type */
-- byte_stream_put16(&frame.payload, 16); /* Length */
-- byte_stream_putcaps(&frame.payload, conn->type); /* Value */
--
-- peer_proxy_send(conn, &frame);
--
-- byte_stream_destroy(&frame.payload);
--}
--
--/**
-- * Create a rendezvous "init recv" packet and send it on its merry way.
-- * This is the first packet sent to the proxy server by the second client
-- * involved in this rendezvous proxy session.
-- *
-- * @param conn The peer connection.
-- * @param pin The 2 byte PIN sent to us by the other user. This acts
-- * as our passcode when establishing the proxy session.
-- */
--static void
--peer_proxy_send_join_existing_conn(PeerConnection *conn, guint16 pin)
--{
-- ProxyFrame frame;
-- PurpleAccount *account;
-- const gchar *bn;
-- guint8 bn_length;
--
-- memset(&frame, 0, sizeof(ProxyFrame));
-- frame.type = PEER_PROXY_TYPE_JOIN;
-- frame.flags = 0x0000;
--
-- account = purple_connection_get_account(conn->od->gc);
-- bn = purple_account_get_username(account);
-- bn_length = strlen(bn);
-- byte_stream_new(&frame.payload, 1 + bn_length + 2 + 8 + 20);
-- byte_stream_put8(&frame.payload, bn_length);
-- byte_stream_putraw(&frame.payload, (const guint8 *)bn, bn_length);
-- byte_stream_put16(&frame.payload, pin);
-- byte_stream_putraw(&frame.payload, conn->cookie, 8);
--
-- byte_stream_put16(&frame.payload, 0x0001); /* Type */
-- byte_stream_put16(&frame.payload, 16); /* Length */
-- byte_stream_putcaps(&frame.payload, conn->type); /* Value */
--
-- peer_proxy_send(conn, &frame);
--
-- byte_stream_destroy(&frame.payload);
--}
--
--/**
-- * Handle an incoming peer proxy negotiation frame.
-- */
--static void
--peer_proxy_recv_frame(PeerConnection *conn, ProxyFrame *frame)
--{
-- purple_debug_info("oscar", "Incoming peer proxy frame with "
-- "type=0x%04hx, unknown=0x%08x, flags=0x%04hx, and "
-- "payload length=%" G_GSIZE_FORMAT "\n", frame->type,
-- frame->unknown, frame->flags, frame->payload.len);
--
-- if (frame->type == PEER_PROXY_TYPE_CREATED)
-- {
-- /*
-- * Read in 2 byte port then 4 byte IP and tell the
-- * remote user to connect to it by sending an ICBM.
-- */
-- guint16 pin;
-- int i;
-- guint8 ip[4];
--
-- pin = byte_stream_get16(&frame->payload);
-- for (i = 0; i < 4; i++)
-- ip[i] = byte_stream_get8(&frame->payload);
-- if (conn->type == OSCAR_CAPABILITY_DIRECTIM)
-- aim_im_sendch2_odc_requestproxy(conn->od,
-- conn->cookie,
-- conn->bn, ip, pin, ++conn->lastrequestnumber);
-- else if (conn->type == OSCAR_CAPABILITY_SENDFILE)
-- {
-- aim_im_sendch2_sendfile_requestproxy(conn->od,
-- conn->cookie, conn->bn,
-- ip, pin, ++conn->lastrequestnumber,
-- (const gchar *)conn->xferdata.name,
-- conn->xferdata.size, conn->xferdata.totfiles);
-- }
-- }
-- else if (frame->type == PEER_PROXY_TYPE_READY)
-- {
-- purple_input_remove(conn->watcher_incoming);
-- conn->watcher_incoming = 0;
--
-- peer_connection_finalize_connection(conn);
-- }
-- else if (frame->type == PEER_PROXY_TYPE_ERROR)
-- {
-- if (byte_stream_bytes_left(&frame->payload) >= 2)
-- {
-- guint16 error;
-- const char *msg;
-- error = byte_stream_get16(&frame->payload);
-- if (error == 0x000d)
-- msg = "bad request";
-- else if (error == 0x0010)
-- msg = "initial request timed out";
-- else if (error == 0x001a)
-- msg ="accept period timed out";
-- else
-- msg = "unknown reason";
-- purple_debug_info("oscar", "Proxy negotiation failed with "
-- "error 0x%04hx: %s\n", error, msg);
-- }
-- else
-- {
-- purple_debug_warning("oscar", "Proxy negotiation failed with "
-- "an unknown error\n");
-- }
-- peer_connection_trynext(conn);
-- }
-- else
-- {
-- purple_debug_warning("oscar", "Unknown peer proxy frame type 0x%04hx.\n",
-- frame->type);
-- }
--}
--
--static void
--peer_proxy_connection_recv_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- PeerConnection *conn;
-- gssize read;
-- ProxyFrame *frame;
--
-- conn = data;
-- frame = conn->frame;
--
-- /* Start reading a new proxy frame */
-- if (frame == NULL)
-- {
-- /* Read the first 12 bytes (frame length and header) */
-- read = recv(conn->fd, conn->proxy_header + conn->proxy_header_received,
-- 12 - conn->proxy_header_received, 0);
--
-- /* Check if the proxy server closed the connection */
-- if (read == 0)
-- {
-- purple_debug_info("oscar", "Peer proxy server closed connection\n");
-- peer_connection_trynext(conn);
-- return;
-- }
--
-- /* If there was an error then close the connection */
-- if (read < 0)
-- {
-- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-- /* No worries */
-- return;
--
-- purple_debug_info("oscar", "Lost connection with peer proxy server\n");
-- peer_connection_trynext(conn);
-- return;
-- }
--
-- conn->lastactivity = time(NULL);
--
-- /* If we don't even have the first 12 bytes then do nothing */
-- conn->proxy_header_received += read;
-- if (conn->proxy_header_received < 12)
-- return;
--
-- /* We only support a specific version of the proxy protocol */
-- if (aimutil_get16(&conn->proxy_header[2]) != PEER_PROXY_PACKET_VERSION)
-- {
-- purple_debug_warning("oscar", "Expected peer proxy protocol "
-- "version %u but received version %u. Closing "
-- "connection.\n", PEER_PROXY_PACKET_VERSION,
-- aimutil_get16(&conn->proxy_header[2]));
-- peer_connection_trynext(conn);
-- return;
-- }
--
-- /* Initialize a new temporary ProxyFrame for incoming data */
-- frame = g_new0(ProxyFrame, 1);
-- frame->payload.len = aimutil_get16(&conn->proxy_header[0]) - 10;
-- frame->version = aimutil_get16(&conn->proxy_header[2]);
-- frame->type = aimutil_get16(&conn->proxy_header[4]);
-- frame->unknown = aimutil_get16(&conn->proxy_header[6]);
-- frame->flags = aimutil_get16(&conn->proxy_header[10]);
-- if (frame->payload.len > 0)
-- frame->payload.data = g_new(guint8, frame->payload.len);
-- conn->frame = frame;
-- }
--
-- /* If this frame has a payload then attempt to read it */
-- if (frame->payload.len - frame->payload.offset > 0)
-- {
-- /* Read data into the temporary buffer until it is complete */
-- read = recv(conn->fd,
-- &frame->payload.data[frame->payload.offset],
-- frame->payload.len - frame->payload.offset,
-- 0);
--
-- /* Check if the proxy server closed the connection */
-- if (read == 0)
-- {
-- purple_debug_info("oscar", "Peer proxy server closed connection\n");
-- g_free(frame->payload.data);
-- g_free(frame);
-- conn->frame = NULL;
-- peer_connection_trynext(conn);
-- return;
-- }
--
-- /* If there was an error then close the connection */
-- if (read < 0)
-- {
-- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-- /* No worries */
-- return;
--
-- purple_debug_info("oscar", "Lost connection with peer proxy server\n");
-- g_free(frame->payload.data);
-- g_free(frame);
-- conn->frame = NULL;
-- peer_connection_trynext(conn);
-- return;
-- }
--
-- frame->payload.offset += read;
-- }
--
-- conn->lastactivity = time(NULL);
-- if (frame->payload.offset < frame->payload.len)
-- /* Waiting for more data to arrive */
-- return;
--
-- /* We have a complete proxy frame! Handle it and continue reading */
-- conn->frame = NULL;
-- byte_stream_rewind(&frame->payload);
-- peer_proxy_recv_frame(conn, frame);
--
-- g_free(frame->payload.data);
-- g_free(frame);
--
-- conn->proxy_header_received = 0;
--}
--
--/**
-- * We tried to make an outgoing connection to a proxy server. It
-- * either connected or failed to connect.
-- */
--void
--peer_proxy_connection_established_cb(gpointer data, gint source, const gchar *error_message)
--{
-- PeerConnection *conn;
--
-- conn = data;
--
-- conn->verified_connect_data = NULL;
--
-- if (source < 0)
-- {
-- peer_connection_trynext(conn);
-- return;
-- }
--
-- conn->fd = source;
-- conn->watcher_incoming = purple_input_add(conn->fd,
-- PURPLE_INPUT_READ, peer_proxy_connection_recv_cb, conn);
--
-- if (conn->proxyip != NULL)
-- /* Connect to the session created by the remote user */
-- peer_proxy_send_join_existing_conn(conn, conn->port);
-- else
-- /* Create a new session */
-- peer_proxy_send_create_new_conn(conn);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/rxhandlers.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/rxhandlers.c
---- pidgin-2.10.7/libpurple/protocols/oscar/rxhandlers.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/rxhandlers.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,95 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--#include "oscar.h"
--#include "peer.h"
--
--aim_module_t *aim__findmodulebygroup(OscarData *od, guint16 group)
--{
-- aim_module_t *cur;
--
-- for (cur = (aim_module_t *)od->modlistv; cur; cur = cur->next) {
-- if (cur->family == group)
-- return cur;
-- }
--
-- return NULL;
--}
--
--aim_module_t *aim__findmodule(OscarData *od, const char *name)
--{
-- aim_module_t *cur;
--
-- for (cur = (aim_module_t *)od->modlistv; cur; cur = cur->next) {
-- if (strcmp(name, cur->name) == 0)
-- return cur;
-- }
--
-- return NULL;
--}
--
--int aim__registermodule(OscarData *od, int (*modfirst)(OscarData *, aim_module_t *))
--{
-- aim_module_t *mod;
--
-- if (!od || !modfirst)
-- return -1;
--
-- mod = g_new0(aim_module_t, 1);
--
-- if (modfirst(od, mod) == -1) {
-- g_free(mod);
-- return -1;
-- }
--
-- if (aim__findmodule(od, mod->name)) {
-- if (mod->shutdown)
-- mod->shutdown(od, mod);
-- g_free(mod);
-- return -1;
-- }
--
-- mod->next = (aim_module_t *)od->modlistv;
-- od->modlistv = mod;
--
-- return 0;
--}
--
--void aim__shutdownmodules(OscarData *od)
--{
-- aim_module_t *cur;
--
-- for (cur = (aim_module_t *)od->modlistv; cur; ) {
-- aim_module_t *tmp;
--
-- tmp = cur->next;
--
-- if (cur->shutdown)
-- cur->shutdown(od, cur);
--
-- g_free(cur);
--
-- cur = tmp;
-- }
--
-- od->modlistv = NULL;
--
-- return;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/snac.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/snac.c
---- pidgin-2.10.7/libpurple/protocols/oscar/snac.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/snac.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,163 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- *
-- * Various SNAC-related dodads...
-- *
-- * outstanding_snacs is a list of aim_snac_t structs. A SNAC should be added
-- * whenever a new SNAC is sent and it should remain in the list until the
-- * response for it has been received.
-- *
-- * cleansnacs() should be called periodically by the client in order
-- * to facilitate the aging out of unreplied-to SNACs. This can and does
-- * happen, so it should be handled.
-- *
-- */
--
--#include "oscar.h"
--
--/*
-- * Called from oscar_session_new() to initialize the hash.
-- */
--void aim_initsnachash(OscarData *od)
--{
-- int i;
--
-- for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++)
-- od->snac_hash[i] = NULL;
--
-- return;
--}
--
--aim_snacid_t aim_cachesnac(OscarData *od, const guint16 family, const guint16 type, const guint16 flags, const void *data, const int datalen)
--{
-- aim_snac_t snac;
--
-- snac.id = od->snacid_next++;
-- snac.family = family;
-- snac.type = type;
-- snac.flags = flags;
--
-- if (datalen)
-- snac.data = g_memdup(data, datalen);
-- else
-- snac.data = NULL;
--
-- return aim_newsnac(od, &snac);
--}
--
--/*
-- * Clones the passed snac structure and caches it in the
-- * list/hash.
-- */
--aim_snacid_t aim_newsnac(OscarData *od, aim_snac_t *newsnac)
--{
-- aim_snac_t *snac;
-- int index;
--
-- if (!newsnac)
-- return 0;
--
-- snac = g_memdup(newsnac, sizeof(aim_snac_t));
-- snac->issuetime = time(NULL);
--
-- index = snac->id % FAIM_SNAC_HASH_SIZE;
--
-- snac->next = (aim_snac_t *)od->snac_hash[index];
-- od->snac_hash[index] = (void *)snac;
--
-- return snac->id;
--}
--
--/*
-- * Finds a snac structure with the passed SNAC ID,
-- * removes it from the list/hash, and returns a pointer to it.
-- *
-- * The returned structure must be freed by the caller.
-- *
-- */
--aim_snac_t *aim_remsnac(OscarData *od, aim_snacid_t id)
--{
-- aim_snac_t *cur, **prev;
-- int index;
--
-- index = id % FAIM_SNAC_HASH_SIZE;
--
-- for (prev = (aim_snac_t **)&od->snac_hash[index]; (cur = *prev); ) {
-- if (cur->id == id) {
-- *prev = cur->next;
-- if (cur->flags & AIM_SNACFLAGS_DESTRUCTOR) {
-- g_free(cur->data);
-- cur->data = NULL;
-- }
-- return cur;
-- } else
-- prev = &cur->next;
-- }
--
-- return cur;
--}
--
--/*
-- * This is for cleaning up old SNACs that either don't get replies or
-- * a reply was never received for. Garbage collection. Plain and simple.
-- *
-- * maxage is the _minimum_ age in seconds to keep SNACs.
-- *
-- */
--void aim_cleansnacs(OscarData *od, int maxage)
--{
-- int i;
--
-- for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) {
-- aim_snac_t *cur, **prev;
-- time_t curtime;
--
-- if (!od->snac_hash[i])
-- continue;
--
-- curtime = time(NULL); /* done here in case we waited for the lock */
--
-- for (prev = (aim_snac_t **)&od->snac_hash[i]; (cur = *prev); ) {
-- if ((curtime - cur->issuetime) > maxage) {
--
-- *prev = cur->next;
--
-- g_free(cur->data);
-- g_free(cur);
-- } else
-- prev = &cur->next;
-- }
-- }
--
-- return;
--}
--
--int aim_putsnac(ByteStream *bs, guint16 family, guint16 subtype, aim_snacid_t snacid)
--{
--
-- byte_stream_put16(bs, family);
-- byte_stream_put16(bs, subtype);
-- byte_stream_put16(bs, 0x0000);
-- byte_stream_put32(bs, snacid);
--
-- return 10;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/snactypes.h pidgin-2.10.7-nonprism/libpurple/protocols/oscar/snactypes.h
---- pidgin-2.10.7/libpurple/protocols/oscar/snactypes.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/snactypes.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,287 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * AIM Callback Types
-- *
-- */
--#ifndef _SNACTYPES_H_
--#define _SNACTYPES_H_
--
--/*
-- * SNAC Families.
-- */
--#define SNAC_FAMILY_OSERVICE 0x0001
--#define SNAC_FAMILY_LOCATE 0x0002
--#define SNAC_FAMILY_BUDDY 0x0003
--#define SNAC_FAMILY_ICBM 0x0004
--#define SNAC_FAMILY_ADVERT 0x0005
--#define SNAC_FAMILY_INVITE 0x0006
--#define SNAC_FAMILY_ADMIN 0x0007
--#define SNAC_FAMILY_POPUP 0x0008
--#define SNAC_FAMILY_BOS 0x0009
--#define SNAC_FAMILY_USERLOOKUP 0x000a
--#define SNAC_FAMILY_STATS 0x000b
--#define SNAC_FAMILY_TRANSLATE 0x000c
--#define SNAC_FAMILY_CHATNAV 0x000d
--#define SNAC_FAMILY_CHAT 0x000e
--#define SNAC_FAMILY_ODIR 0x000f
--#define SNAC_FAMILY_BART 0x0010
--#define SNAC_FAMILY_FEEDBAG 0x0013
--#define SNAC_FAMILY_ICQ 0x0015
--#define SNAC_FAMILY_AUTH 0x0017
--#define SNAC_FAMILY_ALERT 0x0018
--
--#define AIM_CB_FAM_SPECIAL 0xffff /* Internal libfaim use */
--
--/*
-- * SNAC Family: Ack.
-- *
-- * Not really a family, but treating it as one really
-- * helps it fit into the libfaim callback structure better.
-- *
-- */
--#define AIM_CB_ACK_ACK 0x0001
--
--/*
-- * SNAC Family: General.
-- */
--#define SNAC_SUBTYPE_OSERVICE_ERROR 0x0001
--#define SNAC_SUBTYPE_OSERVICE_CLIENTREADY 0x0002
--#define SNAC_SUBTYPE_OSERVICE_SERVERREADY 0x0003
--#define SNAC_SUBTYPE_OSERVICE_SERVICEREQ 0x0004
--#define SNAC_SUBTYPE_OSERVICE_REDIRECT 0x0005
--#define SNAC_SUBTYPE_OSERVICE_RATEINFOREQ 0x0006
--#define SNAC_SUBTYPE_OSERVICE_RATEINFO 0x0007
--#define SNAC_SUBTYPE_OSERVICE_RATEINFOACK 0x0008
--#define SNAC_SUBTYPE_OSERVICE_RATECHANGE 0x000a
--#define SNAC_SUBTYPE_OSERVICE_SERVERPAUSE 0x000b
--#define SNAC_SUBTYPE_OSERVICE_SERVERRESUME 0x000d
--#define SNAC_SUBTYPE_OSERVICE_REQSELFINFO 0x000e
--#define SNAC_SUBTYPE_OSERVICE_SELFINFO 0x000f
--#define SNAC_SUBTYPE_OSERVICE_EVIL 0x0010
--#define SNAC_SUBTYPE_OSERVICE_SETIDLE 0x0011
--#define SNAC_SUBTYPE_OSERVICE_MIGRATIONREQ 0x0012
--#define SNAC_SUBTYPE_OSERVICE_MOTD 0x0013
--#define SNAC_SUBTYPE_OSERVICE_SETPRIVFLAGS 0x0014
--#define SNAC_SUBTYPE_OSERVICE_WELLKNOWNURL 0x0015
--#define SNAC_SUBTYPE_OSERVICE_NOP 0x0016
--#define SNAC_SUBTYPE_OSERVICE_DEFAULT 0xffff
--
--/*
-- * SNAC Family: Location Services.
-- */
--#define SNAC_SUBTYPE_LOCATE_ERROR 0x0001
--#define SNAC_SUBTYPE_LOCATE_REQRIGHTS 0x0002
--#define SNAC_SUBTYPE_LOCATE_RIGHTSINFO 0x0003
--#define SNAC_SUBTYPE_LOCATE_SETUSERINFO 0x0004
--#define SNAC_SUBTYPE_LOCATE_REQUSERINFO 0x0005
--#define SNAC_SUBTYPE_LOCATE_USERINFO 0x0006
--#define SNAC_SUBTYPE_LOCATE_WATCHERSUBREQ 0x0007
--#define SNAC_SUBTYPE_LOCATE_WATCHERNOT 0x0008
--#define SNAC_SUBTYPE_LOCATE_DEFAULT 0xffff
--
--/*
-- * SNAC Family: Buddy List Management Services.
-- */
--#define SNAC_SUBTYPE_BUDDY_ERROR 0x0001
--#define SNAC_SUBTYPE_BUDDY_REQRIGHTS 0x0002
--#define SNAC_SUBTYPE_BUDDY_RIGHTSINFO 0x0003
--#define SNAC_SUBTYPE_BUDDY_ADDBUDDY 0x0004
--#define SNAC_SUBTYPE_BUDDY_REMBUDDY 0x0005
--#define SNAC_SUBTYPE_BUDDY_REJECT 0x000a
--#define SNAC_SUBTYPE_BUDDY_ONCOMING 0x000b
--#define SNAC_SUBTYPE_BUDDY_OFFGOING 0x000c
--#define SNAC_SUBTYPE_BUDDY_DEFAULT 0xffff
--
--/*
-- * SNAC Family: Messaging Services.
-- */
--#define SNAC_SUBTYPE_ICBM_ERROR 0x0001
--#define SNAC_SUBTYPE_ICBM_PARAMINFO 0x0005
--#define SNAC_SUBTYPE_ICBM_INCOMING 0x0007
--#define SNAC_SUBTYPE_ICBM_EVIL 0x0009
--#define SNAC_SUBTYPE_ICBM_MISSEDCALL 0x000a
--#define SNAC_SUBTYPE_ICBM_CLIENTAUTORESP 0x000b
--#define SNAC_SUBTYPE_ICBM_ACK 0x000c
--#define SNAC_SUBTYPE_ICBM_MTN 0x0014
--#define SNAC_SUBTYPE_ICBM_DEFAULT 0xffff
--
--/*
-- * SNAC Family: Advertisement Services
-- */
--#define SNAC_SUBTYPE_ADVERT_ERROR 0x0001
--#define SNAC_SUBTYPE_ADVERT_DEFAULT 0xffff
--
--/*
-- * SNAC Family: Invitation Services.
-- */
--#define SNAC_SUBTYPE_INVITE_ERROR 0x0001
--#define SNAC_SUBTYPE_INVITE_DEFAULT 0xffff
--
--/*
-- * SNAC Family: Administrative Services.
-- */
--#define SNAC_SUBTYPE_ADMIN_ERROR 0x0001
--#define SNAC_SUBTYPE_ADMIN_INFOCHANGE_REPLY 0x0005
--#define SNAC_SUBTYPE_ADMIN_DEFAULT 0xffff
--
--/*
-- * SNAC Family: Popup Messages
-- */
--#define SNAC_SUBTYPE_POPUP_ERROR 0x0001
--#define SNAC_SUBTYPE_POPUP_DEFAULT 0xffff
--
--/*
-- * SNAC Family: Misc BOS Services.
-- */
--#define SNAC_SUBTYPE_BOS_ERROR 0x0001
--#define SNAC_SUBTYPE_BOS_RIGHTSQUERY 0x0002
--#define SNAC_SUBTYPE_BOS_RIGHTS 0x0003
--#define SNAC_SUBTYPE_BOS_DEFAULT 0xffff
--
--/*
-- * SNAC Family: User Lookup Services
-- */
--#define SNAC_SUBTYPE_USERLOOKUP_ERROR 0x0001
--#define SNAC_SUBTYPE_USERLOOKUP_DEFAULT 0xffff
--
--/*
-- * SNAC Family: User Status Services
-- */
--#define SNAC_SUBTYPE_STATS_ERROR 0x0001
--#define SNAC_SUBTYPE_STATS_SETREPORTINTERVAL 0x0002
--#define SNAC_SUBTYPE_STATS_REPORTACK 0x0004
--#define SNAC_SUBTYPE_STATS_DEFAULT 0xffff
--
--/*
-- * SNAC Family: Translation Services
-- */
--#define SNAC_SUBTYPE_TRANSLATE_ERROR 0x0001
--#define SNAC_SUBTYPE_TRANSLATE_DEFAULT 0xffff
--
--/*
-- * SNAC Family: Chat Navigation Services
-- */
--#define SNAC_SUBTYPE_CHATNAV_ERROR 0x0001
--#define SNAC_SUBTYPE_CHATNAV_CREATE 0x0008
--#define SNAC_SUBTYPE_CHATNAV_INFO 0x0009
--#define SNAC_SUBTYPE_CHATNAV_DEFAULT 0xffff
--
--/*
-- * SNAC Family: Chat Services
-- */
--#define SNAC_SUBTYPE_CHAT_ERROR 0x0001
--#define SNAC_SUBTYPE_CHAT_ROOMINFOUPDATE 0x0002
--#define SNAC_SUBTYPE_CHAT_USERJOIN 0x0003
--#define SNAC_SUBTYPE_CHAT_USERLEAVE 0x0004
--#define SNAC_SUBTYPE_CHAT_OUTGOINGMSG 0x0005
--#define SNAC_SUBTYPE_CHAT_INCOMINGMSG 0x0006
--#define SNAC_SUBTYPE_CHAT_DEFAULT 0xffff
--
--/*
-- * SNAC Family: "New" Search
-- */
--#define SNAC_SUBTYPE_ODIR_ERROR 0x0001
--#define SNAC_SUBTYPE_ODIR_SEARCH 0x0002
--#define SNAC_SUBTYPE_ODIR_RESULTS 0x0003
--
--/*
-- * SNAC Family: Buddy icons
-- */
--#define SNAC_SUBTYPE_BART_ERROR 0x0001
--#define SNAC_SUBTYPE_BART_REQUEST 0x0004
--#define SNAC_SUBTYPE_BART_RESPONSE 0x0005
--
--/*
-- * SNAC Family: Server-Stored Buddy Lists
-- */
--#define SNAC_SUBTYPE_FEEDBAG_ERROR 0x0001
--#define SNAC_SUBTYPE_FEEDBAG_REQRIGHTS 0x0002
--#define SNAC_SUBTYPE_FEEDBAG_RIGHTSINFO 0x0003
--#define SNAC_SUBTYPE_FEEDBAG_REQDATA 0x0004
--#define SNAC_SUBTYPE_FEEDBAG_REQIFCHANGED 0x0005
--#define SNAC_SUBTYPE_FEEDBAG_LIST 0x0006
--#define SNAC_SUBTYPE_FEEDBAG_ACTIVATE 0x0007
--#define SNAC_SUBTYPE_FEEDBAG_ADD 0x0008
--#define SNAC_SUBTYPE_FEEDBAG_MOD 0x0009
--#define SNAC_SUBTYPE_FEEDBAG_DEL 0x000A
--#define SNAC_SUBTYPE_FEEDBAG_SRVACK 0x000E
--#define SNAC_SUBTYPE_FEEDBAG_NOLIST 0x000F
--#define SNAC_SUBTYPE_FEEDBAG_EDITSTART 0x0011
--#define SNAC_SUBTYPE_FEEDBAG_EDITSTOP 0x0012
--#define SNAC_SUBTYPE_FEEDBAG_SENDAUTH 0x0014
--#define SNAC_SUBTYPE_FEEDBAG_RECVAUTH 0x0015
--#define SNAC_SUBTYPE_FEEDBAG_SENDAUTHREQ 0x0018
--#define SNAC_SUBTYPE_FEEDBAG_RECVAUTHREQ 0x0019
--#define SNAC_SUBTYPE_FEEDBAG_SENDAUTHREP 0x001a
--#define SNAC_SUBTYPE_FEEDBAG_RECVAUTHREP 0x001b
--#define SNAC_SUBTYPE_FEEDBAG_ADDED 0x001c
--
--/*
-- * SNAC Family: ICQ
-- *
-- * Most of these are actually special.
-- */
--#define SNAC_SUBTYPE_ICQ_ERROR 0x0001
--#define SNAC_SUBTYPE_ICQ_OFFLINEMSG 0x00f0
--#define SNAC_SUBTYPE_ICQ_OFFLINEMSGCOMPLETE 0x00f1
--#define SNAC_SUBTYPE_ICQ_INFO 0x00f2
--#define SNAC_SUBTYPE_ICQ_ALIAS 0x00f3
--#define SNAC_SUBTYPE_ICQ_DEFAULT 0xffff
--
--/*
-- * SNAC Family: Authorizer
-- *
-- * Used only in protocol versions three and above.
-- */
--#define SNAC_SUBTYPE_AUTH_ERROR 0x0001
--#define SNAC_SUBTYPE_AUTH_LOGINREQEST 0x0002
--#define SNAC_SUBTYPE_AUTH_LOGINRESPONSE 0x0003
--#define SNAC_SUBTYPE_AUTH_AUTHREQ 0x0006
--#define SNAC_SUBTYPE_AUTH_AUTHRESPONSE 0x0007
--#define SNAC_SUBTYPE_AUTH_SECURID_REQUEST 0x000a
--#define SNAC_SUBTYPE_AUTH_SECURID_RESPONSE 0x000b
--
--/*
-- * SNAC Family: Email
-- *
-- * Used for getting information on the email address
-- * associated with your username.
-- */
--#define SNAC_SUBTYPE_ALERT_ERROR 0x0001
--#define SNAC_SUBTYPE_ALERT_SENDCOOKIES 0x0006
--#define SNAC_SUBTYPE_ALERT_MAILSTATUS 0x0007
--#define SNAC_SUBTYPE_ALERT_INIT 0x0016
--
--/*
-- * SNAC Family: Internal Messages
-- *
-- * This isn't truly a SNAC family either, but using
-- * these, we can integrated non-SNAC services into
-- * the SNAC-centered libfaim callback structure.
-- */
--#define AIM_CB_SPECIAL_CONNERR 0x0003
--#define AIM_CB_SPECIAL_CONNINITDONE 0x0006
--
--/* SNAC flags */
--#define AIM_SNACFLAGS_DESTRUCTOR 0x0001
--
--#endif /* _SNACTYPES_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/tlv.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/tlv.c
---- pidgin-2.10.7/libpurple/protocols/oscar/tlv.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/tlv.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,828 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--#include "oscar.h"
--
--static aim_tlv_t *
--createtlv(guint16 type, guint16 length, guint8 *value)
--{
-- aim_tlv_t *ret;
--
-- ret = g_new(aim_tlv_t, 1);
-- ret->type = type;
-- ret->length = length;
-- ret->value = value;
--
-- return ret;
--}
--
--static void
--freetlv(aim_tlv_t *oldtlv)
--{
-- g_free(oldtlv->value);
-- g_free(oldtlv);
--}
--
--static GSList *
--aim_tlv_read(GSList *list, ByteStream *bs)
--{
-- guint16 type, length;
-- aim_tlv_t *tlv;
--
-- type = byte_stream_get16(bs);
-- length = byte_stream_get16(bs);
--
-- if (length > byte_stream_bytes_left(bs)) {
-- aim_tlvlist_free(list);
-- return NULL;
-- }
--
-- tlv = createtlv(type, length, NULL);
-- if (tlv->length > 0) {
-- tlv->value = byte_stream_getraw(bs, length);
-- if (!tlv->value) {
-- freetlv(tlv);
-- aim_tlvlist_free(list);
-- return NULL;
-- }
-- }
--
-- return g_slist_prepend(list, tlv);
--}
--
--/**
-- * Read a TLV chain from a buffer.
-- *
-- * Reads and parses a series of TLV patterns from a data buffer; the
-- * returned structure is manipulatable with the rest of the TLV
-- * routines. When done with a TLV chain, aim_tlvlist_free() should
-- * be called to free the dynamic substructures.
-- *
-- * TODO: There should be a flag setable here to have the tlvlist contain
-- * bstream references, so that at least the ->value portion of each
-- * element doesn't need to be malloc/memcpy'd. This could prove to be
-- * just as efficient as the in-place TLV parsing used in a couple places
-- * in libfaim.
-- *
-- * @param bs Input bstream
-- * @return Return the TLV chain read
-- */
--GSList *aim_tlvlist_read(ByteStream *bs)
--{
-- GSList *list = NULL;
--
-- while (byte_stream_bytes_left(bs) > 0) {
-- list = aim_tlv_read(list, bs);
-- if (list == NULL)
-- return NULL;
-- }
--
-- return g_slist_reverse(list);
--}
--
--/**
-- * Read a TLV chain from a buffer.
-- *
-- * Reads and parses a series of TLV patterns from a data buffer; the
-- * returned structure is manipulatable with the rest of the TLV
-- * routines. When done with a TLV chain, aim_tlvlist_free() should
-- * be called to free the dynamic substructures.
-- *
-- * TODO: There should be a flag setable here to have the tlvlist contain
-- * bstream references, so that at least the ->value portion of each
-- * element doesn't need to be malloc/memcpy'd. This could prove to be
-- * just as efficient as the in-place TLV parsing used in a couple places
-- * in libfaim.
-- *
-- * @param bs Input bstream
-- * @param num The max number of TLVs that will be read, or -1 if unlimited.
-- * There are a number of places where you want to read in a tlvchain,
-- * but the chain is not at the end of the SNAC, and the chain is
-- * preceded by the number of TLVs. So you can limit that with this.
-- * @return Return the TLV chain read
-- */
--GSList *aim_tlvlist_readnum(ByteStream *bs, guint16 num)
--{
-- GSList *list = NULL;
--
-- while ((byte_stream_bytes_left(bs) > 0) && (num != 0)) {
-- list = aim_tlv_read(list, bs);
-- if (list == NULL)
-- return NULL;
-- num--;
-- }
--
-- return g_slist_reverse(list);
--}
--
--/**
-- * Read a TLV chain from a buffer.
-- *
-- * Reads and parses a series of TLV patterns from a data buffer; the
-- * returned structure is manipulatable with the rest of the TLV
-- * routines. When done with a TLV chain, aim_tlvlist_free() should
-- * be called to free the dynamic substructures.
-- *
-- * TODO: There should be a flag setable here to have the tlvlist contain
-- * bstream references, so that at least the ->value portion of each
-- * element doesn't need to be malloc/memcpy'd. This could prove to be
-- * just as efficient as the in-place TLV parsing used in a couple places
-- * in libfaim.
-- *
-- * @param bs Input bstream
-- * @param len The max length in bytes that will be read.
-- * There are a number of places where you want to read in a tlvchain,
-- * but the chain is not at the end of the SNAC, and the chain is
-- * preceded by the length of the TLVs. So you can limit that with this.
-- * @return Return the TLV chain read
-- */
--GSList *aim_tlvlist_readlen(ByteStream *bs, guint16 len)
--{
-- GSList *list = NULL;
--
-- while ((byte_stream_bytes_left(bs) > 0) && (len > 0)) {
-- list = aim_tlv_read(list, bs);
-- if (list == NULL)
-- return NULL;
--
-- len -= 2 + 2 + ((aim_tlv_t *)list->data)->length;
-- }
--
-- return g_slist_reverse(list);
--}
--
--/**
-- * Duplicate a TLV chain.
-- * This is pretty self explanatory.
-- *
-- * @param orig The TLV chain you want to make a copy of.
-- * @return A newly allocated TLV chain.
-- */
--GSList *aim_tlvlist_copy(GSList *orig)
--{
-- GSList *new = NULL;
-- aim_tlv_t *tlv;
--
-- while (orig != NULL) {
-- tlv = orig->data;
-- aim_tlvlist_add_raw(&new, tlv->type, tlv->length, tlv->value);
-- orig = orig->next;
-- }
--
-- return new;
--}
--
--/*
-- * Compare two TLV lists for equality. This probably is not the most
-- * efficient way to do this.
-- *
-- * @param one One of the TLV chains to compare.
-- * @param two The other TLV chain to compare.
-- * @return Return 0 if the lists are the same, return 1 if they are different.
-- */
--int aim_tlvlist_cmp(GSList *one, GSList *two)
--{
-- ByteStream bs1, bs2;
--
-- if (aim_tlvlist_size(one) != aim_tlvlist_size(two))
-- return 1;
--
-- byte_stream_new(&bs1, aim_tlvlist_size(one));
-- byte_stream_new(&bs2, aim_tlvlist_size(two));
--
-- aim_tlvlist_write(&bs1, &one);
-- aim_tlvlist_write(&bs2, &two);
--
-- if (memcmp(bs1.data, bs2.data, bs1.len)) {
-- byte_stream_destroy(&bs1);
-- byte_stream_destroy(&bs2);
-- return 1;
-- }
--
-- byte_stream_destroy(&bs1);
-- byte_stream_destroy(&bs2);
--
-- return 0;
--}
--
--/**
-- * Free a TLV chain structure
-- *
-- * Walks the list of TLVs in the passed TLV chain and
-- * frees each one. Note that any references to this data
-- * should be removed before calling this.
-- *
-- * @param list Chain to be freed
-- */
--void aim_tlvlist_free(GSList *list)
--{
-- while (list != NULL)
-- {
-- freetlv(list->data);
-- list = g_slist_delete_link(list, list);
-- }
--}
--
--/**
-- * Count the number of TLVs in a chain.
-- *
-- * @param list Chain to be counted.
-- * @return The number of TLVs stored in the passed chain.
-- */
--int aim_tlvlist_count(GSList *list)
--{
-- GSList *cur;
-- int count;
--
-- if (list == NULL)
-- return 0;
--
-- for (cur = list, count = 0; cur; cur = cur->next)
-- count++;
--
-- return count;
--}
--
--/**
-- * Count the number of bytes in a TLV chain.
-- *
-- * @param list Chain to be sized
-- * @return The number of bytes that would be needed to
-- * write the passed TLV chain to a data buffer.
-- */
--int aim_tlvlist_size(GSList *list)
--{
-- GSList *cur;
-- int size;
--
-- if (list == NULL)
-- return 0;
--
-- for (cur = list, size = 0; cur; cur = cur->next)
-- size += (4 + ((aim_tlv_t *)cur->data)->length);
--
-- return size;
--}
--
--/**
-- * Adds the passed string as a TLV element of the passed type
-- * to the TLV chain.
-- *
-- * @param list Desination chain (%NULL pointer if empty).
-- * @param type TLV type.
-- * @param length Length of string to add (not including %NULL).
-- * @param value String to add.
-- * @return The size of the value added.
-- */
--int aim_tlvlist_add_raw(GSList **list, const guint16 type, const guint16 length, const guint8 *value)
--{
-- aim_tlv_t *tlv;
--
-- if (list == NULL)
-- return 0;
--
-- tlv = createtlv(type, length, NULL);
-- if (tlv->length > 0)
-- tlv->value = g_memdup(value, length);
--
-- *list = g_slist_append(*list, tlv);
--
-- return tlv->length;
--}
--
--/**
-- * Add a one byte integer to a TLV chain.
-- *
-- * @param list Destination chain.
-- * @param type TLV type to add.
-- * @param value Value to add.
-- * @return The size of the value added.
-- */
--int aim_tlvlist_add_8(GSList **list, const guint16 type, const guint8 value)
--{
-- guint8 v8[1];
--
-- aimutil_put8(v8, value);
--
-- return aim_tlvlist_add_raw(list, type, 1, v8);
--}
--
--/**
-- * Add a two byte integer to a TLV chain.
-- *
-- * @param list Destination chain.
-- * @param type TLV type to add.
-- * @param value Value to add.
-- * @return The size of the value added.
-- */
--int aim_tlvlist_add_16(GSList **list, const guint16 type, const guint16 value)
--{
-- guint8 v16[2];
--
-- aimutil_put16(v16, value);
--
-- return aim_tlvlist_add_raw(list, type, 2, v16);
--}
--
--/**
-- * Add a four byte integer to a TLV chain.
-- *
-- * @param list Destination chain.
-- * @param type TLV type to add.
-- * @param value Value to add.
-- * @return The size of the value added.
-- */
--int aim_tlvlist_add_32(GSList **list, const guint16 type, const guint32 value)
--{
-- guint8 v32[4];
--
-- aimutil_put32(v32, value);
--
-- return aim_tlvlist_add_raw(list, type, 4, v32);
--}
--
--/**
-- * Add a string to a TLV chain.
-- *
-- * @param list Destination chain.
-- * @param type TLV type to add.
-- * @param value Value to add.
-- * @return The size of the value added.
-- */
--int aim_tlvlist_add_str(GSList **list, const guint16 type, const char *value)
--{
-- return aim_tlvlist_add_raw(list, type, strlen(value), (guint8 *)value);
--}
--
--static int
--count_caps(guint64 caps)
--{
-- int set_bits = 0;
-- while (caps) {
-- set_bits += caps & 1;
-- caps >>= 1;
-- }
-- return set_bits;
--}
--
--/**
-- * Adds a block of capability blocks to a TLV chain. The bitfield
-- * passed in should be a bitwise %OR of any of the %AIM_CAPS constants:
-- *
-- * %OSCAR_CAPABILITY_BUDDYICON Supports Buddy Icons
-- * %OSCAR_CAPABILITY_TALK Supports Voice Chat
-- * %OSCAR_CAPABILITY_IMIMAGE Supports DirectIM/IMImage
-- * %OSCAR_CAPABILITY_CHAT Supports Chat
-- * %OSCAR_CAPABILITY_GETFILE Supports Get File functions
-- * %OSCAR_CAPABILITY_SENDFILE Supports Send File functions
-- *
-- * @param list Destination chain
-- * @param type TLV type to add
-- * @param caps Bitfield of capability flags to send
-- * @return The size of the value added.
-- */
--int aim_tlvlist_add_caps(GSList **list, const guint16 type, const guint64 caps, const char *mood)
--{
-- int len;
-- ByteStream bs;
-- guint32 bs_size;
-- guint8 *data;
--
-- if (caps == 0)
-- return 0; /* nothing there anyway */
--
-- data = icq_get_custom_icon_data(mood);
-- bs_size = 16*(count_caps(caps) + (data != NULL ? 1 : 0));
--
-- byte_stream_new(&bs, bs_size);
-- byte_stream_putcaps(&bs, caps);
--
-- /* adding of custom icon GUID */
-- if (data != NULL)
-- byte_stream_putraw(&bs, data, 16);
--
-- len = aim_tlvlist_add_raw(list, type, byte_stream_curpos(&bs), bs.data);
--
-- byte_stream_destroy(&bs);
--
-- return len;
--}
--
--/**
-- * Adds the given chatroom info to a TLV chain.
-- *
-- * @param list Destination chain.
-- * @param type TLV type to add.
-- * @param roomname The name of the chat.
-- * @param instance The instance.
-- * @return The size of the value added.
-- */
--int aim_tlvlist_add_chatroom(GSList **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance)
--{
-- int len;
-- ByteStream bs;
--
-- byte_stream_new(&bs, 2 + 1 + strlen(roomname) + 2);
--
-- byte_stream_put16(&bs, exchange);
-- byte_stream_put8(&bs, strlen(roomname));
-- byte_stream_putstr(&bs, roomname);
-- byte_stream_put16(&bs, instance);
--
-- len = aim_tlvlist_add_raw(list, type, byte_stream_curpos(&bs), bs.data);
--
-- byte_stream_destroy(&bs);
--
-- return len;
--}
--
--/**
-- * Adds a TLV with a zero length to a TLV chain.
-- *
-- * @param list Destination chain.
-- * @param type TLV type to add.
-- * @return The size of the value added.
-- */
--int aim_tlvlist_add_noval(GSList **list, const guint16 type)
--{
-- return aim_tlvlist_add_raw(list, type, 0, NULL);
--}
--
--/*
-- * Note that the inner TLV chain will not be modifiable as a tlvchain once
-- * it is written using this. Or rather, it can be, but updates won't be
-- * made to this.
-- *
-- * TODO: Should probably support sublists for real.
-- *
-- * This is so neat.
-- *
-- * @param list Destination chain.
-- * @param type TLV type to add.
-- * @param t1 The TLV chain you want to write.
-- * @return The number of bytes written to the destination TLV chain.
-- * 0 is returned if there was an error or if the destination
-- * TLV chain has length 0.
-- */
--int aim_tlvlist_add_frozentlvlist(GSList **list, guint16 type, GSList **tlvlist)
--{
-- int buflen;
-- ByteStream bs;
--
-- buflen = aim_tlvlist_size(*tlvlist);
--
-- if (buflen <= 0)
-- return 0;
--
-- byte_stream_new(&bs, buflen);
--
-- aim_tlvlist_write(&bs, tlvlist);
--
-- aim_tlvlist_add_raw(list, type, byte_stream_curpos(&bs), bs.data);
--
-- byte_stream_destroy(&bs);
--
-- return buflen;
--}
--
--/**
-- * Substitute a TLV of a given type with a new TLV of the same type. If
-- * you attempt to replace a TLV that does not exist, this function will
-- * just add a new TLV as if you called aim_tlvlist_add_raw().
-- *
-- * @param list Desination chain (%NULL pointer if empty).
-- * @param type TLV type.
-- * @param length Length of string to add (not including %NULL).
-- * @param value String to add.
-- * @return The length of the TLV.
-- */
--int aim_tlvlist_replace_raw(GSList **list, const guint16 type, const guint16 length, const guint8 *value)
--{
-- GSList *cur;
-- aim_tlv_t *tlv;
--
-- if (list == NULL)
-- return 0;
--
-- for (cur = *list; cur != NULL; cur = cur->next)
-- {
-- tlv = cur->data;
-- if (tlv->type == type)
-- break;
-- }
--
-- if (cur == NULL)
-- /* TLV does not exist, so add a new one */
-- return aim_tlvlist_add_raw(list, type, length, value);
--
-- g_free(tlv->value);
-- tlv->length = length;
-- if (tlv->length > 0) {
-- tlv->value = g_memdup(value, length);
-- } else
-- tlv->value = NULL;
--
-- return tlv->length;
--}
--
--/**
-- * Substitute a TLV of a given type with a new TLV of the same type. If
-- * you attempt to replace a TLV that does not exist, this function will
-- * just add a new TLV as if you called aim_tlvlist_add_str().
-- *
-- * @param list Desination chain (%NULL pointer if empty).
-- * @param type TLV type.
-- * @param str String to add.
-- * @return The length of the TLV.
-- */
--int aim_tlvlist_replace_str(GSList **list, const guint16 type, const char *str)
--{
-- return aim_tlvlist_replace_raw(list, type, strlen(str), (const guchar *)str);
--}
--
--/**
-- * Substitute a TLV of a given type with a new TLV of the same type. If
-- * you attempt to replace a TLV that does not exist, this function will
-- * just add a new TLV as if you called aim_tlvlist_add_raw().
-- *
-- * @param list Desination chain (%NULL pointer if empty).
-- * @param type TLV type.
-- * @return The length of the TLV.
-- */
--int aim_tlvlist_replace_noval(GSList **list, const guint16 type)
--{
-- return aim_tlvlist_replace_raw(list, type, 0, NULL);
--}
--
--/**
-- * Substitute a TLV of a given type with a new TLV of the same type. If
-- * you attempt to replace a TLV that does not exist, this function will
-- * just add a new TLV as if you called aim_tlvlist_add_raw().
-- *
-- * @param list Desination chain (%NULL pointer if empty).
-- * @param type TLV type.
-- * @param value 8 bit value to add.
-- * @return The length of the TLV.
-- */
--int aim_tlvlist_replace_8(GSList **list, const guint16 type, const guint8 value)
--{
-- guint8 v8[1];
--
-- aimutil_put8(v8, value);
--
-- return aim_tlvlist_replace_raw(list, type, 1, v8);
--}
--
--/**
-- * Substitute a TLV of a given type with a new TLV of the same type. If
-- * you attempt to replace a TLV that does not exist, this function will
-- * just add a new TLV as if you called aim_tlvlist_add_raw().
-- *
-- * @param list Desination chain (%NULL pointer if empty).
-- * @param type TLV type.
-- * @param value 32 bit value to add.
-- * @return The length of the TLV.
-- */
--int aim_tlvlist_replace_32(GSList **list, const guint16 type, const guint32 value)
--{
-- guint8 v32[4];
--
-- aimutil_put32(v32, value);
--
-- return aim_tlvlist_replace_raw(list, type, 4, v32);
--}
--
--/**
-- * Remove all TLVs of a given type. If you attempt to remove a TLV
-- * that does not exist, nothing happens.
-- *
-- * @param list Desination chain (%NULL pointer if empty).
-- * @param type TLV type.
-- */
--void aim_tlvlist_remove(GSList **list, const guint16 type)
--{
-- GSList *cur, *next;
-- aim_tlv_t *tlv;
--
-- if (list == NULL || *list == NULL)
-- return;
--
-- cur = *list;
-- while (cur != NULL)
-- {
-- tlv = cur->data;
-- next = cur->next;
--
-- if (tlv->type == type)
-- {
-- /* Delete this TLV */
-- *list = g_slist_delete_link(*list, cur);
-- g_free(tlv->value);
-- g_free(tlv);
-- }
--
-- cur = next;
-- }
--}
--
--/**
-- * Write a TLV chain into a data buffer.
-- *
-- * Copies a TLV chain into a raw data buffer, writing only the number
-- * of bytes specified. This operation does not free the chain;
-- * aim_tlvlist_free() must still be called to free up the memory used
-- * by the chain structures.
-- *
-- * TODO: Clean this up, make better use of bstreams
-- *
-- * @param bs Input bstream
-- * @param list Source TLV chain
-- * @return Return 0 if the destination bstream is too small.
-- */
--int aim_tlvlist_write(ByteStream *bs, GSList **list)
--{
-- int goodbuflen;
-- GSList *cur;
-- aim_tlv_t *tlv;
--
-- /* do an initial run to test total length */
-- goodbuflen = aim_tlvlist_size(*list);
--
-- if (goodbuflen > byte_stream_bytes_left(bs))
-- return 0; /* not enough buffer */
--
-- /* do the real write-out */
-- for (cur = *list; cur; cur = cur->next) {
-- tlv = cur->data;
-- byte_stream_put16(bs, tlv->type);
-- byte_stream_put16(bs, tlv->length);
-- if (tlv->length > 0)
-- byte_stream_putraw(bs, tlv->value, tlv->length);
-- }
--
-- return 1; /* TODO: This is a nonsensical return */
--}
--
--
--/**
-- * Grab the Nth TLV of type type in the TLV list list.
-- *
-- * Returns a pointer to an aim_tlv_t of the specified type;
-- * %NULL on error. The @nth parameter is specified starting at %1.
-- * In most cases, there will be no more than one TLV of any type
-- * in a chain.
-- *
-- * @param list Source chain.
-- * @param type Requested TLV type.
-- * @param nth Index of TLV of type to get.
-- * @return The TLV you were looking for, or NULL if one could not be found.
-- */
--aim_tlv_t *aim_tlv_gettlv(GSList *list, const guint16 type, const int nth)
--{
-- GSList *cur;
-- aim_tlv_t *tlv;
-- int i;
--
-- for (cur = list, i = 0; cur != NULL; cur = cur->next) {
-- tlv = cur->data;
-- if (tlv->type == type)
-- i++;
-- if (i >= nth)
-- return tlv;
-- }
--
-- return NULL;
--}
--
--/**
-- * Get the length of the data of the nth TLV in the given TLV chain.
-- *
-- * @param list Source chain.
-- * @param type Requested TLV type.
-- * @param nth Index of TLV of type to get.
-- * @return The length of the data in this TLV, or -1 if the TLV could not be
-- * found. Unless -1 is returned, this value will be 2 bytes.
-- */
--int aim_tlv_getlength(GSList *list, const guint16 type, const int nth)
--{
-- aim_tlv_t *tlv;
--
-- tlv = aim_tlv_gettlv(list, type, nth);
-- if (tlv == NULL)
-- return -1;
--
-- return tlv->length;
--}
--
--char *
--aim_tlv_getvalue_as_string(aim_tlv_t *tlv)
--{
-- char *ret;
--
-- ret = g_malloc(tlv->length + 1);
-- memcpy(ret, tlv->value, tlv->length);
-- ret[tlv->length] = '\0';
--
-- return ret;
--}
--
--/**
-- * Retrieve the data from the nth TLV in the given TLV chain as a string.
-- *
-- * @param list Source TLV chain.
-- * @param type TLV type to search for.
-- * @param nth Index of TLV to return.
-- * @return The value of the TLV you were looking for, or NULL if one could
-- * not be found. This is a dynamic buffer and must be freed by the
-- * caller.
-- */
--char *aim_tlv_getstr(GSList *list, const guint16 type, const int nth)
--{
-- aim_tlv_t *tlv;
--
-- tlv = aim_tlv_gettlv(list, type, nth);
-- if (tlv == NULL)
-- return NULL;
--
-- return aim_tlv_getvalue_as_string(tlv);
--}
--
--/**
-- * Retrieve the data from the nth TLV in the given TLV chain as an 8bit
-- * integer.
-- *
-- * @param list Source TLV chain.
-- * @param type TLV type to search for.
-- * @param nth Index of TLV to return.
-- * @return The value the TLV you were looking for, or 0 if one could
-- * not be found.
-- */
--guint8 aim_tlv_get8(GSList *list, const guint16 type, const int nth)
--{
-- aim_tlv_t *tlv;
--
-- tlv = aim_tlv_gettlv(list, type, nth);
-- if (tlv == NULL)
-- return 0; /* erm */
--
-- return aimutil_get8(tlv->value);
--}
--
--/**
-- * Retrieve the data from the nth TLV in the given TLV chain as a 16bit
-- * integer.
-- *
-- * @param list Source TLV chain.
-- * @param type TLV type to search for.
-- * @param nth Index of TLV to return.
-- * @return The value the TLV you were looking for, or 0 if one could
-- * not be found.
-- */
--guint16 aim_tlv_get16(GSList *list, const guint16 type, const int nth)
--{
-- aim_tlv_t *tlv;
--
-- tlv = aim_tlv_gettlv(list, type, nth);
-- if (tlv == NULL)
-- return 0; /* erm */
--
-- return aimutil_get16(tlv->value);
--}
--
--/**
-- * Retrieve the data from the nth TLV in the given TLV chain as a 32bit
-- * integer.
-- *
-- * @param list Source TLV chain.
-- * @param type TLV type to search for.
-- * @param nth Index of TLV to return.
-- * @return The value the TLV you were looking for, or 0 if one could
-- * not be found.
-- */
--guint32 aim_tlv_get32(GSList *list, const guint16 type, const int nth)
--{
-- aim_tlv_t *tlv;
--
-- tlv = aim_tlv_gettlv(list, type, nth);
-- if (tlv == NULL)
-- return 0; /* erm */
--
-- return aimutil_get32(tlv->value);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/userinfo.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/userinfo.c
---- pidgin-2.10.7/libpurple/protocols/oscar/userinfo.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/userinfo.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,550 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * Displaying various information about buddies.
-- */
--
--#include "encoding.h"
--#include "oscar.h"
--
--static gchar *
--oscar_caps_to_string(guint64 caps)
--{
-- GString *str;
-- const gchar *tmp;
-- guint64 bit = 1;
--
-- str = g_string_new("");
--
-- if (!caps) {
-- return NULL;
-- } else while (bit <= OSCAR_CAPABILITY_LAST) {
-- if (bit & caps) {
-- switch (bit) {
-- case OSCAR_CAPABILITY_BUDDYICON:
-- tmp = _("Buddy Icon");
-- break;
-- case OSCAR_CAPABILITY_TALK:
-- tmp = _("Voice");
-- break;
-- case OSCAR_CAPABILITY_DIRECTIM:
-- tmp = _("AIM Direct IM");
-- break;
-- case OSCAR_CAPABILITY_CHAT:
-- tmp = _("Chat");
-- break;
-- case OSCAR_CAPABILITY_GETFILE:
-- tmp = _("Get File");
-- break;
-- case OSCAR_CAPABILITY_SENDFILE:
-- tmp = _("Send File");
-- break;
-- case OSCAR_CAPABILITY_GAMES:
-- case OSCAR_CAPABILITY_GAMES2:
-- tmp = _("Games");
-- break;
-- case OSCAR_CAPABILITY_XTRAZ:
-- case OSCAR_CAPABILITY_NEWCAPS:
-- tmp = _("ICQ Xtraz");
-- break;
-- case OSCAR_CAPABILITY_ADDINS:
-- tmp = _("Add-Ins");
-- break;
-- case OSCAR_CAPABILITY_SENDBUDDYLIST:
-- tmp = _("Send Buddy List");
-- break;
-- case OSCAR_CAPABILITY_ICQ_DIRECT:
-- tmp = _("ICQ Direct Connect");
-- break;
-- case OSCAR_CAPABILITY_APINFO:
-- tmp = _("AP User");
-- break;
-- case OSCAR_CAPABILITY_ICQRTF:
-- tmp = _("ICQ RTF");
-- break;
-- case OSCAR_CAPABILITY_EMPTY:
-- tmp = _("Nihilist");
-- break;
-- case OSCAR_CAPABILITY_ICQSERVERRELAY:
-- tmp = _("ICQ Server Relay");
-- break;
-- case OSCAR_CAPABILITY_UNICODEOLD:
-- tmp = _("Old ICQ UTF8");
-- break;
-- case OSCAR_CAPABILITY_TRILLIANCRYPT:
-- tmp = _("Trillian Encryption");
-- break;
-- case OSCAR_CAPABILITY_UNICODE:
-- tmp = _("ICQ UTF8");
-- break;
-- case OSCAR_CAPABILITY_HIPTOP:
-- tmp = _("Hiptop");
-- break;
-- case OSCAR_CAPABILITY_SECUREIM:
-- tmp = _("Security Enabled");
-- break;
-- case OSCAR_CAPABILITY_VIDEO:
-- tmp = _("Video Chat");
-- break;
-- /* Not actually sure about this one... WinAIM doesn't show anything */
-- case OSCAR_CAPABILITY_ICHATAV:
-- tmp = _("iChat AV");
-- break;
-- case OSCAR_CAPABILITY_LIVEVIDEO:
-- tmp = _("Live Video");
-- break;
-- case OSCAR_CAPABILITY_CAMERA:
-- tmp = _("Camera");
-- break;
-- case OSCAR_CAPABILITY_ICHAT_SCREENSHARE:
-- tmp = _("Screen Sharing");
-- break;
-- default:
-- tmp = NULL;
-- break;
-- }
-- if (tmp)
-- g_string_append_printf(str, "%s%s", (*(str->str) == '\0' ? "" : ", "), tmp);
-- }
-- bit <<= 1;
-- }
--
-- return g_string_free(str, FALSE);
--}
--
--static void
--oscar_user_info_add_pair(PurpleNotifyUserInfo *user_info, const char *name, const char *value)
--{
-- if (value && value[0]) {
-- purple_notify_user_info_add_pair(user_info, name, value);
-- }
--}
--
--static void
--oscar_user_info_convert_and_add(PurpleAccount *account, OscarData *od, PurpleNotifyUserInfo *user_info,
-- const char *name, const char *value)
--{
-- gchar *utf8;
--
-- if (value && value[0] && (utf8 = oscar_utf8_try_convert(account, od, value))) {
-- purple_notify_user_info_add_pair(user_info, name, utf8);
-- g_free(utf8);
-- }
--}
--
--static void
--oscar_user_info_convert_and_add_hyperlink(PurpleAccount *account, OscarData *od, PurpleNotifyUserInfo *user_info,
-- const char *name, const char *value, const char *url_prefix)
--{
-- gchar *utf8;
--
-- if (value && value[0] && (utf8 = oscar_utf8_try_convert(account, od, value))) {
-- gchar *tmp = g_strdup_printf("<a href=\"%s%s\">%s</a>", url_prefix, utf8, utf8);
-- purple_notify_user_info_add_pair(user_info, name, tmp);
-- g_free(utf8);
-- g_free(tmp);
-- }
--}
--
--/**
-- * @brief Append the status information to a user_info struct
-- *
-- * The returned information is HTML-ready, appropriately escaped, as all information in a user_info struct should be HTML.
-- *
-- * @param gc The PurpleConnection
-- * @param user_info A PurpleNotifyUserInfo object to which status information will be added
-- * @param b The PurpleBuddy whose status is desired. This or the aim_userinfo_t (or both) must be passed to oscar_user_info_append_status().
-- * @param userinfo The aim_userinfo_t of the buddy whose status is desired. This or the PurpleBuddy (or both) must be passed to oscar_user_info_append_status().
-- * @param use_html_status If TRUE, prefer HTML-formatted away message over plaintext available message.
-- */
--void
--oscar_user_info_append_status(PurpleConnection *gc, PurpleNotifyUserInfo *user_info, PurpleBuddy *b, aim_userinfo_t *userinfo, gboolean use_html_status)
--{
-- PurpleAccount *account = purple_connection_get_account(gc);
-- OscarData *od;
-- PurplePresence *presence = NULL;
-- PurpleStatus *status = NULL;
-- gchar *message = NULL, *itmsurl = NULL, *tmp;
-- gboolean escaping_needed = TRUE;
--
-- od = purple_connection_get_protocol_data(gc);
--
-- if (b == NULL && userinfo == NULL)
-- return;
--
-- if (b == NULL)
-- b = purple_find_buddy(purple_connection_get_account(gc), userinfo->bn);
-- else
-- userinfo = aim_locate_finduserinfo(od, purple_buddy_get_name(b));
--
-- if (b) {
-- presence = purple_buddy_get_presence(b);
-- status = purple_presence_get_active_status(presence);
-- }
--
-- /* If we have both b and userinfo we favor userinfo, because if we're
-- viewing someone's profile then we want the HTML away message, and
-- the "message" attribute of the status contains only the plaintext
-- message. */
-- if (userinfo) {
-- if ((userinfo->flags & AIM_FLAG_AWAY) && use_html_status && userinfo->away_len > 0 && userinfo->away != NULL && userinfo->away_encoding != NULL) {
-- /* Away message */
-- message = oscar_encoding_to_utf8(userinfo->away_encoding, userinfo->away, userinfo->away_len);
-- escaping_needed = FALSE;
-- } else {
-- /*
-- * Available message or non-HTML away message (because that's
-- * all we have right now.
-- */
-- if ((userinfo->status != NULL) && userinfo->status[0] != '\0') {
-- message = oscar_encoding_to_utf8(userinfo->status_encoding, userinfo->status, userinfo->status_len);
-- }
--#if defined (_WIN32) || defined (__APPLE__)
-- if (userinfo->itmsurl && (userinfo->itmsurl[0] != '\0')) {
-- itmsurl = oscar_encoding_to_utf8(userinfo->itmsurl_encoding, userinfo->itmsurl, userinfo->itmsurl_len);
-- }
--#endif
-- }
-- } else {
-- message = g_strdup(purple_status_get_attr_string(status, "message"));
-- itmsurl = g_strdup(purple_status_get_attr_string(status, "itmsurl"));
-- }
--
-- if (message) {
-- tmp = oscar_util_format_string(message, purple_account_get_username(account));
-- g_free(message);
-- message = tmp;
-- if (escaping_needed) {
-- tmp = purple_markup_escape_text(message, -1);
-- g_free(message);
-- message = tmp;
-- }
-- }
--
-- if (use_html_status && itmsurl) {
-- tmp = g_strdup_printf("<a href=\"%s\">%s</a>", itmsurl, message);
-- g_free(message);
-- message = tmp;
-- }
--
-- if (b) {
-- if (purple_presence_is_online(presence)) {
-- gboolean is_away = ((status && !purple_status_is_available(status)) || (userinfo && (userinfo->flags & AIM_FLAG_AWAY)));
-- if (oscar_util_valid_name_icq(purple_buddy_get_name(b)) || is_away || !message || !(*message)) {
-- /* Append the status name for online ICQ statuses, away AIM statuses, and for all buddies with no message.
-- * If the status name and the message are the same, only show one. */
-- const char *status_name = purple_status_get_name(status);
-- if (status_name && message && !strcmp(status_name, message))
-- status_name = NULL;
--
-- tmp = g_strdup_printf("%s%s%s",
-- status_name ? status_name : "",
-- ((status_name && message) && *message) ? ": " : "",
-- (message && *message) ? message : "");
-- g_free(message);
-- message = tmp;
-- }
--
-- } else if (aim_ssi_waitingforauth(od->ssi.local,
-- aim_ssi_itemlist_findparentname(od->ssi.local, purple_buddy_get_name(b)),
-- purple_buddy_get_name(b)))
-- {
-- /* Note if an offline buddy is not authorized */
-- tmp = g_strdup_printf("%s%s%s",
-- _("Not Authorized"),
-- (message && *message) ? ": " : "",
-- (message && *message) ? message : "");
-- g_free(message);
-- message = tmp;
-- } else {
-- g_free(message);
-- message = g_strdup(_("Offline"));
-- }
-- }
--
-- if (presence) {
-- const char *mood;
-- const char *comment;
-- char *description;
-- status = purple_presence_get_status(presence, "mood");
-- mood = icq_get_custom_icon_description(purple_status_get_attr_string(status, PURPLE_MOOD_NAME));
-- if (mood) {
-- comment = purple_status_get_attr_string(status, PURPLE_MOOD_COMMENT);
-- if (comment) {
-- char *escaped_comment = purple_markup_escape_text(comment, -1);
-- description = g_strdup_printf("%s (%s)", _(mood), escaped_comment);
-- g_free(escaped_comment);
-- } else {
-- description = g_strdup(_(mood));
-- }
-- purple_notify_user_info_add_pair(user_info, _("Mood"), description);
-- g_free(description);
-- }
-- }
--
-- purple_notify_user_info_add_pair(user_info, _("Status"), message);
-- g_free(message);
--}
--
--void
--oscar_user_info_append_extra_info(PurpleConnection *gc, PurpleNotifyUserInfo *user_info, PurpleBuddy *b, aim_userinfo_t *userinfo)
--{
-- OscarData *od;
-- PurpleAccount *account;
-- PurplePresence *presence = NULL;
-- PurpleStatus *status = NULL;
-- PurpleGroup *g = NULL;
-- struct buddyinfo *bi = NULL;
-- char *tmp;
-- const char *bname = NULL, *gname = NULL;
--
-- od = purple_connection_get_protocol_data(gc);
-- account = purple_connection_get_account(gc);
--
-- if ((user_info == NULL) || ((b == NULL) && (userinfo == NULL)))
-- return;
--
-- if (userinfo == NULL)
-- userinfo = aim_locate_finduserinfo(od, purple_buddy_get_name(b));
--
-- if (b == NULL)
-- b = purple_find_buddy(account, userinfo->bn);
--
-- if (b != NULL) {
-- bname = purple_buddy_get_name(b);
-- g = purple_buddy_get_group(b);
-- gname = purple_group_get_name(g);
-- presence = purple_buddy_get_presence(b);
-- status = purple_presence_get_active_status(presence);
-- }
--
-- if (userinfo != NULL)
-- bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, userinfo->bn));
--
-- if ((bi != NULL) && (bi->ipaddr != 0)) {
-- tmp = g_strdup_printf("%hhu.%hhu.%hhu.%hhu",
-- (bi->ipaddr & 0xff000000) >> 24,
-- (bi->ipaddr & 0x00ff0000) >> 16,
-- (bi->ipaddr & 0x0000ff00) >> 8,
-- (bi->ipaddr & 0x000000ff));
-- oscar_user_info_add_pair(user_info, _("IP Address"), tmp);
-- g_free(tmp);
-- }
--
-- if ((userinfo != NULL) && (userinfo->warnlevel != 0)) {
-- tmp = g_strdup_printf("%d", (int)(userinfo->warnlevel/10.0 + .5));
-- oscar_user_info_add_pair(user_info, _("Warning Level"), tmp);
-- g_free(tmp);
-- }
--
-- if ((b != NULL) && (bname != NULL) && (g != NULL) && (gname != NULL)) {
-- tmp = aim_ssi_getcomment(od->ssi.local, gname, bname);
-- if (tmp != NULL) {
-- char *tmp2 = g_markup_escape_text(tmp, strlen(tmp));
-- g_free(tmp);
--
-- oscar_user_info_convert_and_add(account, od, user_info, _("Buddy Comment"), tmp2);
-- g_free(tmp2);
-- }
-- }
--}
--
--void
--oscar_user_info_display_error(OscarData *od, guint16 error_reason, gchar *buddy)
--{
-- PurpleNotifyUserInfo *user_info = purple_notify_user_info_new();
-- gchar *buf = g_strdup_printf(_("User information not available: %s"), oscar_get_msgerr_reason(error_reason));
-- purple_notify_user_info_add_pair(user_info, NULL, buf);
-- purple_notify_userinfo(od->gc, buddy, user_info, NULL, NULL);
-- purple_notify_user_info_destroy(user_info);
-- purple_conv_present_error(buddy, purple_connection_get_account(od->gc), buf);
-- g_free(buf);
--}
--
--void
--oscar_user_info_display_icq(OscarData *od, struct aim_icq_info *info)
--{
-- PurpleConnection *gc = od->gc;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- PurpleBuddy *buddy;
-- struct buddyinfo *bi;
-- gchar who[16];
-- PurpleNotifyUserInfo *user_info;
-- const gchar *alias;
--
-- if (!info->uin)
-- return;
--
-- user_info = purple_notify_user_info_new();
--
-- g_snprintf(who, sizeof(who), "%u", info->uin);
-- buddy = purple_find_buddy(account, who);
-- if (buddy != NULL)
-- bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, purple_buddy_get_name(buddy)));
-- else
-- bi = NULL;
--
-- purple_notify_user_info_add_pair(user_info, _("UIN"), who);
-- oscar_user_info_convert_and_add(account, od, user_info, _("Nick"), info->nick);
-- if ((bi != NULL) && (bi->ipaddr != 0)) {
-- char *tstr = g_strdup_printf("%hhu.%hhu.%hhu.%hhu",
-- (bi->ipaddr & 0xff000000) >> 24,
-- (bi->ipaddr & 0x00ff0000) >> 16,
-- (bi->ipaddr & 0x0000ff00) >> 8,
-- (bi->ipaddr & 0x000000ff));
-- purple_notify_user_info_add_pair(user_info, _("IP Address"), tstr);
-- g_free(tstr);
-- }
-- oscar_user_info_convert_and_add(account, od, user_info, _("First Name"), info->first);
-- oscar_user_info_convert_and_add(account, od, user_info, _("Last Name"), info->last);
-- oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Email Address"), info->email, "mailto:");
-- if (info->numaddresses && info->email2) {
-- int i;
-- for (i = 0; i < info->numaddresses; i++) {
-- oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Email Address"), info->email2[i], "mailto:");
-- }
-- }
-- oscar_user_info_convert_and_add(account, od, user_info, _("Mobile Phone"), info->mobile);
--
-- if (info->gender != 0)
-- purple_notify_user_info_add_pair(user_info, _("Gender"), (info->gender == 1 ? _("Female") : _("Male")));
--
-- if ((info->birthyear > 1900) && (info->birthmonth > 0) && (info->birthday > 0)) {
-- /* Initialize the struct properly or strftime() will crash
-- * under some conditions (e.g. Debian sarge w/ LANG=en_HK). */
-- time_t t = time(NULL);
-- struct tm *tm = localtime(&t);
--
-- tm->tm_mday = (int)info->birthday;
-- tm->tm_mon = (int)info->birthmonth - 1;
-- tm->tm_year = (int)info->birthyear - 1900;
--
-- /* Ignore dst setting of today to avoid timezone shift between
-- * dates in summer and winter time. */
-- tm->tm_isdst = -1;
--
-- /* To be 100% sure that the fields are re-normalized.
-- * If you're sure strftime() ALWAYS does this EVERYWHERE,
-- * feel free to remove it. --rlaager */
-- mktime(tm);
--
-- oscar_user_info_convert_and_add(account, od, user_info, _("Birthday"), purple_date_format_short(tm));
-- }
-- if ((info->age > 0) && (info->age < 255)) {
-- char age[5];
-- snprintf(age, sizeof(age), "%hhd", info->age);
-- purple_notify_user_info_add_pair(user_info, _("Age"), age);
-- }
-- oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Personal Web Page"), info->email, "");
-- if (buddy != NULL)
-- oscar_user_info_append_status(gc, user_info, buddy, /* aim_userinfo_t */ NULL, /* use_html_status */ TRUE);
--
-- oscar_user_info_convert_and_add(account, od, user_info, _("Additional Information"), info->info);
-- purple_notify_user_info_add_section_break(user_info);
--
-- if ((info->homeaddr && (info->homeaddr[0])) || (info->homecity && info->homecity[0]) || (info->homestate && info->homestate[0]) || (info->homezip && info->homezip[0])) {
-- purple_notify_user_info_add_section_header(user_info, _("Home Address"));
--
-- oscar_user_info_convert_and_add(account, od, user_info, _("Address"), info->homeaddr);
-- oscar_user_info_convert_and_add(account, od, user_info, _("City"), info->homecity);
-- oscar_user_info_convert_and_add(account, od, user_info, _("State"), info->homestate);
-- oscar_user_info_convert_and_add(account, od, user_info, _("Zip Code"), info->homezip);
-- }
-- if ((info->workaddr && info->workaddr[0]) || (info->workcity && info->workcity[0]) || (info->workstate && info->workstate[0]) || (info->workzip && info->workzip[0])) {
-- purple_notify_user_info_add_section_header(user_info, _("Work Address"));
--
-- oscar_user_info_convert_and_add(account, od, user_info, _("Address"), info->workaddr);
-- oscar_user_info_convert_and_add(account, od, user_info, _("City"), info->workcity);
-- oscar_user_info_convert_and_add(account, od, user_info, _("State"), info->workstate);
-- oscar_user_info_convert_and_add(account, od, user_info, _("Zip Code"), info->workzip);
-- }
-- if ((info->workcompany && info->workcompany[0]) || (info->workdivision && info->workdivision[0]) || (info->workposition && info->workposition[0]) || (info->workwebpage && info->workwebpage[0])) {
-- purple_notify_user_info_add_section_header(user_info, _("Work Information"));
--
-- oscar_user_info_convert_and_add(account, od, user_info, _("Company"), info->workcompany);
-- oscar_user_info_convert_and_add(account, od, user_info, _("Division"), info->workdivision);
-- oscar_user_info_convert_and_add(account, od, user_info, _("Position"), info->workposition);
-- oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Web Page"), info->email, "");
-- }
--
-- if (buddy != NULL)
-- alias = purple_buddy_get_alias(buddy);
-- else
-- alias = who;
-- purple_notify_userinfo(gc, who, user_info, NULL, NULL);
-- purple_notify_user_info_destroy(user_info);
--}
--
--void
--oscar_user_info_display_aim(OscarData *od, aim_userinfo_t *userinfo)
--{
-- PurpleConnection *gc = od->gc;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- PurpleNotifyUserInfo *user_info = purple_notify_user_info_new();
-- gchar *tmp = NULL, *info_utf8 = NULL, *base_profile_url = NULL;
--
-- oscar_user_info_append_status(gc, user_info, /* PurpleBuddy */ NULL, userinfo, /* use_html_status */ TRUE);
--
-- if ((userinfo->present & AIM_USERINFO_PRESENT_IDLE) && userinfo->idletime != 0) {
-- tmp = purple_str_seconds_to_string(userinfo->idletime*60);
-- oscar_user_info_add_pair(user_info, _("Idle"), tmp);
-- g_free(tmp);
-- }
--
-- oscar_user_info_append_extra_info(gc, user_info, NULL, userinfo);
--
-- if ((userinfo->present & AIM_USERINFO_PRESENT_ONLINESINCE) && !oscar_util_valid_name_sms(userinfo->bn)) {
-- /* An SMS contact is always online; its Online Since value is not useful */
-- time_t t = userinfo->onlinesince;
-- oscar_user_info_add_pair(user_info, _("Online Since"), purple_date_format_full(localtime(&t)));
-- }
--
-- if (userinfo->present & AIM_USERINFO_PRESENT_MEMBERSINCE) {
-- time_t t = userinfo->membersince;
-- oscar_user_info_add_pair(user_info, _("Member Since"), purple_date_format_full(localtime(&t)));
-- }
--
-- if (userinfo->capabilities != 0) {
-- tmp = oscar_caps_to_string(userinfo->capabilities);
-- oscar_user_info_add_pair(user_info, _("Capabilities"), tmp);
-- g_free(tmp);
-- }
--
-- /* Info */
-- if ((userinfo->info_len > 0) && (userinfo->info != NULL) && (userinfo->info_encoding != NULL)) {
-- info_utf8 = oscar_encoding_to_utf8(userinfo->info_encoding, userinfo->info, userinfo->info_len);
-- tmp = oscar_util_format_string(info_utf8, purple_account_get_username(account));
-- purple_notify_user_info_add_section_break(user_info);
-- oscar_user_info_add_pair(user_info, _("Profile"), tmp);
-- g_free(tmp);
-- g_free(info_utf8);
-- }
--
-- purple_notify_user_info_add_section_break(user_info);
-- base_profile_url = oscar_util_valid_name_icq(userinfo->bn) ? "http://www.icq.com/people" : "http://profiles.aim.com";
-- tmp = g_strdup_printf("<a href=\"%s/%s\">%s</a>",
-- base_profile_url, purple_normalize(account, userinfo->bn), _("View web profile"));
-- purple_notify_user_info_add_pair(user_info, NULL, tmp);
-- g_free(tmp);
--
-- purple_notify_userinfo(gc, userinfo->bn, user_info, NULL, NULL);
-- purple_notify_user_info_destroy(user_info);
--}
-\ No newline at end of file
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/util.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/util.c
---- pidgin-2.10.7/libpurple/protocols/oscar/util.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/util.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,326 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--/*
-- * A little bit of this
-- * A little bit of that
-- * It started with a kiss
-- * Now we're up to bat
-- */
--
--#include "oscar.h"
--
--#include "core.h"
--
--#include <ctype.h>
--
--#ifdef _WIN32
--#include "win32dep.h"
--#endif
--
--static const char * const msgerrreason[] = {
-- N_("Invalid error"),
-- N_("Invalid SNAC"),
-- N_("Server rate limit exceeded"),
-- N_("Client rate limit exceeded"),
-- N_("Not logged in"),
-- N_("Service unavailable"),
-- N_("Service not defined"),
-- N_("Obsolete SNAC"),
-- N_("Not supported by host"),
-- N_("Not supported by client"),
-- N_("Refused by client"),
-- N_("Reply too big"),
-- N_("Responses lost"),
-- N_("Request denied"),
-- N_("Busted SNAC payload"),
-- N_("Insufficient rights"),
-- N_("In local permit/deny"),
-- N_("Warning level too high (sender)"),
-- N_("Warning level too high (receiver)"),
-- N_("User temporarily unavailable"),
-- N_("No match"),
-- N_("List overflow"),
-- N_("Request ambiguous"),
-- N_("Queue full"),
-- N_("Not while on AOL")
--};
--static const int msgerrreasonlen = G_N_ELEMENTS(msgerrreason);
--
--const char *oscar_get_msgerr_reason(size_t reason)
--{
-- return (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason");
--}
--
--int oscar_get_ui_info_int(const char *str, int default_value)
--{
-- GHashTable *ui_info;
--
-- ui_info = purple_core_get_ui_info();
-- if (ui_info != NULL) {
-- gpointer value;
-- if (g_hash_table_lookup_extended(ui_info, str, NULL, &value))
-- return GPOINTER_TO_INT(value);
-- }
--
-- return default_value;
--}
--
--const char *oscar_get_ui_info_string(const char *str, const char *default_value)
--{
-- GHashTable *ui_info;
-- const char *value = NULL;
--
-- ui_info = purple_core_get_ui_info();
-- if (ui_info != NULL)
-- value = g_hash_table_lookup(ui_info, str);
-- if (value == NULL)
-- value = default_value;
--
-- return value;
--}
--
--gchar *oscar_get_clientstring(void)
--{
-- const char *name, *version;
--
-- name = oscar_get_ui_info_string("name", "Purple");
-- version = oscar_get_ui_info_string("version", VERSION);
--
-- return g_strdup_printf("%s/%s", name, version);;
--}
--
--/**
-- * Calculate the checksum of a given icon.
-- */
--guint16
--aimutil_iconsum(const guint8 *buf, int buflen)
--{
-- guint32 sum;
-- int i;
--
-- for (i=0, sum=0; i+1<buflen; i+=2)
-- sum += (buf[i+1] << 8) + buf[i];
-- if (i < buflen)
-- sum += buf[i];
-- sum = ((sum & 0xffff0000) >> 16) + (sum & 0x0000ffff);
--
-- return sum;
--}
--
--/**
-- * Check if the given name is a valid AIM username.
-- * Example: BobDole
-- * Example: Henry_Ford@mac.com
-- * Example: 1KrazyKat@example.com
-- *
-- * @return TRUE if the name is valid, FALSE if not.
-- */
--static gboolean
--oscar_util_valid_name_aim(const char *name)
--{
-- int i;
--
-- if (purple_email_is_valid(name))
-- return TRUE;
--
-- /* Normal AIM usernames can't start with a number, period or underscore */
-- if (isalnum(name[0]) == 0)
-- return FALSE;
--
-- for (i = 0; name[i] != '\0'; i++) {
-- if (!isalnum(name[i]) && name[i] != ' ' && name[i] != '.' && name[i] != '_')
-- return FALSE;
-- }
--
-- return TRUE;
--}
--
--/**
-- * Check if the given name is a valid ICQ username.
-- * Example: 1234567
-- *
-- * @return TRUE if the name is valid, FALSE if not.
-- */
--gboolean
--oscar_util_valid_name_icq(const char *name)
--{
-- int i;
--
-- for (i = 0; name[i] != '\0'; i++) {
-- if (!isdigit(name[i]))
-- return FALSE;
-- }
--
-- return TRUE;
--}
--
--/**
-- * Check if the given name is a valid SMS username.
-- * Example: +19195551234
-- *
-- * @return TRUE if the name is valid, FALSE if not.
-- */
--gboolean
--oscar_util_valid_name_sms(const char *name)
--{
-- int i;
--
-- if (name[0] != '+')
-- return FALSE;
--
-- for (i = 1; name[i] != '\0'; i++) {
-- if (!isdigit(name[i]))
-- return FALSE;
-- }
--
-- return TRUE;
--}
--
--/**
-- * Check if the given name is a valid oscar username.
-- *
-- * @return TRUE if the name is valid, FALSE if not.
-- */
--gboolean
--oscar_util_valid_name(const char *name)
--{
-- if ((name == NULL) || (*name == '\0'))
-- return FALSE;
--
-- return oscar_util_valid_name_icq(name)
-- || oscar_util_valid_name_sms(name)
-- || oscar_util_valid_name_aim(name);
--}
--
--/**
-- * This takes two names and compares them using the rules
-- * on usernames for AIM/AOL. Mainly, this means case and space
-- * insensitivity (all case differences and spacing differences are
-- * ignored, with the exception that usernames can not start with
-- * a space).
-- *
-- * @return 0 if equal, non-0 if different
-- */
--/* TODO: Do something different for email addresses. */
--int
--oscar_util_name_compare(const char *name1, const char *name2)
--{
--
-- if ((name1 == NULL) || (name2 == NULL))
-- return -1;
--
-- do {
-- while (*name2 == ' ')
-- name2++;
-- while (*name1 == ' ')
-- name1++;
-- if (toupper(*name1) != toupper(*name2))
-- return 1;
-- } while ((*name1 != '\0') && name1++ && name2++);
--
-- return 0;
--}
--
--/**
-- * Looks for %n, %d, or %t in a string, and replaces them with the
-- * specified name, date, and time, respectively.
-- *
-- * @param str The string that may contain the special variables.
-- * @param name The sender name.
-- *
-- * @return A newly allocated string where the special variables are
-- * expanded. This should be g_free'd by the caller.
-- */
--gchar *
--oscar_util_format_string(const char *str, const char *name)
--{
-- char *c;
-- GString *cpy;
-- time_t t;
-- struct tm *tme;
--
-- g_return_val_if_fail(str != NULL, NULL);
-- g_return_val_if_fail(name != NULL, NULL);
--
-- /* Create an empty GString that is hopefully big enough for most messages */
-- cpy = g_string_sized_new(1024);
--
-- t = time(NULL);
-- tme = localtime(&t);
--
-- c = (char *)str;
-- while (*c) {
-- switch (*c) {
-- case '%':
-- if (*(c + 1)) {
-- switch (*(c + 1)) {
-- case 'n':
-- /* append name */
-- g_string_append(cpy, name);
-- c++;
-- break;
-- case 'd':
-- /* append date */
-- g_string_append(cpy, purple_date_format_short(tme));
-- c++;
-- break;
-- case 't':
-- /* append time */
-- g_string_append(cpy, purple_time_format(tme));
-- c++;
-- break;
-- default:
-- g_string_append_c(cpy, *c);
-- }
-- } else {
-- g_string_append_c(cpy, *c);
-- }
-- break;
-- default:
-- g_string_append_c(cpy, *c);
-- }
-- c++;
-- }
--
-- return g_string_free(cpy, FALSE);
--}
--
--gchar *
--oscar_format_buddies(GSList *buddies, const gchar *no_buddies_message)
--{
-- GSList *cur;
-- GString *result;
-- if (!buddies) {
-- return g_strdup_printf("<i>%s</i>", no_buddies_message);
-- }
-- result = g_string_new("");
-- for (cur = buddies; cur != NULL; cur = cur->next) {
-- PurpleBuddy *buddy = cur->data;
-- const gchar *bname = purple_buddy_get_name(buddy);
-- const gchar *alias = purple_buddy_get_alias_only(buddy);
-- g_string_append(result, bname);
-- if (alias) {
-- g_string_append_printf(result, " (%s)", alias);
-- }
-- g_string_append(result, "<br>");
-- }
-- return g_string_free(result, FALSE);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/visibility.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/visibility.c
---- pidgin-2.10.7/libpurple/protocols/oscar/visibility.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/visibility.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,140 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--#include "visibility.h"
--
--/* Translators: This string is a menu option that, if selected, will cause
-- you to appear online to the chosen user even when your status is set to
-- Invisible. */
--#define APPEAR_ONLINE N_("Appear Online")
--
--/* Translators: This string is a menu option that, if selected, will cause
-- you to appear offline to the chosen user when your status is set to
-- Invisible (this is the default). */
--#define DONT_APPEAR_ONLINE N_("Don't Appear Online")
--
--/* Translators: This string is a menu option that, if selected, will cause
-- you to always appear offline to the chosen user (even when your status
-- isn't Invisible). */
--#define APPEAR_OFFLINE N_("Appear Offline")
--
--/* Translators: This string is a menu option that, if selected, will cause
-- you to appear offline to the chosen user if you are invisible, and
-- appear online to the chosen user if you are not invisible (this is the
-- default). */
--#define DONT_APPEAR_OFFLINE N_("Don't Appear Offline")
--
--static guint16
--get_buddy_list_type(OscarData *od)
--{
-- PurpleAccount *account = purple_connection_get_account(od->gc);
-- return purple_account_is_status_active(account, OSCAR_STATUS_ID_INVISIBLE) ? AIM_SSI_TYPE_PERMIT : AIM_SSI_TYPE_DENY;
--}
--
--static gboolean
--is_buddy_on_list(OscarData *od, const char *bname)
--{
-- return aim_ssi_itemlist_finditem(od->ssi.local, NULL, bname, get_buddy_list_type(od)) != NULL;
--}
--
--static void
--visibility_cb(PurpleBlistNode *node, gpointer whatever)
--{
-- PurpleBuddy *buddy = PURPLE_BUDDY(node);
-- const char* bname = purple_buddy_get_name(buddy);
-- OscarData *od = purple_connection_get_protocol_data(purple_account_get_connection(purple_buddy_get_account(buddy)));
-- guint16 list_type = get_buddy_list_type(od);
--
-- if (!is_buddy_on_list(od, bname)) {
-- aim_ssi_add_to_private_list(od, bname, list_type);
-- } else {
-- aim_ssi_del_from_private_list(od, bname, list_type);
-- }
--}
--
--PurpleMenuAction *
--create_visibility_menu_item(OscarData *od, const char *bname)
--{
-- PurpleAccount *account = purple_connection_get_account(od->gc);
-- gboolean invisible = purple_account_is_status_active(account, OSCAR_STATUS_ID_INVISIBLE);
-- gboolean on_list = is_buddy_on_list(od, bname);
-- const gchar *label;
--
-- if (invisible) {
-- label = on_list ? _(DONT_APPEAR_ONLINE) : _(APPEAR_ONLINE);
-- } else {
-- label = on_list ? _(DONT_APPEAR_OFFLINE) : _(APPEAR_OFFLINE);
-- }
-- return purple_menu_action_new(label, PURPLE_CALLBACK(visibility_cb), NULL, NULL);
--}
--
--static void
--show_private_list(PurplePluginAction *action, guint16 list_type, const gchar *title, const gchar *list_description, const gchar *menu_action_name)
--{
-- PurpleConnection *gc = (PurpleConnection *) action->context;
-- OscarData *od = purple_connection_get_protocol_data(gc);
-- PurpleAccount *account = purple_connection_get_account(gc);
-- GSList *buddies, *filtered_buddies, *cur;
-- gchar *text, *secondary;
--
-- buddies = purple_find_buddies(account, NULL);
-- filtered_buddies = NULL;
-- for (cur = buddies; cur != NULL; cur = cur->next) {
-- PurpleBuddy *buddy;
-- const gchar *bname;
--
-- buddy = cur->data;
-- bname = purple_buddy_get_name(buddy);
-- if (aim_ssi_itemlist_finditem(od->ssi.local, NULL, bname, list_type)) {
-- filtered_buddies = g_slist_prepend(filtered_buddies, buddy);
-- }
-- }
--
-- g_slist_free(buddies);
--
-- filtered_buddies = g_slist_reverse(filtered_buddies);
-- text = oscar_format_buddies(filtered_buddies, _("you have no buddies on this list"));
-- g_slist_free(filtered_buddies);
--
-- secondary = g_strdup_printf(_("You can add a buddy to this list "
-- "by right-clicking on them and "
-- "selecting \"%s\""), menu_action_name);
-- purple_notify_formatted(gc, title, list_description, secondary, text, NULL, NULL);
-- g_free(secondary);
-- g_free(text);
--}
--
--void
--oscar_show_visible_list(PurplePluginAction *action)
--{
-- show_private_list(action, AIM_SSI_TYPE_PERMIT, _("Visible List"),
-- _("These buddies will see "
-- "your status when you switch "
-- "to \"Invisible\""),
-- _(APPEAR_ONLINE));
--}
--
--void
--oscar_show_invisible_list(PurplePluginAction *action)
--{
-- show_private_list(action, AIM_SSI_TYPE_DENY, _("Invisible List"),
-- _("These buddies will always see you as offline"),
-- _(APPEAR_OFFLINE));
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/visibility.h pidgin-2.10.7-nonprism/libpurple/protocols/oscar/visibility.h
---- pidgin-2.10.7/libpurple/protocols/oscar/visibility.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/visibility.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,32 +0,0 @@
--/*
-- * Purple's oscar protocol plugin
-- * This file is the legal property of its developers.
-- * Please see the AUTHORS file distributed alongside this file.
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
--*/
--
--#ifndef _VISIBILITY_H_
--#define _VISIBILITY_H_
--
--#include "oscar.h"
--#include "plugin.h"
--#include "util.h"
--
--PurpleMenuAction * create_visibility_menu_item(OscarData *od, const char *bname);
--void oscar_show_visible_list(PurplePluginAction *action);
--void oscar_show_invisible_list(PurplePluginAction *action);
--
--#endif
-\ No newline at end of file
-diff -Nur pidgin-2.10.7/libpurple/protocols/sametime/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/sametime/Makefile.am
---- pidgin-2.10.7/libpurple/protocols/sametime/Makefile.am 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/sametime/Makefile.am 1969-12-31 21:00:00.000000000 -0300
-@@ -1,37 +0,0 @@
--EXTRA_DIST = \
-- Makefile.mingw
--
--pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
--
--noinst_HEADERS = sametime.h
--
--SAMETIMESOURCES = sametime.c
--
--AM_CFLAGS = \
-- $(st)
--
--if STATIC_SAMETIME
--
--st = -DPURPLE_STATIC_PRPL
--noinst_LTLIBRARIES = libsametime.la
--libsametime_la_CFLAGS = $(AM_CFLAGS)
--
--else
--
--st =
--pkg_LTLIBRARIES = libsametime.la
--
--endif
--
--libsametime_la_SOURCES = $(SAMETIMESOURCES)
--libsametime_la_LDFLAGS = -module -avoid-version
--libsametime_la_LIBADD = $(GLIB_LIBS) $(MEANWHILE_LIBS)
--
--AM_CPPFLAGS = \
-- -I$(top_srcdir)/libpurple \
-- -I$(top_builddir)/libpurple \
-- $(DEBUG_CFLAGS) \
-- $(GLIB_CFLAGS) \
-- $(MEANWHILE_CFLAGS) \
-- -DG_LOG_DOMAIN=\"sametime\"
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/sametime/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/sametime/Makefile.in
---- pidgin-2.10.7/libpurple/protocols/sametime/Makefile.in 2013-02-11 07:17:21.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/sametime/Makefile.in 1969-12-31 21:00:00.000000000 -0300
-@@ -1,752 +0,0 @@
--# Makefile.in generated by automake 1.11.6 from Makefile.am.
--# @configure_input@
--
--# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
--# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
--# Foundation, Inc.
--# This Makefile.in is free software; the Free Software Foundation
--# gives unlimited permission to copy and/or distribute it,
--# with or without modifications, as long as this notice is preserved.
--
--# This program is distributed in the hope that it will be useful,
--# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
--# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
--# PARTICULAR PURPOSE.
--
--@SET_MAKE@
--
--
--VPATH = @srcdir@
--am__make_dryrun = \
-- { \
-- am__dry=no; \
-- case $$MAKEFLAGS in \
-- *\\[\ \ ]*) \
-- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
-- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
-- *) \
-- for am__flg in $$MAKEFLAGS; do \
-- case $$am__flg in \
-- *=*|--*) ;; \
-- *n*) am__dry=yes; break;; \
-- esac; \
-- done;; \
-- esac; \
-- test $$am__dry = yes; \
-- }
--pkgdatadir = $(datadir)/@PACKAGE@
--pkgincludedir = $(includedir)/@PACKAGE@
--pkglibdir = $(libdir)/@PACKAGE@
--pkglibexecdir = $(libexecdir)/@PACKAGE@
--am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
--install_sh_DATA = $(install_sh) -c -m 644
--install_sh_PROGRAM = $(install_sh) -c
--install_sh_SCRIPT = $(install_sh) -c
--INSTALL_HEADER = $(INSTALL_DATA)
--transform = $(program_transform_name)
--NORMAL_INSTALL = :
--PRE_INSTALL = :
--POST_INSTALL = :
--NORMAL_UNINSTALL = :
--PRE_UNINSTALL = :
--POST_UNINSTALL = :
--build_triplet = @build@
--host_triplet = @host@
--subdir = libpurple/protocols/sametime
--DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
-- $(srcdir)/Makefile.in
--ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
--am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
-- $(top_srcdir)/configure.ac
--am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-- $(ACLOCAL_M4)
--mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
--CONFIG_HEADER = $(top_builddir)/config.h
--CONFIG_CLEAN_FILES =
--CONFIG_CLEAN_VPATH_FILES =
--am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
--am__vpath_adj = case $$p in \
-- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
-- *) f=$$p;; \
-- esac;
--am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
--am__install_max = 40
--am__nobase_strip_setup = \
-- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
--am__nobase_strip = \
-- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
--am__nobase_list = $(am__nobase_strip_setup); \
-- for p in $$list; do echo "$$p $$p"; done | \
-- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
-- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
-- if (++n[$$2] == $(am__install_max)) \
-- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
-- END { for (dir in files) print dir, files[dir] }'
--am__base_list = \
-- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
-- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
--am__uninstall_files_from_dir = { \
-- test -z "$$files" \
-- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
-- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
-- $(am__cd) "$$dir" && rm -f $$files; }; \
-- }
--am__installdirs = "$(DESTDIR)$(pkgdir)"
--LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkg_LTLIBRARIES)
--am__DEPENDENCIES_1 =
--libsametime_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
-- $(am__DEPENDENCIES_1)
--am__objects_1 = libsametime_la-sametime.lo
--am_libsametime_la_OBJECTS = $(am__objects_1)
--libsametime_la_OBJECTS = $(am_libsametime_la_OBJECTS)
--AM_V_lt = $(am__v_lt_@AM_V@)
--am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
--am__v_lt_0 = --silent
--libsametime_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
-- $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
-- $(libsametime_la_CFLAGS) $(CFLAGS) $(libsametime_la_LDFLAGS) \
-- $(LDFLAGS) -o $@
--@STATIC_SAMETIME_FALSE@am_libsametime_la_rpath = -rpath $(pkgdir)
--@STATIC_SAMETIME_TRUE@am_libsametime_la_rpath =
--DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
--depcomp = $(SHELL) $(top_srcdir)/depcomp
--am__depfiles_maybe = depfiles
--am__mv = mv -f
--COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
--LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-- $(AM_CFLAGS) $(CFLAGS)
--AM_V_CC = $(am__v_CC_@AM_V@)
--am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
--am__v_CC_0 = @echo " CC " $@;
--AM_V_at = $(am__v_at_@AM_V@)
--am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
--am__v_at_0 = @
--CCLD = $(CC)
--LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-- $(AM_LDFLAGS) $(LDFLAGS) -o $@
--AM_V_CCLD = $(am__v_CCLD_@AM_V@)
--am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
--am__v_CCLD_0 = @echo " CCLD " $@;
--AM_V_GEN = $(am__v_GEN_@AM_V@)
--am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
--am__v_GEN_0 = @echo " GEN " $@;
--SOURCES = $(libsametime_la_SOURCES)
--DIST_SOURCES = $(libsametime_la_SOURCES)
--am__can_run_installinfo = \
-- case $$AM_UPDATE_INFO_DIR in \
-- n|no|NO) false;; \
-- *) (install-info --version) >/dev/null 2>&1;; \
-- esac
--HEADERS = $(noinst_HEADERS)
--ETAGS = etags
--CTAGS = ctags
--DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
--ACLOCAL = @ACLOCAL@
--ALLOCA = @ALLOCA@
--ALL_LINGUAS = @ALL_LINGUAS@
--AMTAR = @AMTAR@
--AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
--AR = @AR@
--AUTOCONF = @AUTOCONF@
--AUTOHEADER = @AUTOHEADER@
--AUTOMAKE = @AUTOMAKE@
--AVAHI_CFLAGS = @AVAHI_CFLAGS@
--AVAHI_LIBS = @AVAHI_LIBS@
--AWK = @AWK@
--CATALOGS = @CATALOGS@
--CATOBJEXT = @CATOBJEXT@
--CC = @CC@
--CCDEPMODE = @CCDEPMODE@
--CFLAGS = @CFLAGS@
--CHECK_CFLAGS = @CHECK_CFLAGS@
--CHECK_LIBS = @CHECK_LIBS@
--CPP = @CPP@
--CPPFLAGS = @CPPFLAGS@
--CYGPATH_W = @CYGPATH_W@
--DATADIRNAME = @DATADIRNAME@
--DBUS_CFLAGS = @DBUS_CFLAGS@
--DBUS_LIBS = @DBUS_LIBS@
--DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
--DEBUG_CFLAGS = @DEBUG_CFLAGS@
--DEFS = @DEFS@
--DEPDIR = @DEPDIR@
--DLLTOOL = @DLLTOOL@
--DOT = @DOT@
--DOXYGEN = @DOXYGEN@
--DSYMUTIL = @DSYMUTIL@
--DUMPBIN = @DUMPBIN@
--DYNALOADER_A = @DYNALOADER_A@
--DYNAMIC_PRPLS = @DYNAMIC_PRPLS@
--ECHO_C = @ECHO_C@
--ECHO_N = @ECHO_N@
--ECHO_T = @ECHO_T@
--EGREP = @EGREP@
--EVOLUTION_ADDRESSBOOK_CFLAGS = @EVOLUTION_ADDRESSBOOK_CFLAGS@
--EVOLUTION_ADDRESSBOOK_LIBS = @EVOLUTION_ADDRESSBOOK_LIBS@
--EXEEXT = @EXEEXT@
--FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
--FARSTREAM_LIBS = @FARSTREAM_LIBS@
--FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
--GCONFTOOL = @GCONFTOOL@
--GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
--GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
--GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
--GLIB_CFLAGS = @GLIB_CFLAGS@
--GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
--GLIB_LIBS = @GLIB_LIBS@
--GMOFILES = @GMOFILES@
--GMSGFMT = @GMSGFMT@
--GNT_CFLAGS = @GNT_CFLAGS@
--GNT_LIBS = @GNT_LIBS@
--GNT_LT_VERSION_INFO = @GNT_LT_VERSION_INFO@
--GNT_MAJOR_VERSION = @GNT_MAJOR_VERSION@
--GNT_MICRO_VERSION = @GNT_MICRO_VERSION@
--GNT_MINOR_VERSION = @GNT_MINOR_VERSION@
--GNT_VERSION = @GNT_VERSION@
--GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
--GNUTLS_LIBS = @GNUTLS_LIBS@
--GREP = @GREP@
--GSTINTERFACES_CFLAGS = @GSTINTERFACES_CFLAGS@
--GSTINTERFACES_LIBS = @GSTINTERFACES_LIBS@
--GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
--GSTREAMER_LIBS = @GSTREAMER_LIBS@
--GTKSPELL_CFLAGS = @GTKSPELL_CFLAGS@
--GTKSPELL_LIBS = @GTKSPELL_LIBS@
--GTK_CFLAGS = @GTK_CFLAGS@
--GTK_LIBS = @GTK_LIBS@
--IDN_CFLAGS = @IDN_CFLAGS@
--IDN_LIBS = @IDN_LIBS@
--INSTALL = @INSTALL@
--INSTALL_DATA = @INSTALL_DATA@
--INSTALL_PROGRAM = @INSTALL_PROGRAM@
--INSTALL_SCRIPT = @INSTALL_SCRIPT@
--INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
--INSTOBJEXT = @INSTOBJEXT@
--INTLLIBS = @INTLLIBS@
--INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
--INTLTOOL_MERGE = @INTLTOOL_MERGE@
--INTLTOOL_PERL = @INTLTOOL_PERL@
--INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
--INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
--INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
--INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
--INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
--KRB4_CFLAGS = @KRB4_CFLAGS@
--KRB4_LDFLAGS = @KRB4_LDFLAGS@
--KRB4_LIBS = @KRB4_LIBS@
--LD = @LD@
--LDADD = @LDADD@
--LDFLAGS = @LDFLAGS@
--LIBOBJS = @LIBOBJS@
--LIBPERL_A = @LIBPERL_A@
--LIBS = @LIBS@
--LIBTOOL = @LIBTOOL@
--LIBXML_CFLAGS = @LIBXML_CFLAGS@
--LIBXML_LIBS = @LIBXML_LIBS@
--LIPO = @LIPO@
--LN_S = @LN_S@
--LTLIBOBJS = @LTLIBOBJS@
--MAKEINFO = @MAKEINFO@
--MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
--MKDIR_P = @MKDIR_P@
--MKINSTALLDIRS = @MKINSTALLDIRS@
--MONO_CFLAGS = @MONO_CFLAGS@
--MONO_LIBS = @MONO_LIBS@
--MSGFMT = @MSGFMT@
--MSGFMT_OPTS = @MSGFMT_OPTS@
--MSGMERGE = @MSGMERGE@
--NETWORKMANAGER_CFLAGS = @NETWORKMANAGER_CFLAGS@
--NETWORKMANAGER_LIBS = @NETWORKMANAGER_LIBS@
--NM = @NM@
--NMEDIT = @NMEDIT@
--NSS_CFLAGS = @NSS_CFLAGS@
--NSS_LIBS = @NSS_LIBS@
--OBJDUMP = @OBJDUMP@
--OBJEXT = @OBJEXT@
--OTOOL = @OTOOL@
--OTOOL64 = @OTOOL64@
--PACKAGE = @PACKAGE@
--PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
--PACKAGE_NAME = @PACKAGE_NAME@
--PACKAGE_STRING = @PACKAGE_STRING@
--PACKAGE_TARNAME = @PACKAGE_TARNAME@
--PACKAGE_URL = @PACKAGE_URL@
--PACKAGE_VERSION = @PACKAGE_VERSION@
--PANGO_CFLAGS = @PANGO_CFLAGS@
--PANGO_LIBS = @PANGO_LIBS@
--PATH_SEPARATOR = @PATH_SEPARATOR@
--PERL = @PERL@
--PERL_CFLAGS = @PERL_CFLAGS@
--PERL_LIBS = @PERL_LIBS@
--PKG_CONFIG = @PKG_CONFIG@
--PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
--PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
--PLUGINS_DEFINE = @PLUGINS_DEFINE@
--POFILES = @POFILES@
--POSUB = @POSUB@
--PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
--PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
--PURPLE_LT_VERSION_INFO = @PURPLE_LT_VERSION_INFO@
--PURPLE_MAJOR_VERSION = @PURPLE_MAJOR_VERSION@
--PURPLE_MICRO_VERSION = @PURPLE_MICRO_VERSION@
--PURPLE_MINOR_VERSION = @PURPLE_MINOR_VERSION@
--PURPLE_VERSION = @PURPLE_VERSION@
--PYTHON = @PYTHON@
--PY_CFLAGS = @PY_CFLAGS@
--PY_LIBS = @PY_LIBS@
--RANLIB = @RANLIB@
--SASL_LIBS = @SASL_LIBS@
--SED = @SED@
--SET_MAKE = @SET_MAKE@
--SHELL = @SHELL@
--SILC_CFLAGS = @SILC_CFLAGS@
--SILC_LIBS = @SILC_LIBS@
--SM_LIBS = @SM_LIBS@
--SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
--SQLITE3_LIBS = @SQLITE3_LIBS@
--SSL_CERTIFICATES_DIR = @SSL_CERTIFICATES_DIR@
--STATIC_LINK_LIBS = @STATIC_LINK_LIBS@
--STATIC_PRPLS = @STATIC_PRPLS@
--STRIP = @STRIP@
--TCL_CFLAGS = @TCL_CFLAGS@
--TCL_LIBS = @TCL_LIBS@
--TK_LIBS = @TK_LIBS@
--USE_NLS = @USE_NLS@
--VERSION = @VERSION@
--X11_CFLAGS = @X11_CFLAGS@
--X11_LIBS = @X11_LIBS@
--XGETTEXT = @XGETTEXT@
--XMKMF = @XMKMF@
--XSLTPROC = @XSLTPROC@
--XSS_LIBS = @XSS_LIBS@
--X_CFLAGS = @X_CFLAGS@
--X_EXTRA_LIBS = @X_EXTRA_LIBS@
--X_LIBS = @X_LIBS@
--X_PRE_LIBS = @X_PRE_LIBS@
--ZEPHYR_CFLAGS = @ZEPHYR_CFLAGS@
--ZEPHYR_LDFLAGS = @ZEPHYR_LDFLAGS@
--ZEPHYR_LIBS = @ZEPHYR_LIBS@
--abs_builddir = @abs_builddir@
--abs_srcdir = @abs_srcdir@
--abs_top_builddir = @abs_top_builddir@
--abs_top_srcdir = @abs_top_srcdir@
--ac_ct_AR = @ac_ct_AR@
--ac_ct_CC = @ac_ct_CC@
--ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
--am__include = @am__include@
--am__leading_dot = @am__leading_dot@
--am__quote = @am__quote@
--am__tar = @am__tar@
--am__untar = @am__untar@
--bindir = @bindir@
--build = @build@
--build_alias = @build_alias@
--build_cpu = @build_cpu@
--build_os = @build_os@
--build_vendor = @build_vendor@
--builddir = @builddir@
--datadir = @datadir@
--datarootdir = @datarootdir@
--docdir = @docdir@
--dvidir = @dvidir@
--enable_dbus = @enable_dbus@
--enable_devhelp = @enable_devhelp@
--enable_dot = @enable_dot@
--enable_doxygen = @enable_doxygen@
--exec_prefix = @exec_prefix@
--host = @host@
--host_alias = @host_alias@
--host_cpu = @host_cpu@
--host_os = @host_os@
--host_vendor = @host_vendor@
--htmldir = @htmldir@
--includedir = @includedir@
--infodir = @infodir@
--install_sh = @install_sh@
--intltool__v_merge_options_ = @intltool__v_merge_options_@
--intltool__v_merge_options_0 = @intltool__v_merge_options_0@
--libdir = @libdir@
--libexecdir = @libexecdir@
--localedir = @localedir@
--localstatedir = @localstatedir@
--mandir = @mandir@
--mkdir_p = @mkdir_p@
--oldincludedir = @oldincludedir@
--pdfdir = @pdfdir@
--perlpath = @perlpath@
--pidginpath = @pidginpath@
--prefix = @prefix@
--program_transform_name = @program_transform_name@
--psdir = @psdir@
--sbindir = @sbindir@
--sedpath = @sedpath@
--sharedstatedir = @sharedstatedir@
--srcdir = @srcdir@
--sysconfdir = @sysconfdir@
--target_alias = @target_alias@
--top_build_prefix = @top_build_prefix@
--top_builddir = @top_builddir@
--top_srcdir = @top_srcdir@
--EXTRA_DIST = \
-- Makefile.mingw
--
--pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
--noinst_HEADERS = sametime.h
--SAMETIMESOURCES = sametime.c
--AM_CFLAGS = \
-- $(st)
--
--@STATIC_SAMETIME_FALSE@st =
--@STATIC_SAMETIME_TRUE@st = -DPURPLE_STATIC_PRPL
--@STATIC_SAMETIME_TRUE@noinst_LTLIBRARIES = libsametime.la
--@STATIC_SAMETIME_TRUE@libsametime_la_CFLAGS = $(AM_CFLAGS)
--@STATIC_SAMETIME_FALSE@pkg_LTLIBRARIES = libsametime.la
--libsametime_la_SOURCES = $(SAMETIMESOURCES)
--libsametime_la_LDFLAGS = -module -avoid-version
--libsametime_la_LIBADD = $(GLIB_LIBS) $(MEANWHILE_LIBS)
--AM_CPPFLAGS = \
-- -I$(top_srcdir)/libpurple \
-- -I$(top_builddir)/libpurple \
-- $(DEBUG_CFLAGS) \
-- $(GLIB_CFLAGS) \
-- $(MEANWHILE_CFLAGS) \
-- -DG_LOG_DOMAIN=\"sametime\"
--
--all: all-am
--
--.SUFFIXES:
--.SUFFIXES: .c .lo .o .obj
--$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
-- @for dep in $?; do \
-- case '$(am__configure_deps)' in \
-- *$$dep*) \
-- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
-- && { if test -f $@; then exit 0; else break; fi; }; \
-- exit 1;; \
-- esac; \
-- done; \
-- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpurple/protocols/sametime/Makefile'; \
-- $(am__cd) $(top_srcdir) && \
-- $(AUTOMAKE) --gnu libpurple/protocols/sametime/Makefile
--.PRECIOUS: Makefile
--Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-- @case '$?' in \
-- *config.status*) \
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-- *) \
-- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-- esac;
--
--$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--
--$(top_srcdir)/configure: $(am__configure_deps)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--$(ACLOCAL_M4): $(am__aclocal_m4_deps)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--$(am__aclocal_m4_deps):
--
--clean-noinstLTLIBRARIES:
-- -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-- @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
-- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-- test "$$dir" != "$$p" || dir=.; \
-- echo "rm -f \"$${dir}/so_locations\""; \
-- rm -f "$${dir}/so_locations"; \
-- done
--install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES)
-- @$(NORMAL_INSTALL)
-- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
-- list2=; for p in $$list; do \
-- if test -f $$p; then \
-- list2="$$list2 $$p"; \
-- else :; fi; \
-- done; \
-- test -z "$$list2" || { \
-- echo " $(MKDIR_P) '$(DESTDIR)$(pkgdir)'"; \
-- $(MKDIR_P) "$(DESTDIR)$(pkgdir)" || exit 1; \
-- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgdir)'"; \
-- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgdir)"; \
-- }
--
--uninstall-pkgLTLIBRARIES:
-- @$(NORMAL_UNINSTALL)
-- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
-- for p in $$list; do \
-- $(am__strip_dir) \
-- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgdir)/$$f'"; \
-- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgdir)/$$f"; \
-- done
--
--clean-pkgLTLIBRARIES:
-- -test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES)
-- @list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
-- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-- test "$$dir" != "$$p" || dir=.; \
-- echo "rm -f \"$${dir}/so_locations\""; \
-- rm -f "$${dir}/so_locations"; \
-- done
--libsametime.la: $(libsametime_la_OBJECTS) $(libsametime_la_DEPENDENCIES) $(EXTRA_libsametime_la_DEPENDENCIES)
-- $(AM_V_CCLD)$(libsametime_la_LINK) $(am_libsametime_la_rpath) $(libsametime_la_OBJECTS) $(libsametime_la_LIBADD) $(LIBS)
--
--mostlyclean-compile:
-- -rm -f *.$(OBJEXT)
--
--distclean-compile:
-- -rm -f *.tab.c
--
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsametime_la-sametime.Plo@am__quote@
--
--.c.o:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
--
--.c.obj:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
--
--.c.lo:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
--
--libsametime_la-sametime.lo: sametime.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsametime_la_CFLAGS) $(CFLAGS) -MT libsametime_la-sametime.lo -MD -MP -MF $(DEPDIR)/libsametime_la-sametime.Tpo -c -o libsametime_la-sametime.lo `test -f 'sametime.c' || echo '$(srcdir)/'`sametime.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsametime_la-sametime.Tpo $(DEPDIR)/libsametime_la-sametime.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sametime.c' object='libsametime_la-sametime.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsametime_la_CFLAGS) $(CFLAGS) -c -o libsametime_la-sametime.lo `test -f 'sametime.c' || echo '$(srcdir)/'`sametime.c
--
--mostlyclean-libtool:
-- -rm -f *.lo
--
--clean-libtool:
-- -rm -rf .libs _libs
--
--ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- mkid -fID $$unique
--tags: TAGS
--
--TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
-- $(TAGS_FILES) $(LISP)
-- set x; \
-- here=`pwd`; \
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- shift; \
-- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-- test -n "$$unique" || unique=$$empty_fix; \
-- if test $$# -gt 0; then \
-- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-- "$$@" $$unique; \
-- else \
-- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-- $$unique; \
-- fi; \
-- fi
--ctags: CTAGS
--CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
-- $(TAGS_FILES) $(LISP)
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- test -z "$(CTAGS_ARGS)$$unique" \
-- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-- $$unique
--
--GTAGS:
-- here=`$(am__cd) $(top_builddir) && pwd` \
-- && $(am__cd) $(top_srcdir) \
-- && gtags -i $(GTAGS_ARGS) "$$here"
--
--distclean-tags:
-- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
--
--distdir: $(DISTFILES)
-- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-- list='$(DISTFILES)'; \
-- dist_files=`for file in $$list; do echo $$file; done | \
-- sed -e "s|^$$srcdirstrip/||;t" \
-- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-- case $$dist_files in \
-- */*) $(MKDIR_P) `echo "$$dist_files" | \
-- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-- sort -u` ;; \
-- esac; \
-- for file in $$dist_files; do \
-- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-- if test -d $$d/$$file; then \
-- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-- if test -d "$(distdir)/$$file"; then \
-- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-- fi; \
-- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-- fi; \
-- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-- else \
-- test -f "$(distdir)/$$file" \
-- || cp -p $$d/$$file "$(distdir)/$$file" \
-- || exit 1; \
-- fi; \
-- done
--check-am: all-am
--check: check-am
--all-am: Makefile $(LTLIBRARIES) $(HEADERS)
--installdirs:
-- for dir in "$(DESTDIR)$(pkgdir)"; do \
-- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
-- done
--install: install-am
--install-exec: install-exec-am
--install-data: install-data-am
--uninstall: uninstall-am
--
--install-am: all-am
-- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
--
--installcheck: installcheck-am
--install-strip:
-- if test -z '$(STRIP)'; then \
-- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-- install; \
-- else \
-- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-- fi
--mostlyclean-generic:
--
--clean-generic:
--
--distclean-generic:
-- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
--
--maintainer-clean-generic:
-- @echo "This command is intended for maintainers to use"
-- @echo "it deletes files that may require special tools to rebuild."
--clean: clean-am
--
--clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
-- clean-pkgLTLIBRARIES mostlyclean-am
--
--distclean: distclean-am
-- -rm -rf ./$(DEPDIR)
-- -rm -f Makefile
--distclean-am: clean-am distclean-compile distclean-generic \
-- distclean-tags
--
--dvi: dvi-am
--
--dvi-am:
--
--html: html-am
--
--html-am:
--
--info: info-am
--
--info-am:
--
--install-data-am: install-pkgLTLIBRARIES
--
--install-dvi: install-dvi-am
--
--install-dvi-am:
--
--install-exec-am:
--
--install-html: install-html-am
--
--install-html-am:
--
--install-info: install-info-am
--
--install-info-am:
--
--install-man:
--
--install-pdf: install-pdf-am
--
--install-pdf-am:
--
--install-ps: install-ps-am
--
--install-ps-am:
--
--installcheck-am:
--
--maintainer-clean: maintainer-clean-am
-- -rm -rf ./$(DEPDIR)
-- -rm -f Makefile
--maintainer-clean-am: distclean-am maintainer-clean-generic
--
--mostlyclean: mostlyclean-am
--
--mostlyclean-am: mostlyclean-compile mostlyclean-generic \
-- mostlyclean-libtool
--
--pdf: pdf-am
--
--pdf-am:
--
--ps: ps-am
--
--ps-am:
--
--uninstall-am: uninstall-pkgLTLIBRARIES
--
--.MAKE: install-am install-strip
--
--.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
-- clean-libtool clean-noinstLTLIBRARIES clean-pkgLTLIBRARIES \
-- ctags distclean distclean-compile distclean-generic \
-- distclean-libtool distclean-tags distdir dvi dvi-am html \
-- html-am info info-am install install-am install-data \
-- install-data-am install-dvi install-dvi-am install-exec \
-- install-exec-am install-html install-html-am install-info \
-- install-info-am install-man install-pdf install-pdf-am \
-- install-pkgLTLIBRARIES install-ps install-ps-am install-strip \
-- installcheck installcheck-am installdirs maintainer-clean \
-- maintainer-clean-generic mostlyclean mostlyclean-compile \
-- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-- tags uninstall uninstall-am uninstall-pkgLTLIBRARIES
--
--
--# Tell versions [3.59,3.63) of GNU make to not export all variables.
--# Otherwise a system limit (for SysV at least) may be exceeded.
--.NOEXPORT:
-diff -Nur pidgin-2.10.7/libpurple/protocols/sametime/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/sametime/Makefile.mingw
---- pidgin-2.10.7/libpurple/protocols/sametime/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/sametime/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,85 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of libsametime
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = libsametime
--NEEDED_DLLS = $(MEANWHILE_TOP)/bin/libmeanwhile-1.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
--
--CFLAGS += -DG_LOG_DOMAIN=\"sametime\"
--
--##
--## INCLUDE PATHS
--##
--INCLUDE_PATHS += -I. \
-- -I$(MEANWHILE_TOP)/include/meanwhile \
-- -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)
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(MEANWHILE_TOP)/lib \
-- -L$(PURPLE_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = sametime.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lintl \
-- -lws2_32 \
-- -lmeanwhile \
-- -lpurple
--
--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) -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--
--clean:
-- rm -f $(OBJECTS)
-- rm -f $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/sametime/sametime.c pidgin-2.10.7-nonprism/libpurple/protocols/sametime/sametime.c
---- pidgin-2.10.7/libpurple/protocols/sametime/sametime.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/sametime/sametime.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,5832 +0,0 @@
--
--/*
-- Meanwhile Protocol Plugin for Purple
-- Adds Lotus Sametime support to Purple using the Meanwhile library
--
-- Copyright (C) 2004 Christopher (siege) O'Brien <siege@preoccupied.net>
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or (at
-- your option) any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301,
-- USA.
--*/
--
--#include "internal.h"
--
--/* system includes */
--#include <stdlib.h>
--#include <time.h>
--
--/* glib includes */
--#include <glib.h>
--
--/* purple includes */
--#include "account.h"
--#include "accountopt.h"
--#include "circbuffer.h"
--#include "conversation.h"
--#include "debug.h"
--#include "ft.h"
--#include "imgstore.h"
--#include "mime.h"
--#include "notify.h"
--#include "plugin.h"
--#include "privacy.h"
--#include "prpl.h"
--#include "request.h"
--#include "util.h"
--#include "version.h"
--
--/* meanwhile includes */
--#include <mw_cipher.h>
--#include <mw_common.h>
--#include <mw_error.h>
--#include <mw_service.h>
--#include <mw_session.h>
--#include <mw_srvc_aware.h>
--#include <mw_srvc_conf.h>
--#include <mw_srvc_ft.h>
--#include <mw_srvc_im.h>
--#include <mw_srvc_place.h>
--#include <mw_srvc_resolve.h>
--#include <mw_srvc_store.h>
--#include <mw_st_list.h>
--
--/* plugin includes */
--#include "sametime.h"
--
--
--/* considering that there's no display of this information for prpls,
-- I don't know why I even bother providing these. Oh valiant reader,
-- I do it all for you. */
--/* scratch that, I just added it to the prpl options panel */
--#define PLUGIN_ID "prpl-meanwhile"
--#define PLUGIN_NAME "Sametime"
--#define PLUGIN_SUMMARY "Sametime Protocol Plugin"
--#define PLUGIN_DESC "Open implementation of a Lotus Sametime client"
--#define PLUGIN_AUTHOR "Christopher (siege) O'Brien <siege@preoccupied.net>"
--#define PLUGIN_HOMEPAGE "http://meanwhile.sourceforge.net/"
--
--
--/* plugin preference names */
--#define MW_PRPL_OPT_BASE "/plugins/prpl/meanwhile"
--#define MW_PRPL_OPT_BLIST_ACTION MW_PRPL_OPT_BASE "/blist_action"
--#define MW_PRPL_OPT_PSYCHIC MW_PRPL_OPT_BASE "/psychic"
--#define MW_PRPL_OPT_FORCE_LOGIN MW_PRPL_OPT_BASE "/force_login"
--#define MW_PRPL_OPT_SAVE_DYNAMIC MW_PRPL_OPT_BASE "/save_dynamic"
--
--
--/* stages of connecting-ness */
--#define MW_CONNECT_STEPS 11
--
--
--/* stages of conciousness */
--#define MW_STATE_OFFLINE "offline"
--#define MW_STATE_ACTIVE "active"
--#define MW_STATE_AWAY "away"
--#define MW_STATE_BUSY "dnd"
--#define MW_STATE_MESSAGE "message"
--#define MW_STATE_ENLIGHTENED "buddha"
--
--
--/* keys to get/set chat information */
--#define CHAT_KEY_CREATOR "chat.creator"
--#define CHAT_KEY_NAME "chat.name"
--#define CHAT_KEY_TOPIC "chat.topic"
--#define CHAT_KEY_INVITE "chat.invite"
--#define CHAT_KEY_IS_PLACE "chat.is_place"
--
--
--/* key for associating a mwLoginType with a buddy */
--#define BUDDY_KEY_CLIENT "meanwhile.client"
--
--/* store the remote alias so that we can re-create it easily */
--#define BUDDY_KEY_NAME "meanwhile.shortname"
--
--/* enum mwSametimeUserType */
--#define BUDDY_KEY_TYPE "meanwhile.type"
--
--
--/* key for the real group name for a meanwhile group */
--#define GROUP_KEY_NAME "meanwhile.group"
--
--/* enum mwSametimeGroupType */
--#define GROUP_KEY_TYPE "meanwhile.type"
--
--/* NAB group owning account */
--#define GROUP_KEY_OWNER "meanwhile.account"
--
--/* key gtk blist uses to indicate a collapsed group */
--#define GROUP_KEY_COLLAPSED "collapsed"
--
--
--/* verification replacement */
--#define mwSession_NO_SECRET "meanwhile.no_secret"
--
--
--/* keys to get/set purple plugin information */
--#define MW_KEY_HOST "server"
--#define MW_KEY_PORT "port"
--#define MW_KEY_FORCE "force_login"
--#define MW_KEY_FAKE_IT "fake_client_id"
--#define MW_KEY_CLIENT "client_id_val"
--#define MW_KEY_MAJOR "client_major"
--#define MW_KEY_MINOR "client_minor"
--
--
--/** number of seconds from the first blist change before a save to the
-- storage service occurs. */
--#define BLIST_SAVE_SECONDS 15
--
--
--/** the possible buddy list storage settings */
--enum blist_choice {
-- blist_choice_LOCAL = 1, /**< local only */
-- blist_choice_MERGE = 2, /**< merge from server */
-- blist_choice_STORE = 3, /**< merge from and save to server */
-- blist_choice_SYNCH = 4 /**< sync with server */
--};
--
--
--/** the default blist storage option */
--#define BLIST_CHOICE_DEFAULT blist_choice_SYNCH
--
--
--/* testing for the above */
--#define BLIST_PREF_IS(n) (purple_prefs_get_int(MW_PRPL_OPT_BLIST_ACTION)==(n))
--#define BLIST_PREF_IS_LOCAL() BLIST_PREF_IS(blist_choice_LOCAL)
--#define BLIST_PREF_IS_MERGE() BLIST_PREF_IS(blist_choice_MERGE)
--#define BLIST_PREF_IS_STORE() BLIST_PREF_IS(blist_choice_STORE)
--#define BLIST_PREF_IS_SYNCH() BLIST_PREF_IS(blist_choice_SYNCH)
--
--
--/* debugging output */
--#define DEBUG_ERROR(...) purple_debug_error(G_LOG_DOMAIN, __VA_ARGS__)
--#define DEBUG_INFO(...) purple_debug_info(G_LOG_DOMAIN, __VA_ARGS__)
--#define DEBUG_MISC(...) purple_debug_misc(G_LOG_DOMAIN, __VA_ARGS__)
--#define DEBUG_WARN(...) purple_debug_warning(G_LOG_DOMAIN, __VA_ARGS__)
--
--
--/** ensure non-null strings */
--#ifndef NSTR
--# define NSTR(str) ((str)? (str): "(null)")
--#endif
--
--
--/** calibrates distinct secure channel nomenclature */
--static const unsigned char no_secret[] = {
-- 0x2d, 0x2d, 0x20, 0x73, 0x69, 0x65, 0x67, 0x65,
-- 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x73, 0x20, 0x6a,
-- 0x65, 0x6e, 0x6e, 0x69, 0x20, 0x61, 0x6e, 0x64,
-- 0x20, 0x7a, 0x6f, 0x65, 0x20, 0x2d, 0x2d, 0x00,
--};
--
--
--/** handler IDs from g_log_set_handler in mw_plugin_init */
--static guint log_handler[2] = { 0, 0 };
--
--
--/** the purple plugin data.
-- available as gc->proto_data and mwSession_getClientData */
--struct mwPurplePluginData {
-- struct mwSession *session;
--
-- struct mwServiceAware *srvc_aware;
-- struct mwServiceConference *srvc_conf;
-- struct mwServiceFileTransfer *srvc_ft;
-- struct mwServiceIm *srvc_im;
-- struct mwServicePlace *srvc_place;
-- struct mwServiceResolve *srvc_resolve;
-- struct mwServiceStorage *srvc_store;
--
-- /** map of PurpleGroup:mwAwareList and mwAwareList:PurpleGroup */
-- GHashTable *group_list_map;
--
-- /** event id for the buddy list save callback */
-- guint save_event;
--
-- /** socket fd */
-- int socket;
-- gint outpa; /* like inpa, but the other way */
--
-- /** circular buffer for outgoing data */
-- PurpleCircBuffer *sock_buf;
--
-- PurpleConnection *gc;
--};
--
--
--typedef struct {
-- PurpleBuddy *buddy;
-- PurpleGroup *group;
--} BuddyAddData;
--
--
--/* blist and aware functions */
--
--static void blist_export(PurpleConnection *gc, struct mwSametimeList *stlist);
--
--static void blist_store(struct mwPurplePluginData *pd);
--
--static void blist_schedule(struct mwPurplePluginData *pd);
--
--static void blist_merge(PurpleConnection *gc, struct mwSametimeList *stlist);
--
--static void blist_sync(PurpleConnection *gc, struct mwSametimeList *stlist);
--
--static gboolean buddy_is_external(PurpleBuddy *b);
--
--static void buddy_add(struct mwPurplePluginData *pd, PurpleBuddy *buddy);
--
--static PurpleBuddy *
--buddy_ensure(PurpleConnection *gc, PurpleGroup *group,
-- struct mwSametimeUser *stuser);
--
--static void group_add(struct mwPurplePluginData *pd, PurpleGroup *group);
--
--static PurpleGroup *
--group_ensure(PurpleConnection *gc, struct mwSametimeGroup *stgroup);
--
--static struct mwAwareList *
--list_ensure(struct mwPurplePluginData *pd, PurpleGroup *group);
--
--
--/* session functions */
--
--static struct mwSession *
--gc_to_session(PurpleConnection *gc);
--
--static PurpleConnection *session_to_gc(struct mwSession *session);
--
--
--/* conference functions */
--
--static struct mwConference *
--conf_find_by_id(struct mwPurplePluginData *pd, int id);
--
--
--/* conversation functions */
--
--struct convo_msg {
-- enum mwImSendType type;
-- gpointer data;
-- GDestroyNotify clear;
--};
--
--
--struct convo_data {
-- struct mwConversation *conv;
-- GList *queue; /**< outgoing message queue, list of convo_msg */
--};
--
--static void convo_data_new(struct mwConversation *conv);
--
--static void convo_data_free(struct convo_data *conv);
--
--static void convo_features(struct mwConversation *conv);
--
--static PurpleConversation *convo_get_gconv(struct mwConversation *conv);
--
--
--/* name and id */
--
--struct named_id {
-- char *id;
-- char *name;
--};
--
--
--/* connection functions */
--
--static void connect_cb(gpointer data, gint source, const gchar *error_message);
--
--
--/* ----- session ------ */
--
--
--/** resolves a mwSession from a PurpleConnection */
--static struct mwSession *gc_to_session(PurpleConnection *gc) {
-- struct mwPurplePluginData *pd;
--
-- g_return_val_if_fail(gc != NULL, NULL);
--
-- pd = gc->proto_data;
-- g_return_val_if_fail(pd != NULL, NULL);
--
-- return pd->session;
--}
--
--
--/** resolves a PurpleConnection from a mwSession */
--static PurpleConnection *session_to_gc(struct mwSession *session) {
-- struct mwPurplePluginData *pd;
--
-- g_return_val_if_fail(session != NULL, NULL);
--
-- pd = mwSession_getClientData(session);
-- g_return_val_if_fail(pd != NULL, NULL);
--
-- return pd->gc;
--}
--
--
--static void write_cb(gpointer data, gint source, PurpleInputCondition cond) {
-- struct mwPurplePluginData *pd = data;
-- PurpleCircBuffer *circ = pd->sock_buf;
-- gsize avail;
-- int ret;
--
-- DEBUG_INFO("write_cb\n");
--
-- g_return_if_fail(circ != NULL);
--
-- avail = purple_circ_buffer_get_max_read(circ);
-- if(BUF_LONG < avail) avail = BUF_LONG;
--
-- while(avail) {
-- ret = write(pd->socket, circ->outptr, avail);
--
-- if(ret <= 0)
-- break;
--
-- purple_circ_buffer_mark_read(circ, ret);
-- avail = purple_circ_buffer_get_max_read(circ);
-- if(BUF_LONG < avail) avail = BUF_LONG;
-- }
--
-- if(! avail) {
-- purple_input_remove(pd->outpa);
-- pd->outpa = 0;
-- }
--}
--
--
--static int mw_session_io_write(struct mwSession *session,
-- const guchar *buf, gsize len) {
-- struct mwPurplePluginData *pd;
-- gssize ret = 0;
-- int err = 0;
--
-- pd = mwSession_getClientData(session);
--
-- /* socket was already closed. */
-- if(pd->socket == 0)
-- return 1;
--
-- if(pd->outpa) {
-- DEBUG_INFO("already pending INPUT_WRITE, buffering\n");
-- purple_circ_buffer_append(pd->sock_buf, buf, len);
-- return 0;
-- }
--
-- while(len) {
-- ret = write(pd->socket, buf, (len > BUF_LEN)? BUF_LEN: len);
--
-- if(ret <= 0)
-- break;
--
-- len -= ret;
-- buf += ret;
-- }
--
-- if(ret <= 0)
-- err = errno;
--
-- if(err == EAGAIN) {
-- /* append remainder to circular buffer */
-- DEBUG_INFO("EAGAIN\n");
-- purple_circ_buffer_append(pd->sock_buf, buf, len);
-- pd->outpa = purple_input_add(pd->socket, PURPLE_INPUT_WRITE, write_cb, pd);
--
-- } else if(len > 0) {
-- gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
-- g_strerror(errno));
-- DEBUG_ERROR("write returned %" G_GSSIZE_FORMAT ", %" G_GSIZE_FORMAT
-- " bytes left unwritten\n", ret, len);
-- purple_connection_error_reason(pd->gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- tmp);
-- g_free(tmp);
--
--#if 0
-- close(pd->socket);
-- pd->socket = 0;
--#endif
--
-- return -1;
-- }
--
-- return 0;
--}
--
--
--static void mw_session_io_close(struct mwSession *session) {
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
--
-- pd = mwSession_getClientData(session);
-- g_return_if_fail(pd != NULL);
--
-- gc = pd->gc;
--
-- if(pd->outpa) {
-- purple_input_remove(pd->outpa);
-- pd->outpa = 0;
-- }
--
-- if(pd->socket) {
-- close(pd->socket);
-- pd->socket = 0;
-- }
--
-- if(gc->inpa) {
-- purple_input_remove(gc->inpa);
-- gc->inpa = 0;
-- }
--}
--
--
--static void mw_session_clear(struct mwSession *session) {
-- ; /* nothing for now */
--}
--
--
--/* ----- aware list ----- */
--
--
--static void blist_resolve_alias_cb(struct mwServiceResolve *srvc,
-- guint32 id, guint32 code, GList *results,
-- gpointer data) {
-- struct mwResolveResult *result;
-- struct mwResolveMatch *match;
--
-- g_return_if_fail(results != NULL);
--
-- result = results->data;
-- g_return_if_fail(result != NULL);
-- g_return_if_fail(result->matches != NULL);
--
-- match = result->matches->data;
-- g_return_if_fail(match != NULL);
--
-- purple_blist_server_alias_buddy(data, match->name);
-- purple_blist_node_set_string(data, BUDDY_KEY_NAME, match->name);
--}
--
--
--static void mw_aware_list_on_aware(struct mwAwareList *list,
-- struct mwAwareSnapshot *aware) {
--
-- PurpleConnection *gc;
-- PurpleAccount *acct;
--
-- struct mwPurplePluginData *pd;
-- guint32 idle;
-- guint stat;
-- const char *id;
-- const char *status = MW_STATE_ACTIVE;
--
-- gc = mwAwareList_getClientData(list);
-- acct = purple_connection_get_account(gc);
--
-- pd = gc->proto_data;
-- idle = aware->status.time;
-- stat = aware->status.status;
-- id = aware->id.user;
--
-- if(idle) {
-- guint32 idle_len; /*< how long a client has been idle */
-- guint32 ugly_idle_len; /*< how long a broken client has been idle */
--
-- DEBUG_INFO("%s has idle value 0x%x\n", NSTR(id), idle);
--
-- idle_len = time(NULL) - idle;
-- ugly_idle_len = ((time(NULL) * 1000) - idle) / 1000;
--
-- if(idle > ugly_idle_len)
-- ugly_idle_len = 0;
-- else
-- ugly_idle_len = (ugly_idle_len - idle) / 1000;
--
-- /*
-- what's the deal here? Well, good clients are smart enough to
-- publish their idle time by using an attribute to indicate that
-- they went idle at some time UTC, in seconds since epoch. Bad
-- clients use milliseconds since epoch. So we're going to compute
-- the idle time for either method, then figure out the lower of
-- the two and use that. Blame the ST 7.5 development team for
-- this.
-- */
--
-- DEBUG_INFO("idle time: %u, ugly idle time: %u\n", idle_len, ugly_idle_len);
--
--#if 1
-- if(idle_len <= ugly_idle_len) {
-- ; /* DEBUG_INFO("sane idle value, let's use it\n"); */
-- } else {
-- idle = time(NULL) - ugly_idle_len;
-- }
--
--#else
-- if(idle < 0 || idle > time(NULL)) {
-- DEBUG_INFO("hiding a messy idle value 0x%x\n", NSTR(id), idle);
-- idle = -1;
-- }
--#endif
-- }
--
-- switch(stat) {
-- case mwStatus_ACTIVE:
-- status = MW_STATE_ACTIVE;
-- idle = 0;
-- break;
--
-- case mwStatus_IDLE:
-- if(! idle) idle = -1;
-- break;
--
-- case mwStatus_AWAY:
-- status = MW_STATE_AWAY;
-- break;
--
-- case mwStatus_BUSY:
-- status = MW_STATE_BUSY;
-- break;
-- }
--
-- /* NAB group members */
-- if(aware->group) {
-- PurpleGroup *group;
-- PurpleBuddy *buddy;
-- PurpleBlistNode *bnode;
--
-- group = g_hash_table_lookup(pd->group_list_map, list);
-- buddy = purple_find_buddy_in_group(acct, id, group);
-- bnode = (PurpleBlistNode *) buddy;
--
-- if(! buddy) {
-- struct mwServiceResolve *srvc;
-- GList *query;
--
-- buddy = purple_buddy_new(acct, id, NULL);
-- purple_blist_add_buddy(buddy, NULL, group, NULL);
--
-- bnode = (PurpleBlistNode *) buddy;
--
-- srvc = pd->srvc_resolve;
-- query = g_list_append(NULL, (char *) id);
--
-- mwServiceResolve_resolve(srvc, query, mwResolveFlag_USERS,
-- blist_resolve_alias_cb, buddy, NULL);
-- g_list_free(query);
-- }
--
-- purple_blist_node_set_int(bnode, BUDDY_KEY_TYPE, mwSametimeUser_NORMAL);
-- }
--
-- if(aware->online) {
-- purple_prpl_got_user_status(acct, id, status, NULL);
-- purple_prpl_got_user_idle(acct, id, !!idle, (time_t) idle);
--
-- } else {
-- purple_prpl_got_user_status(acct, id, MW_STATE_OFFLINE, NULL);
-- }
--}
--
--
--static void mw_aware_list_on_attrib(struct mwAwareList *list,
-- struct mwAwareIdBlock *id,
-- struct mwAwareAttribute *attrib) {
--
-- ; /* nothing. We'll get attribute data as we need it */
--}
--
--
--static void mw_aware_list_clear(struct mwAwareList *list) {
-- ; /* nothing for now */
--}
--
--
--static struct mwAwareListHandler mw_aware_list_handler = {
-- mw_aware_list_on_aware,
-- mw_aware_list_on_attrib,
-- mw_aware_list_clear,
--};
--
--
--/** Ensures that an Aware List is associated with the given group, and
-- returns that list. */
--static struct mwAwareList *
--list_ensure(struct mwPurplePluginData *pd, PurpleGroup *group) {
--
-- struct mwAwareList *list;
--
-- g_return_val_if_fail(pd != NULL, NULL);
-- g_return_val_if_fail(group != NULL, NULL);
--
-- list = g_hash_table_lookup(pd->group_list_map, group);
-- if(! list) {
-- list = mwAwareList_new(pd->srvc_aware, &mw_aware_list_handler);
-- mwAwareList_setClientData(list, pd->gc, NULL);
--
-- mwAwareList_watchAttributes(list,
-- mwAttribute_AV_PREFS_SET,
-- mwAttribute_MICROPHONE,
-- mwAttribute_SPEAKERS,
-- mwAttribute_VIDEO_CAMERA,
-- mwAttribute_FILE_TRANSFER,
-- NULL);
--
-- g_hash_table_replace(pd->group_list_map, group, list);
-- g_hash_table_insert(pd->group_list_map, list, group);
-- }
--
-- return list;
--}
--
--
--static void blist_export(PurpleConnection *gc, struct mwSametimeList *stlist) {
-- /* - find the account for this connection
-- - iterate through the buddy list
-- - add each buddy matching this account to the stlist
-- */
--
-- PurpleAccount *acct;
-- PurpleBlistNode *gn, *cn, *bn;
-- PurpleGroup *grp;
-- PurpleBuddy *bdy;
--
-- struct mwSametimeGroup *stg = NULL;
-- struct mwIdBlock idb = { NULL, NULL };
--
-- acct = purple_connection_get_account(gc);
-- g_return_if_fail(acct != NULL);
--
-- for(gn = purple_blist_get_root(); gn;
-- gn = purple_blist_node_get_sibling_next(gn)) {
-- const char *owner;
-- const char *gname;
-- enum mwSametimeGroupType gtype;
-- gboolean gopen;
--
-- if(! PURPLE_BLIST_NODE_IS_GROUP(gn)) continue;
-- grp = (PurpleGroup *) gn;
--
-- /* the group's type (normal or dynamic) */
-- gtype = purple_blist_node_get_int(gn, GROUP_KEY_TYPE);
-- if(! gtype) gtype = mwSametimeGroup_NORMAL;
--
-- /* if it's a normal group with none of our people in it, skip it */
-- if(gtype == mwSametimeGroup_NORMAL && !purple_group_on_account(grp, acct))
-- continue;
--
-- /* if the group has an owner and we're not it, skip it */
-- owner = purple_blist_node_get_string(gn, GROUP_KEY_OWNER);
-- if(owner && strcmp(owner, purple_account_get_username(acct)))
-- continue;
--
-- /* the group's actual name may be different from the purple group's
-- name. Find whichever is there */
-- gname = purple_blist_node_get_string(gn, GROUP_KEY_NAME);
-- if(! gname) gname = purple_group_get_name(grp);
--
-- /* we save this, but never actually honor it */
-- gopen = ! purple_blist_node_get_bool(gn, GROUP_KEY_COLLAPSED);
--
-- stg = mwSametimeGroup_new(stlist, gtype, gname);
-- mwSametimeGroup_setAlias(stg, purple_group_get_name(grp));
-- mwSametimeGroup_setOpen(stg, gopen);
--
-- /* don't attempt to put buddies in a dynamic group, it breaks
-- other clients */
-- if(gtype == mwSametimeGroup_DYNAMIC)
-- continue;
--
-- for(cn = purple_blist_node_get_first_child(gn);
-- cn;
-- cn = purple_blist_node_get_sibling_next(cn)) {
-- if(! PURPLE_BLIST_NODE_IS_CONTACT(cn)) continue;
--
-- for(bn = purple_blist_node_get_first_child(cn);
-- bn;
-- bn = purple_blist_node_get_sibling_next(bn)) {
-- if(! PURPLE_BLIST_NODE_IS_BUDDY(bn)) continue;
-- if(! PURPLE_BLIST_NODE_SHOULD_SAVE(bn)) continue;
--
-- bdy = (PurpleBuddy *) bn;
--
-- if(purple_buddy_get_account(bdy) == acct) {
-- struct mwSametimeUser *stu;
-- enum mwSametimeUserType utype;
--
-- idb.user = (char *)purple_buddy_get_name(bdy);
--
-- utype = purple_blist_node_get_int(bn, BUDDY_KEY_TYPE);
-- if(! utype) utype = mwSametimeUser_NORMAL;
--
-- stu = mwSametimeUser_new(stg, utype, &idb);
-- mwSametimeUser_setShortName(stu, purple_buddy_get_server_alias(bdy));
-- mwSametimeUser_setAlias(stu, purple_buddy_get_local_buddy_alias(bdy));
-- }
-- }
-- }
-- }
--}
--
--
--static void blist_store(struct mwPurplePluginData *pd) {
--
-- struct mwSametimeList *stlist;
-- struct mwServiceStorage *srvc;
-- struct mwStorageUnit *unit;
--
-- PurpleConnection *gc;
--
-- struct mwPutBuffer *b;
-- struct mwOpaque *o;
--
-- g_return_if_fail(pd != NULL);
--
-- srvc = pd->srvc_store;
-- g_return_if_fail(srvc != NULL);
--
-- gc = pd->gc;
--
-- if(BLIST_PREF_IS_LOCAL() || BLIST_PREF_IS_MERGE()) {
-- DEBUG_INFO("preferences indicate not to save remote blist\n");
-- return;
--
-- } else if(MW_SERVICE_IS_DEAD(srvc)) {
-- DEBUG_INFO("aborting save of blist: storage service is not alive\n");
-- return;
--
-- } else if(BLIST_PREF_IS_STORE() || BLIST_PREF_IS_SYNCH()) {
-- DEBUG_INFO("saving remote blist\n");
--
-- } else {
-- g_return_if_reached();
-- }
--
-- /* create and export to a list object */
-- stlist = mwSametimeList_new();
-- blist_export(gc, stlist);
--
-- /* write it to a buffer */
-- b = mwPutBuffer_new();
-- mwSametimeList_put(b, stlist);
-- mwSametimeList_free(stlist);
--
-- /* put the buffer contents into a storage unit */
-- unit = mwStorageUnit_new(mwStore_AWARE_LIST);
-- o = mwStorageUnit_asOpaque(unit);
-- mwPutBuffer_finalize(o, b);
--
-- /* save the storage unit to the service */
-- mwServiceStorage_save(srvc, unit, NULL, NULL, NULL);
--}
--
--
--static gboolean blist_save_cb(gpointer data) {
-- struct mwPurplePluginData *pd = data;
--
-- blist_store(pd);
-- pd->save_event = 0;
-- return FALSE;
--}
--
--
--/** schedules the buddy list to be saved to the server */
--static void blist_schedule(struct mwPurplePluginData *pd) {
-- if(pd->save_event) return;
--
-- pd->save_event = purple_timeout_add_seconds(BLIST_SAVE_SECONDS,
-- blist_save_cb, pd);
--}
--
--
--static gboolean buddy_is_external(PurpleBuddy *b) {
-- g_return_val_if_fail(b != NULL, FALSE);
-- return purple_str_has_prefix(purple_buddy_get_name(b), "@E ");
--}
--
--
--/** Actually add a buddy to the aware service, and schedule the buddy
-- list to be saved to the server */
--static void buddy_add(struct mwPurplePluginData *pd,
-- PurpleBuddy *buddy) {
--
-- struct mwAwareIdBlock idb = { mwAware_USER, (char *) purple_buddy_get_name(buddy), NULL };
-- struct mwAwareList *list;
--
-- PurpleGroup *group;
-- GList *add;
--
-- add = g_list_prepend(NULL, &idb);
--
-- group = purple_buddy_get_group(buddy);
-- list = list_ensure(pd, group);
--
-- if(mwAwareList_addAware(list, add)) {
-- purple_blist_remove_buddy(buddy);
-- }
--
-- blist_schedule(pd);
--
-- g_list_free(add);
--}
--
--
--/** ensure that a PurpleBuddy exists in the group with data
-- appropriately matching the st user entry from the st list */
--static PurpleBuddy *buddy_ensure(PurpleConnection *gc, PurpleGroup *group,
-- struct mwSametimeUser *stuser) {
--
-- struct mwPurplePluginData *pd = gc->proto_data;
-- PurpleBuddy *buddy;
-- PurpleAccount *acct = purple_connection_get_account(gc);
--
-- const char *id = mwSametimeUser_getUser(stuser);
-- const char *name = mwSametimeUser_getShortName(stuser);
-- const char *alias = mwSametimeUser_getAlias(stuser);
-- enum mwSametimeUserType type = mwSametimeUser_getType(stuser);
--
-- g_return_val_if_fail(id != NULL, NULL);
-- g_return_val_if_fail(strlen(id) > 0, NULL);
--
-- buddy = purple_find_buddy_in_group(acct, id, group);
-- if(! buddy) {
-- buddy = purple_buddy_new(acct, id, alias);
--
-- purple_blist_add_buddy(buddy, NULL, group, NULL);
-- buddy_add(pd, buddy);
-- }
--
-- purple_blist_alias_buddy(buddy, alias);
-- purple_blist_server_alias_buddy(buddy, name);
-- purple_blist_node_set_string((PurpleBlistNode *) buddy, BUDDY_KEY_NAME, name);
-- purple_blist_node_set_int((PurpleBlistNode *) buddy, BUDDY_KEY_TYPE, type);
--
-- return buddy;
--}
--
--
--/** add aware watch for a dynamic group */
--static void group_add(struct mwPurplePluginData *pd,
-- PurpleGroup *group) {
--
-- struct mwAwareIdBlock idb = { mwAware_GROUP, NULL, NULL };
-- struct mwAwareList *list;
-- const char *n;
-- GList *add;
--
-- n = purple_blist_node_get_string((PurpleBlistNode *) group, GROUP_KEY_NAME);
-- if(! n) n = purple_group_get_name(group);
--
-- idb.user = (char *) n;
-- add = g_list_prepend(NULL, &idb);
--
-- list = list_ensure(pd, group);
-- mwAwareList_addAware(list, add);
-- g_list_free(add);
--}
--
--
--/** ensure that a PurpleGroup exists in the blist with data
-- appropriately matching the st group entry from the st list */
--static PurpleGroup *group_ensure(PurpleConnection *gc,
-- struct mwSametimeGroup *stgroup) {
-- PurpleAccount *acct;
-- PurpleGroup *group = NULL;
-- PurpleBuddyList *blist;
-- PurpleBlistNode *gn;
-- const char *name, *alias, *owner;
-- enum mwSametimeGroupType type;
--
-- acct = purple_connection_get_account(gc);
-- owner = purple_account_get_username(acct);
--
-- blist = purple_get_blist();
-- g_return_val_if_fail(blist != NULL, NULL);
--
-- name = mwSametimeGroup_getName(stgroup);
-- alias = mwSametimeGroup_getAlias(stgroup);
-- type = mwSametimeGroup_getType(stgroup);
--
-- if (!name) {
-- DEBUG_WARN("Can't ensure a null group\n");
-- return NULL;
-- }
--
-- if (!name) {
-- DEBUG_WARN("Can't ensure a null group\n");
-- return NULL;
-- }
--
-- DEBUG_INFO("attempting to ensure group %s, called %s\n",
-- NSTR(name), NSTR(alias));
--
-- /* first attempt at finding the group, by the name key */
-- for(gn = purple_blist_get_root(); gn;
-- gn = purple_blist_node_get_sibling_next(gn)) {
-- const char *n, *o;
-- if(! PURPLE_BLIST_NODE_IS_GROUP(gn)) continue;
-- n = purple_blist_node_get_string(gn, GROUP_KEY_NAME);
-- o = purple_blist_node_get_string(gn, GROUP_KEY_OWNER);
--
-- DEBUG_INFO("found group named %s, owned by %s\n", NSTR(n), NSTR(o));
--
-- if(n && !strcmp(n, name)) {
-- if(!o || !strcmp(o, owner)) {
-- DEBUG_INFO("that'll work\n");
-- group = (PurpleGroup *) gn;
-- break;
-- }
-- }
-- }
--
-- /* try again, by alias */
-- if(! group) {
-- DEBUG_INFO("searching for group by alias %s\n", NSTR(alias));
-- group = purple_find_group(alias);
-- }
--
-- /* oh well, no such group. Let's create it! */
-- if(! group) {
-- DEBUG_INFO("creating group\n");
-- group = purple_group_new(alias);
-- purple_blist_add_group(group, NULL);
-- }
--
-- gn = (PurpleBlistNode *) group;
-- purple_blist_node_set_string(gn, GROUP_KEY_NAME, name);
-- purple_blist_node_set_int(gn, GROUP_KEY_TYPE, type);
--
-- if(type == mwSametimeGroup_DYNAMIC) {
-- purple_blist_node_set_string(gn, GROUP_KEY_OWNER, owner);
-- group_add(gc->proto_data, group);
-- }
--
-- return group;
--}
--
--
--/** merge the entries from a st list into the purple blist */
--static void blist_merge(PurpleConnection *gc, struct mwSametimeList *stlist) {
-- struct mwSametimeGroup *stgroup;
-- struct mwSametimeUser *stuser;
--
-- PurpleGroup *group;
-- PurpleBuddy *buddy;
--
-- GList *gl, *gtl, *ul, *utl;
--
-- gl = gtl = mwSametimeList_getGroups(stlist);
-- for(; gl; gl = gl->next) {
--
-- stgroup = (struct mwSametimeGroup *) gl->data;
-- group = group_ensure(gc, stgroup);
--
-- ul = utl = mwSametimeGroup_getUsers(stgroup);
-- for(; ul; ul = ul->next) {
--
-- stuser = (struct mwSametimeUser *) ul->data;
-- buddy = buddy_ensure(gc, group, stuser);
-- }
-- g_list_free(utl);
-- }
-- g_list_free(gtl);
--}
--
--
--/** remove all buddies on account from group. If del is TRUE and group
-- is left empty, remove group as well */
--static void group_clear(PurpleGroup *group, PurpleAccount *acct, gboolean del) {
-- PurpleConnection *gc;
-- GList *prune = NULL;
-- PurpleBlistNode *gn, *cn, *bn;
--
-- g_return_if_fail(group != NULL);
--
-- DEBUG_INFO("clearing members from pruned group %s\n", NSTR(purple_group_get_name(group)));
--
-- gc = purple_account_get_connection(acct);
-- g_return_if_fail(gc != NULL);
--
-- gn = (PurpleBlistNode *) group;
--
-- for(cn = purple_blist_node_get_first_child(gn);
-- cn;
-- cn = purple_blist_node_get_sibling_next(cn)) {
-- if(! PURPLE_BLIST_NODE_IS_CONTACT(cn)) continue;
--
-- for(bn = purple_blist_node_get_first_child(cn);
-- bn;
-- bn = purple_blist_node_get_sibling_next(bn)) {
-- PurpleBuddy *gb = (PurpleBuddy *) bn;
--
-- if(! PURPLE_BLIST_NODE_IS_BUDDY(bn)) continue;
--
-- if(purple_buddy_get_account(gb) == acct) {
-- DEBUG_INFO("clearing %s from group\n", NSTR(purple_buddy_get_name(gb)));
-- prune = g_list_prepend(prune, gb);
-- }
-- }
-- }
--
-- /* quickly unsubscribe from presence for the entire group */
-- purple_account_remove_group(acct, group);
--
-- /* remove blist entries that need to go */
-- while(prune) {
-- purple_blist_remove_buddy(prune->data);
-- prune = g_list_delete_link(prune, prune);
-- }
-- DEBUG_INFO("cleared buddies\n");
--
-- /* optionally remove group from blist */
-- if(del && !purple_blist_get_group_size(group, TRUE)) {
-- DEBUG_INFO("removing empty group\n");
-- purple_blist_remove_group(group);
-- }
--}
--
--
--/** prune out group members that shouldn't be there */
--static void group_prune(PurpleConnection *gc, PurpleGroup *group,
-- struct mwSametimeGroup *stgroup) {
--
-- PurpleAccount *acct;
-- PurpleBlistNode *gn, *cn, *bn;
--
-- GHashTable *stusers;
-- GList *prune = NULL;
-- GList *ul, *utl;
--
-- g_return_if_fail(group != NULL);
--
-- DEBUG_INFO("pruning membership of group %s\n", NSTR(purple_group_get_name(group)));
--
-- acct = purple_connection_get_account(gc);
-- g_return_if_fail(acct != NULL);
--
-- stusers = g_hash_table_new(g_str_hash, g_str_equal);
--
-- /* build a hash table for quick lookup while pruning the group
-- contents */
-- utl = mwSametimeGroup_getUsers(stgroup);
-- for(ul = utl; ul; ul = ul->next) {
-- const char *id = mwSametimeUser_getUser(ul->data);
-- g_hash_table_insert(stusers, (char *) id, ul->data);
-- DEBUG_INFO("server copy has %s\n", NSTR(id));
-- }
-- g_list_free(utl);
--
-- gn = (PurpleBlistNode *) group;
--
-- for(cn = purple_blist_node_get_first_child(gn);
-- cn;
-- cn = purple_blist_node_get_sibling_next(cn)) {
-- if(! PURPLE_BLIST_NODE_IS_CONTACT(cn)) continue;
--
-- for(bn = purple_blist_node_get_first_child(cn);
-- bn;
-- bn = purple_blist_node_get_sibling_next(bn)) {
-- PurpleBuddy *gb = (PurpleBuddy *) bn;
--
-- if(! PURPLE_BLIST_NODE_IS_BUDDY(bn)) continue;
--
-- /* if the account is correct and they're not in our table, mark
-- them for pruning */
-- if(purple_buddy_get_account(gb) == acct && !g_hash_table_lookup(stusers, purple_buddy_get_name(gb))) {
-- DEBUG_INFO("marking %s for pruning\n", NSTR(purple_buddy_get_name(gb)));
-- prune = g_list_prepend(prune, gb);
-- }
-- }
-- }
-- DEBUG_INFO("done marking\n");
--
-- g_hash_table_destroy(stusers);
--
-- if(prune) {
-- purple_account_remove_buddies(acct, prune, NULL);
-- while(prune) {
-- purple_blist_remove_buddy(prune->data);
-- prune = g_list_delete_link(prune, prune);
-- }
-- }
--}
--
--
--/** synch the entries from a st list into the purple blist, removing any
-- existing buddies that aren't in the st list */
--static void blist_sync(PurpleConnection *gc, struct mwSametimeList *stlist) {
--
-- PurpleAccount *acct;
-- PurpleBuddyList *blist;
-- PurpleBlistNode *gn;
--
-- GHashTable *stgroups;
-- GList *g_prune = NULL;
--
-- GList *gl, *gtl;
--
-- const char *acct_n;
--
-- DEBUG_INFO("synchronizing local buddy list from server list\n");
--
-- acct = purple_connection_get_account(gc);
-- g_return_if_fail(acct != NULL);
--
-- acct_n = purple_account_get_username(acct);
--
-- blist = purple_get_blist();
-- g_return_if_fail(blist != NULL);
--
-- /* build a hash table for quick lookup while pruning the local
-- list, mapping group name to group structure */
-- stgroups = g_hash_table_new(g_str_hash, g_str_equal);
--
-- gtl = mwSametimeList_getGroups(stlist);
-- for(gl = gtl; gl; gl = gl->next) {
-- const char *name = mwSametimeGroup_getName(gl->data);
-- g_hash_table_insert(stgroups, (char *) name, gl->data);
-- }
-- g_list_free(gtl);
--
-- /* find all groups which should be pruned from the local list */
-- for(gn = purple_blist_get_root(); gn;
-- gn = purple_blist_node_get_sibling_next(gn)) {
-- PurpleGroup *grp = (PurpleGroup *) gn;
-- const char *gname, *owner;
-- struct mwSametimeGroup *stgrp;
--
-- if(! PURPLE_BLIST_NODE_IS_GROUP(gn)) continue;
--
-- /* group not belonging to this account */
-- if(! purple_group_on_account(grp, acct))
-- continue;
--
-- /* dynamic group belonging to this account. don't prune contents */
-- owner = purple_blist_node_get_string(gn, GROUP_KEY_OWNER);
-- if(owner && !strcmp(owner, acct_n))
-- continue;
--
-- /* we actually are synching by this key as opposed to the group
-- title, which can be different things in the st list */
-- gname = purple_blist_node_get_string(gn, GROUP_KEY_NAME);
-- if(! gname) gname = purple_group_get_name(grp);
--
-- stgrp = g_hash_table_lookup(stgroups, gname);
-- if(! stgrp) {
-- /* remove the whole group */
-- DEBUG_INFO("marking group %s for pruning\n", purple_group_get_name(grp));
-- g_prune = g_list_prepend(g_prune, grp);
--
-- } else {
-- /* synch the group contents */
-- group_prune(gc, grp, stgrp);
-- }
-- }
-- DEBUG_INFO("done marking groups\n");
--
-- /* don't need this anymore */
-- g_hash_table_destroy(stgroups);
--
-- /* prune all marked groups */
-- while(g_prune) {
-- PurpleGroup *grp = g_prune->data;
-- PurpleBlistNode *gn = (PurpleBlistNode *) grp;
-- const char *owner;
-- gboolean del = TRUE;
--
-- owner = purple_blist_node_get_string(gn, GROUP_KEY_OWNER);
-- if(owner && strcmp(owner, acct_n)) {
-- /* it's a specialty group belonging to another account with some
-- of our members in it, so don't fully delete it */
-- del = FALSE;
-- }
--
-- group_clear(g_prune->data, acct, del);
-- g_prune = g_list_delete_link(g_prune, g_prune);
-- }
--
-- /* done with the pruning, let's merge in the additions */
-- blist_merge(gc, stlist);
--}
--
--
--/** callback passed to the storage service when it's told to load the
-- st list */
--static void fetch_blist_cb(struct mwServiceStorage *srvc,
-- guint32 result, struct mwStorageUnit *item,
-- gpointer data) {
--
-- struct mwPurplePluginData *pd = data;
-- struct mwSametimeList *stlist;
--
-- struct mwGetBuffer *b;
--
-- g_return_if_fail(result == ERR_SUCCESS);
--
-- /* check our preferences for loading */
-- if(BLIST_PREF_IS_LOCAL()) {
-- DEBUG_INFO("preferences indicate not to load remote buddy list\n");
-- return;
-- }
--
-- b = mwGetBuffer_wrap(mwStorageUnit_asOpaque(item));
--
-- stlist = mwSametimeList_new();
-- mwSametimeList_get(b, stlist);
--
-- /* merge or synch depending on preferences */
-- if(BLIST_PREF_IS_MERGE() || BLIST_PREF_IS_STORE()) {
-- blist_merge(pd->gc, stlist);
--
-- } else if(BLIST_PREF_IS_SYNCH()) {
-- blist_sync(pd->gc, stlist);
-- }
--
-- mwSametimeList_free(stlist);
-- mwGetBuffer_free(b);
--}
--
--
--/** signal triggered when a conversation is opened in Purple */
--static void conversation_created_cb(PurpleConversation *g_conv,
-- struct mwPurplePluginData *pd) {
--
-- /* we need to tell the IM service to negotiate features for the
-- conversation right away, otherwise it'll wait until the first
-- message is sent before offering NotesBuddy features. Therefore
-- whenever Purple creates a conversation, we'll immediately open the
-- channel to the other side and figure out what the target can
-- handle. Unfortunately, this makes us vulnerable to Psychic Mode,
-- whereas a more lazy negotiation based on the first message
-- would not */
--
-- PurpleConnection *gc;
-- struct mwIdBlock who = { 0, 0 };
-- struct mwConversation *conv;
--
-- gc = purple_conversation_get_gc(g_conv);
-- if(pd->gc != gc)
-- return; /* not ours */
--
-- if(purple_conversation_get_type(g_conv) != PURPLE_CONV_TYPE_IM)
-- return; /* wrong type */
--
-- who.user = (char *) purple_conversation_get_name(g_conv);
-- conv = mwServiceIm_getConversation(pd->srvc_im, &who);
--
-- convo_features(conv);
--
-- if(mwConversation_isClosed(conv))
-- mwConversation_open(conv);
--}
--
--
--static void blist_menu_nab(PurpleBlistNode *node, gpointer data) {
-- struct mwPurplePluginData *pd = data;
-- PurpleConnection *gc;
--
-- PurpleGroup *group = (PurpleGroup *) node;
--
-- GString *str;
-- char *tmp;
-- const char *gname;
--
-- g_return_if_fail(pd != NULL);
--
-- gc = pd->gc;
-- g_return_if_fail(gc != NULL);
--
-- g_return_if_fail(PURPLE_BLIST_NODE_IS_GROUP(node));
--
-- str = g_string_new(NULL);
--
-- tmp = (char *) purple_blist_node_get_string(node, GROUP_KEY_NAME);
-- gname = purple_group_get_name(group);
--
-- g_string_append_printf(str, _("<b>Group Title:</b> %s<br>"), gname);
-- g_string_append_printf(str, _("<b>Notes Group ID:</b> %s<br>"), tmp);
--
-- tmp = g_strdup_printf(_("Info for Group %s"), gname);
--
-- purple_notify_formatted(gc, tmp, _("Notes Address Book Information"),
-- NULL, str->str, NULL, NULL);
--
-- g_free(tmp);
-- g_string_free(str, TRUE);
--}
--
--
--/** The normal blist menu prpl function doesn't get called for groups,
-- so we use the blist-node-extended-menu signal to trigger this
-- handler */
--static void blist_node_menu_cb(PurpleBlistNode *node,
-- GList **menu, struct mwPurplePluginData *pd) {
-- const char *owner;
-- PurpleGroup *group;
-- PurpleAccount *acct;
-- PurpleMenuAction *act;
--
-- /* we only want groups */
-- if(! PURPLE_BLIST_NODE_IS_GROUP(node)) return;
-- group = (PurpleGroup *) node;
--
-- acct = purple_connection_get_account(pd->gc);
-- g_return_if_fail(acct != NULL);
--
-- /* better make sure we're connected */
-- if(! purple_account_is_connected(acct)) return;
--
--#if 0
-- /* if there's anyone in the group for this acct, offer to invite
-- them all to a conference */
-- if(purple_group_on_account(group, acct)) {
-- act = purple_menu_action_new(_("Invite Group to Conference..."),
-- PURPLE_CALLBACK(blist_menu_group_invite),
-- pd, NULL);
-- *menu = g_list_append(*menu, NULL);
-- }
--#endif
--
-- /* check if it's a NAB group for this account */
-- owner = purple_blist_node_get_string(node, GROUP_KEY_OWNER);
-- if(owner && !strcmp(owner, purple_account_get_username(acct))) {
-- act = purple_menu_action_new(_("Get Notes Address Book Info"),
-- PURPLE_CALLBACK(blist_menu_nab), pd, NULL);
-- *menu = g_list_append(*menu, act);
-- }
--}
--
--
--/* lifted this from oldstatus, since HEAD doesn't do this at login
-- anymore. */
--static void blist_init(PurpleAccount *acct) {
-- PurpleBlistNode *gnode, *cnode, *bnode;
-- GList *add_buds = NULL;
--
-- for(gnode = purple_blist_get_root(); gnode;
-- gnode = purple_blist_node_get_sibling_next(gnode)) {
-- if(! PURPLE_BLIST_NODE_IS_GROUP(gnode)) continue;
--
-- for(cnode = purple_blist_node_get_first_child(gnode);
-- cnode;
-- cnode = purple_blist_node_get_sibling_next(cnode)) {
-- if(! PURPLE_BLIST_NODE_IS_CONTACT(cnode))
-- continue;
-- for(bnode = purple_blist_node_get_first_child(cnode);
-- bnode;
-- bnode = purple_blist_node_get_sibling_next(bnode)) {
-- PurpleBuddy *b;
-- if(!PURPLE_BLIST_NODE_IS_BUDDY(bnode))
-- continue;
--
-- b = (PurpleBuddy *)bnode;
-- if(purple_buddy_get_account(b) == acct) {
-- add_buds = g_list_append(add_buds, b);
-- }
-- }
-- }
-- }
--
-- if(add_buds) {
-- purple_account_add_buddies(acct, add_buds);
-- g_list_free(add_buds);
-- }
--}
--
--
--/** Last thing to happen from a started session */
--static void services_starting(struct mwPurplePluginData *pd) {
--
-- PurpleConnection *gc;
-- PurpleAccount *acct;
-- struct mwStorageUnit *unit;
-- PurpleBlistNode *l;
--
-- gc = pd->gc;
-- acct = purple_connection_get_account(gc);
--
-- /* grab the buddy list from the server */
-- unit = mwStorageUnit_new(mwStore_AWARE_LIST);
-- mwServiceStorage_load(pd->srvc_store, unit, fetch_blist_cb, pd, NULL);
--
-- /* find all the NAB groups and subscribe to them */
-- for(l = purple_blist_get_root(); l;
-- l = purple_blist_node_get_sibling_next(l)) {
-- PurpleGroup *group = (PurpleGroup *) l;
-- enum mwSametimeGroupType gt;
-- const char *owner;
--
-- if(! PURPLE_BLIST_NODE_IS_GROUP(l)) continue;
--
-- /* if the group is ownerless, or has an owner and we're not it,
-- skip it */
-- owner = purple_blist_node_get_string(l, GROUP_KEY_OWNER);
-- if(!owner || strcmp(owner, purple_account_get_username(acct)))
-- continue;
--
-- gt = purple_blist_node_get_int(l, GROUP_KEY_TYPE);
-- if(gt == mwSametimeGroup_DYNAMIC)
-- group_add(pd, group);
-- }
--
-- /* set the aware attributes */
-- /* indicate we understand what AV prefs are, but don't support any */
-- mwServiceAware_setAttributeBoolean(pd->srvc_aware,
-- mwAttribute_AV_PREFS_SET, TRUE);
-- mwServiceAware_unsetAttribute(pd->srvc_aware, mwAttribute_MICROPHONE);
-- mwServiceAware_unsetAttribute(pd->srvc_aware, mwAttribute_SPEAKERS);
-- mwServiceAware_unsetAttribute(pd->srvc_aware, mwAttribute_VIDEO_CAMERA);
--
-- /* ... but we can do file transfers! */
-- mwServiceAware_setAttributeBoolean(pd->srvc_aware,
-- mwAttribute_FILE_TRANSFER, TRUE);
--
-- blist_init(acct);
--}
--
--
--static void session_loginRedirect(struct mwSession *session,
-- const char *host) {
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- guint port;
-- const char *current_host;
--
-- pd = mwSession_getClientData(session);
-- gc = pd->gc;
-- account = purple_connection_get_account(gc);
-- port = purple_account_get_int(account, MW_KEY_PORT, MW_PLUGIN_DEFAULT_PORT);
-- current_host = purple_account_get_string(account, MW_KEY_HOST,
-- MW_PLUGIN_DEFAULT_HOST);
--
-- if(purple_account_get_bool(account, MW_KEY_FORCE, FALSE) ||
-- !host || (! strcmp(current_host, host)) ||
-- (purple_proxy_connect(gc, account, host, port, connect_cb, pd) == NULL)) {
--
-- /* if we're configured to force logins, or if we're being
-- redirected to the already configured host, or if we couldn't
-- connect to the new host, we'll force the login instead */
--
-- mwSession_forceLogin(session);
-- }
--}
--
--
--static void mw_prpl_set_status(PurpleAccount *acct, PurpleStatus *status);
--
--
--/** called from mw_session_stateChange when the session's state is
-- mwSession_STARTED. Any finalizing of start-up stuff should go
-- here */
--static void session_started(struct mwPurplePluginData *pd) {
-- PurpleStatus *status;
-- PurpleAccount *acct;
--
-- /* set out initial status */
-- acct = purple_connection_get_account(pd->gc);
-- status = purple_account_get_active_status(acct);
-- mw_prpl_set_status(acct, status);
--
-- /* start watching for new conversations */
-- purple_signal_connect(purple_conversations_get_handle(),
-- "conversation-created", pd,
-- PURPLE_CALLBACK(conversation_created_cb), pd);
--
-- /* watch for group extended menu items */
-- purple_signal_connect(purple_blist_get_handle(),
-- "blist-node-extended-menu", pd,
-- PURPLE_CALLBACK(blist_node_menu_cb), pd);
--
-- /* use our services to do neat things */
-- services_starting(pd);
--}
--
--
--static void session_stopping(struct mwPurplePluginData *pd) {
-- /* stop watching the signals from session_started */
-- purple_signals_disconnect_by_handle(pd);
--}
--
--
--static void mw_session_stateChange(struct mwSession *session,
-- enum mwSessionState state,
-- gpointer info) {
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
-- const char *msg = NULL;
--
-- pd = mwSession_getClientData(session);
-- gc = pd->gc;
--
-- switch(state) {
-- case mwSession_STARTING:
-- msg = _("Sending Handshake");
-- purple_connection_update_progress(gc, msg, 2, MW_CONNECT_STEPS);
-- break;
--
-- case mwSession_HANDSHAKE:
-- msg = _("Waiting for Handshake Acknowledgement");
-- purple_connection_update_progress(gc, msg, 3, MW_CONNECT_STEPS);
-- break;
--
-- case mwSession_HANDSHAKE_ACK:
-- msg = _("Handshake Acknowledged, Sending Login");
-- purple_connection_update_progress(gc, msg, 4, MW_CONNECT_STEPS);
-- break;
--
-- case mwSession_LOGIN:
-- msg = _("Waiting for Login Acknowledgement");
-- purple_connection_update_progress(gc, msg, 5, MW_CONNECT_STEPS);
-- break;
--
-- case mwSession_LOGIN_REDIR:
-- msg = _("Login Redirected");
-- purple_connection_update_progress(gc, msg, 6, MW_CONNECT_STEPS);
-- session_loginRedirect(session, info);
-- break;
--
-- case mwSession_LOGIN_CONT:
-- msg = _("Forcing Login");
-- purple_connection_update_progress(gc, msg, 7, MW_CONNECT_STEPS);
--
-- case mwSession_LOGIN_ACK:
-- msg = _("Login Acknowledged");
-- purple_connection_update_progress(gc, msg, 8, MW_CONNECT_STEPS);
-- break;
--
-- case mwSession_STARTED:
-- msg = _("Starting Services");
-- purple_connection_update_progress(gc, msg, 9, MW_CONNECT_STEPS);
--
-- session_started(pd);
--
-- msg = _("Connected");
-- purple_connection_update_progress(gc, msg, 10, MW_CONNECT_STEPS);
-- purple_connection_set_state(gc, PURPLE_CONNECTED);
-- break;
--
-- case mwSession_STOPPING:
--
-- session_stopping(pd);
--
-- if(GPOINTER_TO_UINT(info) & ERR_FAILURE) {
-- char *err = mwError(GPOINTER_TO_UINT(info));
-- PurpleConnectionError reason;
-- switch (GPOINTER_TO_UINT(info)) {
-- case VERSION_MISMATCH:
-- reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
-- break;
--
-- case USER_RESTRICTED:
-- case INCORRECT_LOGIN:
-- case USER_UNREGISTERED:
-- case GUEST_IN_USE:
-- reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
-- break;
--
-- case ENCRYPT_MISMATCH:
-- case ERR_ENCRYPT_NO_SUPPORT:
-- case ERR_NO_COMMON_ENCRYPT:
-- reason = PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR;
-- break;
--
-- case VERIFICATION_DOWN:
-- reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE;
-- break;
--
-- case MULTI_SERVER_LOGIN:
-- case MULTI_SERVER_LOGIN2:
-- reason = PURPLE_CONNECTION_ERROR_NAME_IN_USE;
-- break;
--
-- default:
-- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-- }
-- purple_connection_error_reason(gc, reason, err);
-- g_free(err);
-- }
-- break;
--
-- case mwSession_STOPPED:
-- break;
--
-- case mwSession_UNKNOWN:
-- default:
-- DEBUG_WARN("session in unknown state\n");
-- }
--}
--
--
--static void mw_session_setPrivacyInfo(struct mwSession *session) {
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
-- PurpleAccount *acct;
-- struct mwPrivacyInfo *privacy;
-- GSList *l, **ll;
-- guint count;
--
-- DEBUG_INFO("privacy information set from server\n");
--
-- g_return_if_fail(session != NULL);
--
-- pd = mwSession_getClientData(session);
-- g_return_if_fail(pd != NULL);
--
-- gc = pd->gc;
-- g_return_if_fail(gc != NULL);
--
-- acct = purple_connection_get_account(gc);
-- g_return_if_fail(acct != NULL);
--
-- privacy = mwSession_getPrivacyInfo(session);
-- count = privacy->count;
--
-- ll = (privacy->deny)? &acct->deny: &acct->permit;
-- for(l = *ll; l; l = l->next) g_free(l->data);
-- g_slist_free(*ll);
-- l = *ll = NULL;
--
-- while(count--) {
-- struct mwUserItem *u = privacy->users + count;
-- l = g_slist_prepend(l, g_strdup(u->id));
-- }
-- *ll = l;
--}
--
--
--static void mw_session_setUserStatus(struct mwSession *session) {
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
-- struct mwAwareIdBlock idb = { mwAware_USER, NULL, NULL };
-- struct mwUserStatus *stat;
--
-- g_return_if_fail(session != NULL);
--
-- pd = mwSession_getClientData(session);
-- g_return_if_fail(pd != NULL);
--
-- gc = pd->gc;
-- g_return_if_fail(gc != NULL);
--
-- idb.user = mwSession_getProperty(session, mwSession_AUTH_USER_ID);
-- stat = mwSession_getUserStatus(session);
--
-- /* trigger an update of our own status if we're in the buddy list */
-- mwServiceAware_setStatus(pd->srvc_aware, &idb, stat);
--}
--
--
--static void mw_session_admin(struct mwSession *session,
-- const char *text) {
-- PurpleConnection *gc;
-- PurpleAccount *acct;
-- const char *host;
-- const char *msg;
-- char *prim;
--
-- gc = session_to_gc(session);
-- g_return_if_fail(gc != NULL);
--
-- acct = purple_connection_get_account(gc);
-- g_return_if_fail(acct != NULL);
--
-- host = purple_account_get_string(acct, MW_KEY_HOST, NULL);
--
-- msg = _("A Sametime administrator has issued the following announcement"
-- " on server %s");
-- prim = g_strdup_printf(msg, NSTR(host));
--
-- purple_notify_message(gc, PURPLE_NOTIFY_MSG_INFO,
-- _("Sametime Administrator Announcement"),
-- prim, text, NULL, NULL);
--
-- g_free(prim);
--}
--
--
--/** called from read_cb, attempts to read available data from sock and
-- pass it to the session, passing back the return code from the read
-- call for handling in read_cb */
--static int read_recv(struct mwSession *session, int sock) {
-- guchar buf[BUF_LEN];
-- int len;
--
-- len = read(sock, buf, BUF_LEN);
-- if(len > 0) {
-- mwSession_recv(session, buf, len);
-- }
--
-- return len;
--}
--
--
--/** callback triggered from purple_input_add, watches the socked for
-- available data to be processed by the session */
--static void read_cb(gpointer data, gint source, PurpleInputCondition cond) {
-- struct mwPurplePluginData *pd = data;
-- int ret = 0, err = 0;
--
-- g_return_if_fail(pd != NULL);
--
-- ret = read_recv(pd->session, pd->socket);
--
-- /* normal operation ends here */
-- if(ret > 0) return;
--
-- /* fetch the global error value */
-- err = errno;
--
-- /* read problem occurred if we're here, so we'll need to take care of
-- it and clean up internal state */
--
-- if(pd->socket) {
-- close(pd->socket);
-- pd->socket = 0;
-- }
--
-- if(pd->gc->inpa) {
-- purple_input_remove(pd->gc->inpa);
-- pd->gc->inpa = 0;
-- }
--
-- if(! ret) {
-- DEBUG_INFO("connection reset\n");
-- purple_connection_error_reason(pd->gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Server closed the connection"));
--
-- } else if(ret < 0) {
-- const gchar *err_str = g_strerror(err);
-- char *msg = NULL;
--
-- DEBUG_INFO("error in read callback: %s\n", err_str);
--
-- msg = g_strdup_printf(_("Lost connection with server: %s"), err_str);
-- purple_connection_error_reason(pd->gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- msg);
-- g_free(msg);
-- }
--}
--
--
--/** Callback passed to purple_proxy_connect when an account is logged
-- in, and if the session logging in receives a redirect message */
--static void connect_cb(gpointer data, gint source, const gchar *error_message) {
--
-- struct mwPurplePluginData *pd = data;
-- PurpleConnection *gc = pd->gc;
--
-- if(source < 0) {
-- /* connection failed */
--
-- if(pd->socket) {
-- /* this is a redirect connect, force login on existing socket */
-- mwSession_forceLogin(pd->session);
--
-- } else {
-- /* this is a regular connect, error out */
-- gchar *tmp = g_strdup_printf(_("Unable to connect: %s"),
-- error_message);
-- purple_connection_error_reason(pd->gc,
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- tmp);
-- g_free(tmp);
-- }
--
-- return;
-- }
--
-- if(pd->socket) {
-- /* stop any existing login attempt */
-- mwSession_stop(pd->session, ERR_SUCCESS);
-- }
--
-- pd->socket = source;
-- gc->inpa = purple_input_add(source, PURPLE_INPUT_READ,
-- read_cb, pd);
--
-- mwSession_start(pd->session);
--}
--
--
--static void mw_session_announce(struct mwSession *s,
-- struct mwLoginInfo *from,
-- gboolean may_reply,
-- const char *text) {
-- struct mwPurplePluginData *pd;
-- PurpleAccount *acct;
-- PurpleConversation *conv;
-- PurpleBuddy *buddy;
-- char *who = from->user_id;
-- char *msg;
--
-- pd = mwSession_getClientData(s);
-- acct = purple_connection_get_account(pd->gc);
-- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, acct);
-- if(! conv) conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, who);
--
-- buddy = purple_find_buddy(acct, who);
-- if(buddy) who = (char *) purple_buddy_get_contact_alias(buddy);
--
-- who = g_strdup_printf(_("Announcement from %s"), who);
-- msg = purple_markup_linkify(text);
--
-- purple_conversation_write(conv, who, msg ? msg : "", PURPLE_MESSAGE_RECV, time(NULL));
-- g_free(who);
-- g_free(msg);
--}
--
--
--static struct mwSessionHandler mw_session_handler = {
-- mw_session_io_write,
-- mw_session_io_close,
-- mw_session_clear,
-- mw_session_stateChange,
-- mw_session_setPrivacyInfo,
-- mw_session_setUserStatus,
-- mw_session_admin,
-- mw_session_announce,
--};
--
--
--static void mw_aware_on_attrib(struct mwServiceAware *srvc,
-- struct mwAwareAttribute *attrib) {
--
-- ; /** @todo handle server attributes. There may be some stuff we
-- actually want to look for, but I'm not aware of anything right
-- now.*/
--}
--
--
--static void mw_aware_clear(struct mwServiceAware *srvc) {
-- ; /* nothing for now */
--}
--
--
--static struct mwAwareHandler mw_aware_handler = {
-- mw_aware_on_attrib,
-- mw_aware_clear,
--};
--
--
--static struct mwServiceAware *mw_srvc_aware_new(struct mwSession *s) {
-- struct mwServiceAware *srvc;
-- srvc = mwServiceAware_new(s, &mw_aware_handler);
-- return srvc;
--};
--
--
--static void mw_conf_invited(struct mwConference *conf,
-- struct mwLoginInfo *inviter,
-- const char *invitation) {
--
-- struct mwServiceConference *srvc;
-- struct mwSession *session;
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
--
-- char *c_inviter, *c_name, *c_topic, *c_invitation;
-- GHashTable *ht;
--
-- srvc = mwConference_getService(conf);
-- session = mwService_getSession(MW_SERVICE(srvc));
-- pd = mwSession_getClientData(session);
-- gc = pd->gc;
--
-- ht = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
--
-- c_inviter = g_strdup(inviter->user_id);
-- g_hash_table_insert(ht, CHAT_KEY_CREATOR, c_inviter);
--
-- c_name = g_strdup(mwConference_getName(conf));
-- g_hash_table_insert(ht, CHAT_KEY_NAME, c_name);
--
-- c_topic = g_strdup(mwConference_getTitle(conf));
-- g_hash_table_insert(ht, CHAT_KEY_TOPIC, c_topic);
--
-- c_invitation = g_strdup(invitation);
-- g_hash_table_insert(ht, CHAT_KEY_INVITE, c_invitation);
--
-- DEBUG_INFO("received invitation from '%s' to join ('%s','%s'): '%s'\n",
-- NSTR(c_inviter), NSTR(c_name),
-- NSTR(c_topic), NSTR(c_invitation));
--
-- if(! c_topic) c_topic = "(no title)";
-- if(! c_invitation) c_invitation = "(no message)";
-- serv_got_chat_invite(gc, c_topic, c_inviter, c_invitation, ht);
--}
--
--
--/* The following mess helps us relate a mwConference to a PurpleConvChat
-- in the various forms by which either may be indicated */
--
--#define CONF_TO_ID(conf) (GPOINTER_TO_INT(conf))
--#define ID_TO_CONF(pd, id) (conf_find_by_id((pd), (id)))
--
--#define CHAT_TO_ID(chat) (purple_conv_chat_get_id(chat))
--#define ID_TO_CHAT(id) (purple_find_chat(id))
--
--#define CHAT_TO_CONF(pd, chat) (ID_TO_CONF((pd), CHAT_TO_ID(chat)))
--#define CONF_TO_CHAT(conf) (ID_TO_CHAT(CONF_TO_ID(conf)))
--
--
--static struct mwConference *
--conf_find_by_id(struct mwPurplePluginData *pd, int id) {
--
-- struct mwServiceConference *srvc = pd->srvc_conf;
-- struct mwConference *conf = NULL;
-- GList *l, *ll;
--
-- ll = mwServiceConference_getConferences(srvc);
-- for(l = ll; l; l = l->next) {
-- struct mwConference *c = l->data;
-- PurpleConvChat *h = mwConference_getClientData(c);
--
-- if(CHAT_TO_ID(h) == id) {
-- conf = c;
-- break;
-- }
-- }
-- g_list_free(ll);
--
-- return conf;
--}
--
--
--static void mw_conf_opened(struct mwConference *conf, GList *members) {
-- struct mwServiceConference *srvc;
-- struct mwSession *session;
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
-- PurpleConversation *g_conf;
--
-- const char *n = mwConference_getName(conf);
-- const char *t = mwConference_getTitle(conf);
--
-- DEBUG_INFO("conf %s opened, %u initial members\n",
-- NSTR(n), g_list_length(members));
--
-- srvc = mwConference_getService(conf);
-- session = mwService_getSession(MW_SERVICE(srvc));
-- pd = mwSession_getClientData(session);
-- gc = pd->gc;
--
-- if(! t) t = "(no title)";
-- g_conf = serv_got_joined_chat(gc, CONF_TO_ID(conf), t);
--
-- mwConference_setClientData(conf, PURPLE_CONV_CHAT(g_conf), NULL);
--
-- for(; members; members = members->next) {
-- struct mwLoginInfo *peer = members->data;
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(g_conf), peer->user_id,
-- NULL, PURPLE_CBFLAGS_NONE, FALSE);
-- }
--}
--
--
--static void mw_conf_closed(struct mwConference *conf, guint32 reason) {
-- struct mwServiceConference *srvc;
-- struct mwSession *session;
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
--
-- const char *n = mwConference_getName(conf);
-- char *msg = mwError(reason);
--
-- DEBUG_INFO("conf %s closed, 0x%08x\n", NSTR(n), reason);
--
-- srvc = mwConference_getService(conf);
-- session = mwService_getSession(MW_SERVICE(srvc));
-- pd = mwSession_getClientData(session);
-- gc = pd->gc;
--
-- serv_got_chat_left(gc, CONF_TO_ID(conf));
--
-- purple_notify_error(gc, _("Conference Closed"), NULL, msg);
-- g_free(msg);
--}
--
--
--static void mw_conf_peer_joined(struct mwConference *conf,
-- struct mwLoginInfo *peer) {
--
-- struct mwServiceConference *srvc;
-- struct mwSession *session;
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
-- PurpleConvChat *g_conf;
--
-- const char *n = mwConference_getName(conf);
--
-- DEBUG_INFO("%s joined conf %s\n", NSTR(peer->user_id), NSTR(n));
--
-- srvc = mwConference_getService(conf);
-- session = mwService_getSession(MW_SERVICE(srvc));
-- pd = mwSession_getClientData(session);
-- gc = pd->gc;
--
-- g_conf = mwConference_getClientData(conf);
-- g_return_if_fail(g_conf != NULL);
--
-- purple_conv_chat_add_user(g_conf, peer->user_id,
-- NULL, PURPLE_CBFLAGS_NONE, TRUE);
--}
--
--
--static void mw_conf_peer_parted(struct mwConference *conf,
-- struct mwLoginInfo *peer) {
--
-- struct mwServiceConference *srvc;
-- struct mwSession *session;
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
-- PurpleConvChat *g_conf;
--
-- const char *n = mwConference_getName(conf);
--
-- DEBUG_INFO("%s left conf %s\n", NSTR(peer->user_id), NSTR(n));
--
-- srvc = mwConference_getService(conf);
-- session = mwService_getSession(MW_SERVICE(srvc));
-- pd = mwSession_getClientData(session);
-- gc = pd->gc;
--
-- g_conf = mwConference_getClientData(conf);
-- g_return_if_fail(g_conf != NULL);
--
-- purple_conv_chat_remove_user(g_conf, peer->user_id, NULL);
--}
--
--
--static void mw_conf_text(struct mwConference *conf,
-- struct mwLoginInfo *who, const char *text) {
--
-- struct mwServiceConference *srvc;
-- struct mwSession *session;
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
-- char *esc;
--
-- if(! text) return;
--
-- srvc = mwConference_getService(conf);
-- session = mwService_getSession(MW_SERVICE(srvc));
-- pd = mwSession_getClientData(session);
-- gc = pd->gc;
--
-- esc = g_markup_escape_text(text, -1);
-- serv_got_chat_in(gc, CONF_TO_ID(conf), who->user_id, 0, esc, time(NULL));
-- g_free(esc);
--}
--
--
--static void mw_conf_typing(struct mwConference *conf,
-- struct mwLoginInfo *who, gboolean typing) {
--
-- /* purple really has no good way to expose this to the user. */
--
-- const char *n = mwConference_getName(conf);
-- const char *w = who->user_id;
--
-- if(typing) {
-- DEBUG_INFO("%s in conf %s: <typing>\n", NSTR(w), NSTR(n));
--
-- } else {
-- DEBUG_INFO("%s in conf %s: <stopped typing>\n", NSTR(w), NSTR(n));
-- }
--}
--
--
--static void mw_conf_clear(struct mwServiceConference *srvc) {
-- ;
--}
--
--
--static struct mwConferenceHandler mw_conference_handler = {
-- mw_conf_invited,
-- mw_conf_opened,
-- mw_conf_closed,
-- mw_conf_peer_joined,
-- mw_conf_peer_parted,
-- mw_conf_text,
-- mw_conf_typing,
-- mw_conf_clear,
--};
--
--
--static struct mwServiceConference *mw_srvc_conf_new(struct mwSession *s) {
-- struct mwServiceConference *srvc;
-- srvc = mwServiceConference_new(s, &mw_conference_handler);
-- return srvc;
--}
--
--
--/** size of an outgoing file transfer chunk */
--#define MW_FT_LEN (BUF_LONG * 2)
--
--
--static void ft_incoming_cancel(PurpleXfer *xfer) {
-- /* incoming transfer rejected or cancelled in-progress */
-- struct mwFileTransfer *ft = xfer->data;
-- if(ft) mwFileTransfer_reject(ft);
--}
--
--
--static void ft_incoming_init(PurpleXfer *xfer) {
-- /* incoming transfer accepted */
--
-- /* - accept the mwFileTransfer
-- - open/create the local FILE "wb"
-- - stick the FILE's fp in xfer->dest_fp
-- */
--
-- struct mwFileTransfer *ft;
-- FILE *fp;
--
-- ft = xfer->data;
--
-- fp = g_fopen(xfer->local_filename, "wb");
-- if(! fp) {
-- mwFileTransfer_cancel(ft);
-- return;
-- }
--
-- xfer->dest_fp = fp;
-- mwFileTransfer_accept(ft);
--}
--
--
--static void mw_ft_offered(struct mwFileTransfer *ft) {
-- /*
-- - create a purple ft object
-- - offer it
-- */
--
-- struct mwServiceFileTransfer *srvc;
-- struct mwSession *session;
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
-- PurpleAccount *acct;
-- const char *who;
-- PurpleXfer *xfer;
--
-- /* @todo add some safety checks */
-- srvc = mwFileTransfer_getService(ft);
-- session = mwService_getSession(MW_SERVICE(srvc));
-- pd = mwSession_getClientData(session);
-- gc = pd->gc;
-- acct = purple_connection_get_account(gc);
--
-- who = mwFileTransfer_getUser(ft)->user;
--
-- DEBUG_INFO("file transfer %p offered\n", ft);
-- DEBUG_INFO(" from: %s\n", NSTR(who));
-- DEBUG_INFO(" file: %s\n", NSTR(mwFileTransfer_getFileName(ft)));
-- DEBUG_INFO(" size: %u\n", mwFileTransfer_getFileSize(ft));
-- DEBUG_INFO(" text: %s\n", NSTR(mwFileTransfer_getMessage(ft)));
--
-- xfer = purple_xfer_new(acct, PURPLE_XFER_RECEIVE, who);
-- if (xfer)
-- {
-- purple_xfer_ref(xfer);
-- mwFileTransfer_setClientData(ft, xfer, (GDestroyNotify) purple_xfer_unref);
-- xfer->data = ft;
--
-- purple_xfer_set_init_fnc(xfer, ft_incoming_init);
-- purple_xfer_set_cancel_recv_fnc(xfer, ft_incoming_cancel);
-- purple_xfer_set_request_denied_fnc(xfer, ft_incoming_cancel);
--
-- purple_xfer_set_filename(xfer, mwFileTransfer_getFileName(ft));
-- purple_xfer_set_size(xfer, mwFileTransfer_getFileSize(ft));
-- purple_xfer_set_message(xfer, mwFileTransfer_getMessage(ft));
--
-- purple_xfer_request(xfer);
-- }
--}
--
--
--static void ft_send(struct mwFileTransfer *ft, FILE *fp) {
-- guchar buf[MW_FT_LEN];
-- struct mwOpaque o = { MW_FT_LEN, buf };
-- guint32 rem;
-- PurpleXfer *xfer;
--
-- xfer = mwFileTransfer_getClientData(ft);
--
-- rem = mwFileTransfer_getRemaining(ft);
-- if(rem < MW_FT_LEN) o.len = rem;
--
-- if(fread(buf, (size_t) o.len, 1, fp)) {
--
-- /* calculate progress and display it */
-- xfer->bytes_sent += o.len;
-- xfer->bytes_remaining -= o.len;
-- purple_xfer_update_progress(xfer);
--
-- mwFileTransfer_send(ft, &o);
--
-- } else {
-- int err = errno;
-- DEBUG_WARN("problem reading from file %s: %s\n",
-- NSTR(mwFileTransfer_getFileName(ft)), g_strerror(err));
--
-- mwFileTransfer_cancel(ft);
-- }
--}
--
--
--static void mw_ft_opened(struct mwFileTransfer *ft) {
-- /*
-- - get purple ft from client data in ft
-- - set the state to active
-- */
--
-- PurpleXfer *xfer;
--
-- xfer = mwFileTransfer_getClientData(ft);
--
-- if(! xfer) {
-- mwFileTransfer_cancel(ft);
-- mwFileTransfer_free(ft);
-- g_return_if_reached();
-- }
--
-- if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
-- xfer->dest_fp = g_fopen(xfer->local_filename, "rb");
-- ft_send(ft, xfer->dest_fp);
-- }
--}
--
--
--static void mw_ft_closed(struct mwFileTransfer *ft, guint32 code) {
-- /*
-- - get purple ft from client data in ft
-- - indicate rejection/cancelation/completion
-- - free the file transfer itself
-- */
--
-- PurpleXfer *xfer;
--
-- xfer = mwFileTransfer_getClientData(ft);
-- if(xfer) {
-- xfer->data = NULL;
--
-- if(! mwFileTransfer_getRemaining(ft)) {
-- purple_xfer_set_completed(xfer, TRUE);
-- purple_xfer_end(xfer);
--
-- } else if(mwFileTransfer_isCancelLocal(ft)) {
-- /* calling purple_xfer_cancel_local is redundant, since that's
-- probably what triggered this function to be called */
-- ;
--
-- } else if(mwFileTransfer_isCancelRemote(ft)) {
-- /* steal the reference for the xfer */
-- mwFileTransfer_setClientData(ft, NULL, NULL);
-- purple_xfer_cancel_remote(xfer);
--
-- /* drop the stolen reference */
-- purple_xfer_unref(xfer);
-- return;
-- }
-- }
--
-- mwFileTransfer_free(ft);
--}
--
--
--static void mw_ft_recv(struct mwFileTransfer *ft,
-- struct mwOpaque *data) {
-- /*
-- - get purple ft from client data in ft
-- - update transfered percentage
-- - if done, destroy the ft, disassociate from purple ft
-- */
--
-- PurpleXfer *xfer;
-- FILE *fp;
-- size_t wc;
--
-- xfer = mwFileTransfer_getClientData(ft);
-- g_return_if_fail(xfer != NULL);
--
-- fp = xfer->dest_fp;
-- g_return_if_fail(fp != NULL);
--
-- /* we must collect and save our precious data */
-- wc = fwrite(data->data, 1, data->len, fp);
-- if (wc != data->len) {
-- DEBUG_ERROR("failed to write data\n");
-- purple_xfer_cancel_local(xfer);
-- return;
-- }
--
-- /* update the progress */
-- xfer->bytes_sent += data->len;
-- xfer->bytes_remaining -= data->len;
-- purple_xfer_update_progress(xfer);
--
-- /* let the other side know we got it, and to send some more */
-- mwFileTransfer_ack(ft);
--}
--
--
--static void mw_ft_ack(struct mwFileTransfer *ft) {
-- PurpleXfer *xfer;
--
-- xfer = mwFileTransfer_getClientData(ft);
-- g_return_if_fail(xfer != NULL);
-- g_return_if_fail(xfer->watcher == 0);
--
-- if(! mwFileTransfer_getRemaining(ft)) {
-- purple_xfer_set_completed(xfer, TRUE);
-- purple_xfer_end(xfer);
--
-- } else if(mwFileTransfer_isOpen(ft)) {
-- ft_send(ft, xfer->dest_fp);
-- }
--}
--
--
--static void mw_ft_clear(struct mwServiceFileTransfer *srvc) {
-- ;
--}
--
--
--static struct mwFileTransferHandler mw_ft_handler = {
-- mw_ft_offered,
-- mw_ft_opened,
-- mw_ft_closed,
-- mw_ft_recv,
-- mw_ft_ack,
-- mw_ft_clear,
--};
--
--
--static struct mwServiceFileTransfer *mw_srvc_ft_new(struct mwSession *s) {
-- struct mwServiceFileTransfer *srvc;
-- GHashTable *ft_map;
--
-- ft_map = g_hash_table_new(g_direct_hash, g_direct_equal);
--
-- srvc = mwServiceFileTransfer_new(s, &mw_ft_handler);
-- mwService_setClientData(MW_SERVICE(srvc), ft_map,
-- (GDestroyNotify) g_hash_table_destroy);
--
-- return srvc;
--}
--
--
--static void convo_data_free(struct convo_data *cd) {
-- GList *l;
--
-- /* clean the queue */
-- for(l = cd->queue; l; l = g_list_delete_link(l, l)) {
-- struct convo_msg *m = l->data;
-- if(m->clear) m->clear(m->data);
-- g_free(m);
-- }
--
-- g_free(cd);
--}
--
--
--/** allocates a convo_data structure and associates it with the
-- conversation in the client data slot */
--static void convo_data_new(struct mwConversation *conv) {
-- struct convo_data *cd;
--
-- g_return_if_fail(conv != NULL);
--
-- if(mwConversation_getClientData(conv))
-- return;
--
-- cd = g_new0(struct convo_data, 1);
-- cd->conv = conv;
--
-- mwConversation_setClientData(conv, cd, (GDestroyNotify) convo_data_free);
--}
--
--
--static PurpleConversation *convo_get_gconv(struct mwConversation *conv) {
-- struct mwServiceIm *srvc;
-- struct mwSession *session;
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
-- PurpleAccount *acct;
--
-- struct mwIdBlock *idb;
--
-- srvc = mwConversation_getService(conv);
-- session = mwService_getSession(MW_SERVICE(srvc));
-- pd = mwSession_getClientData(session);
-- gc = pd->gc;
-- acct = purple_connection_get_account(gc);
--
-- idb = mwConversation_getTarget(conv);
--
-- return purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-- idb->user, acct);
--}
--
--
--static void convo_queue(struct mwConversation *conv,
-- enum mwImSendType type, gconstpointer data) {
--
-- struct convo_data *cd;
-- struct convo_msg *m;
--
-- convo_data_new(conv);
-- cd = mwConversation_getClientData(conv);
--
-- m = g_new0(struct convo_msg, 1);
-- m->type = type;
--
-- switch(type) {
-- case mwImSend_PLAIN:
-- m->data = g_strdup(data);
-- m->clear = g_free;
-- break;
--
-- case mwImSend_TYPING:
-- default:
-- m->data = (gpointer) data;
-- m->clear = NULL;
-- }
--
-- cd->queue = g_list_append(cd->queue, m);
--}
--
--
--/* Does what it takes to get an error displayed for a conversation */
--static void convo_error(struct mwConversation *conv, guint32 err) {
-- PurpleConversation *gconv;
-- char *tmp, *text;
-- struct mwIdBlock *idb;
--
-- idb = mwConversation_getTarget(conv);
--
-- tmp = mwError(err);
-- text = g_strconcat(_("Unable to send message: "), tmp, NULL);
--
-- gconv = convo_get_gconv(conv);
-- if(gconv && !purple_conv_present_error(idb->user, gconv->account, text)) {
--
-- g_free(text);
-- text = g_strdup_printf(_("Unable to send message to %s:"),
-- (idb->user)? idb->user: "(unknown)");
-- purple_notify_error(purple_account_get_connection(gconv->account),
-- NULL, text, tmp);
-- }
--
-- g_free(tmp);
-- g_free(text);
--}
--
--
--static void convo_queue_send(struct mwConversation *conv) {
-- struct convo_data *cd;
-- GList *l;
--
-- cd = mwConversation_getClientData(conv);
--
-- for(l = cd->queue; l; l = g_list_delete_link(l, l)) {
-- struct convo_msg *m = l->data;
--
-- mwConversation_send(conv, m->type, m->data);
--
-- if(m->clear) m->clear(m->data);
-- g_free(m);
-- }
--
-- cd->queue = NULL;
--}
--
--
--/** called when a mw conversation leaves a purple conversation to
-- inform the purple conversation that it's unsafe to offer any *cool*
-- features. */
--static void convo_nofeatures(struct mwConversation *conv) {
-- PurpleConversation *gconv;
-- PurpleConnection *gc;
--
-- gconv = convo_get_gconv(conv);
-- if(! gconv) return;
--
-- gc = purple_conversation_get_gc(gconv);
-- if(! gc) return;
--
-- purple_conversation_set_features(gconv, gc->flags);
--}
--
--
--/** called when a mw conversation and purple conversation come together,
-- to inform the purple conversation of what features to offer the
-- user */
--static void convo_features(struct mwConversation *conv) {
-- PurpleConversation *gconv;
-- PurpleConnectionFlags feat;
--
-- gconv = convo_get_gconv(conv);
-- if(! gconv) return;
--
-- feat = purple_conversation_get_features(gconv);
--
-- if(mwConversation_isOpen(conv)) {
-- if(mwConversation_supports(conv, mwImSend_HTML)) {
-- feat |= PURPLE_CONNECTION_HTML;
-- } else {
-- feat &= ~PURPLE_CONNECTION_HTML;
-- }
--
-- if(mwConversation_supports(conv, mwImSend_MIME)) {
-- feat &= ~PURPLE_CONNECTION_NO_IMAGES;
-- } else {
-- feat |= PURPLE_CONNECTION_NO_IMAGES;
-- }
--
-- DEBUG_INFO("conversation features set to 0x%04x\n", feat);
-- purple_conversation_set_features(gconv, feat);
--
-- } else {
-- convo_nofeatures(conv);
-- }
--}
--
--
--static void mw_conversation_opened(struct mwConversation *conv) {
-- struct mwServiceIm *srvc;
-- struct mwSession *session;
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
-- PurpleAccount *acct;
--
-- struct convo_dat *cd;
--
-- srvc = mwConversation_getService(conv);
-- session = mwService_getSession(MW_SERVICE(srvc));
-- pd = mwSession_getClientData(session);
-- gc = pd->gc;
-- acct = purple_connection_get_account(gc);
--
-- /* set up the queue */
-- cd = mwConversation_getClientData(conv);
-- if(cd) {
-- convo_queue_send(conv);
--
-- if(! convo_get_gconv(conv)) {
-- mwConversation_free(conv);
-- return;
-- }
--
-- } else {
-- convo_data_new(conv);
-- }
--
-- { /* record the client key for the buddy */
-- PurpleBuddy *buddy;
-- struct mwLoginInfo *info;
-- info = mwConversation_getTargetInfo(conv);
--
-- buddy = purple_find_buddy(acct, info->user_id);
-- if(buddy) {
-- purple_blist_node_set_int((PurpleBlistNode *) buddy,
-- BUDDY_KEY_CLIENT, info->type);
-- }
-- }
--
-- convo_features(conv);
--}
--
--
--static void mw_conversation_closed(struct mwConversation *conv,
-- guint32 reason) {
--
-- struct convo_data *cd;
--
-- g_return_if_fail(conv != NULL);
--
-- /* if there's an error code and a non-typing message in the queue,
-- print an error message to the conversation */
-- cd = mwConversation_getClientData(conv);
-- if(reason && cd && cd->queue) {
-- GList *l;
-- for(l = cd->queue; l; l = l->next) {
-- struct convo_msg *m = l->data;
-- if(m->type != mwImSend_TYPING) {
-- convo_error(conv, reason);
-- break;
-- }
-- }
-- }
--
--#if 0
-- /* don't do this, to prevent the occasional weird sending of
-- formatted messages as plaintext when the other end closes the
-- conversation after we've begun composing the message */
-- convo_nofeatures(conv);
--#endif
--
-- mwConversation_removeClientData(conv);
--}
--
--
--static void im_recv_text(struct mwConversation *conv,
-- struct mwPurplePluginData *pd,
-- const char *msg) {
--
-- struct mwIdBlock *idb;
-- char *txt, *esc;
-- const char *t;
--
-- idb = mwConversation_getTarget(conv);
--
-- txt = purple_utf8_try_convert(msg);
-- t = txt? txt: msg;
--
-- esc = g_markup_escape_text(t, -1);
-- serv_got_im(pd->gc, idb->user, esc, 0, time(NULL));
-- g_free(esc);
--
-- g_free(txt);
--}
--
--
--static void im_recv_typing(struct mwConversation *conv,
-- struct mwPurplePluginData *pd,
-- gboolean typing) {
--
-- struct mwIdBlock *idb;
-- idb = mwConversation_getTarget(conv);
--
-- serv_got_typing(pd->gc, idb->user, 0,
-- typing? PURPLE_TYPING: PURPLE_NOT_TYPING);
--}
--
--
--static void im_recv_html(struct mwConversation *conv,
-- struct mwPurplePluginData *pd,
-- const char *msg) {
-- struct mwIdBlock *idb;
-- char *t1, *t2;
-- const char *t;
--
-- idb = mwConversation_getTarget(conv);
--
-- /* ensure we're receiving UTF8 */
-- t1 = purple_utf8_try_convert(msg);
-- t = t1? t1: msg;
--
-- /* convert entities to UTF8 so they'll log correctly */
-- t2 = purple_utf8_ncr_decode(t);
-- t = t2? t2: t;
--
-- serv_got_im(pd->gc, idb->user, t, 0, time(NULL));
--
-- g_free(t1);
-- g_free(t2);
--}
--
--
--static void im_recv_subj(struct mwConversation *conv,
-- struct mwPurplePluginData *pd,
-- const char *subj) {
--
-- /** @todo somehow indicate receipt of a conversation subject. It
-- would also be nice if we added a /topic command for the
-- protocol */
-- ;
--}
--
--
--/** generate "cid:908@20582notesbuddy" from "<908@20582notesbuddy>" */
--static char *make_cid(const char *cid) {
-- gsize n;
-- char *c, *d;
--
-- g_return_val_if_fail(cid != NULL, NULL);
--
-- n = strlen(cid);
-- g_return_val_if_fail(n > 2, NULL);
--
-- c = g_strndup(cid+1, n-2);
-- d = g_strdup_printf("cid:%s", c);
--
-- g_free(c);
-- return d;
--}
--
--
--static void im_recv_mime(struct mwConversation *conv,
-- struct mwPurplePluginData *pd,
-- const char *data) {
--
-- GHashTable *img_by_cid;
-- GList *images;
--
-- GString *str;
--
-- PurpleMimeDocument *doc;
-- GList *parts;
--
-- img_by_cid = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-- images = NULL;
--
-- /* don't want the contained string to ever be NULL */
-- str = g_string_new("");
--
-- doc = purple_mime_document_parse(data);
--
-- /* handle all the MIME parts */
-- parts = purple_mime_document_get_parts(doc);
-- for(; parts; parts = parts->next) {
-- PurpleMimePart *part = parts->data;
-- const char *type;
--
-- type = purple_mime_part_get_field(part, "content-type");
-- DEBUG_INFO("MIME part Content-Type: %s\n", NSTR(type));
--
-- if(! type) {
-- ; /* feh */
--
-- } else if(purple_str_has_prefix(type, "image")) {
-- /* put images into the image store */
--
-- guchar *d_dat;
-- gsize d_len;
-- char *cid;
-- int img;
--
-- /* obtain and unencode the data */
-- purple_mime_part_get_data_decoded(part, &d_dat, &d_len);
--
-- /* look up the content id */
-- cid = (char *) purple_mime_part_get_field(part, "Content-ID");
-- cid = make_cid(cid);
--
-- /* add image to the purple image store */
-- img = purple_imgstore_add_with_id(d_dat, d_len, cid);
--
-- /* map the cid to the image store identifier */
-- g_hash_table_insert(img_by_cid, cid, GINT_TO_POINTER(img));
--
-- /* recall the image for dereferencing later */
-- images = g_list_append(images, GINT_TO_POINTER(img));
--
-- } else if(purple_str_has_prefix(type, "text")) {
--
-- /* concatenate all the text parts together */
-- guchar *data;
-- gsize len;
--
-- purple_mime_part_get_data_decoded(part, &data, &len);
-- g_string_append(str, (const char *)data);
-- g_free(data);
-- }
-- }
--
-- purple_mime_document_free(doc);
--
-- /* @todo should put this in its own function */
-- { /* replace each IMG tag's SRC attribute with an ID attribute. This
-- actually modifies the contents of str */
-- GData *attribs;
-- char *start, *end;
-- char *tmp = str->str;
--
-- while(*tmp && purple_markup_find_tag("img", tmp, (const char **) &start,
-- (const char **) &end, &attribs)) {
--
-- char *alt, *align, *border, *src;
-- int img = 0;
--
-- alt = g_datalist_get_data(&attribs, "alt");
-- align = g_datalist_get_data(&attribs, "align");
-- border = g_datalist_get_data(&attribs, "border");
-- src = g_datalist_get_data(&attribs, "src");
--
-- if(src)
-- img = GPOINTER_TO_INT(g_hash_table_lookup(img_by_cid, src));
--
-- if(img) {
-- GString *atstr;
-- gsize len = (end - start);
-- gsize mov;
--
-- atstr = g_string_new("");
-- if(alt) g_string_append_printf(atstr, " alt=\"%s\"", alt);
-- if(align) g_string_append_printf(atstr, " align=\"%s\"", align);
-- if(border) g_string_append_printf(atstr, " border=\"%s\"", border);
--
-- mov = g_snprintf(start, len, "<img%s id=\"%i\"", atstr->str, img);
-- while(mov < len) start[mov++] = ' ';
--
-- g_string_free(atstr, TRUE);
-- }
--
-- g_datalist_clear(&attribs);
-- tmp = end + 1;
-- }
-- }
--
-- im_recv_html(conv, pd, str->str);
--
-- g_string_free(str, TRUE);
--
-- /* clean up the cid table */
-- g_hash_table_destroy(img_by_cid);
--
-- /* dereference all the imgages */
-- while(images) {
-- purple_imgstore_unref_by_id(GPOINTER_TO_INT(images->data));
-- images = g_list_delete_link(images, images);
-- }
--}
--
--
--static void mw_conversation_recv(struct mwConversation *conv,
-- enum mwImSendType type,
-- gconstpointer msg) {
-- struct mwServiceIm *srvc;
-- struct mwSession *session;
-- struct mwPurplePluginData *pd;
--
-- srvc = mwConversation_getService(conv);
-- session = mwService_getSession(MW_SERVICE(srvc));
-- pd = mwSession_getClientData(session);
--
-- switch(type) {
-- case mwImSend_PLAIN:
-- im_recv_text(conv, pd, msg);
-- break;
--
-- case mwImSend_TYPING:
-- im_recv_typing(conv, pd, !! msg);
-- break;
--
-- case mwImSend_HTML:
-- im_recv_html(conv, pd, msg);
-- break;
--
-- case mwImSend_SUBJECT:
-- im_recv_subj(conv, pd, msg);
-- break;
--
-- case mwImSend_MIME:
-- im_recv_mime(conv, pd, msg);
-- break;
--
-- default:
-- DEBUG_INFO("conversation received strange type, 0x%04x\n", type);
-- ; /* erm... */
-- }
--}
--
--
--static void mw_place_invite(struct mwConversation *conv,
-- const char *message,
-- const char *title, const char *name) {
-- struct mwServiceIm *srvc;
-- struct mwSession *session;
-- struct mwPurplePluginData *pd;
--
-- struct mwIdBlock *idb;
-- GHashTable *ht;
--
-- srvc = mwConversation_getService(conv);
-- session = mwService_getSession(MW_SERVICE(srvc));
-- pd = mwSession_getClientData(session);
--
-- idb = mwConversation_getTarget(conv);
--
-- ht = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
-- g_hash_table_insert(ht, CHAT_KEY_CREATOR, g_strdup(idb->user));
-- g_hash_table_insert(ht, CHAT_KEY_NAME, g_strdup(name));
-- g_hash_table_insert(ht, CHAT_KEY_TOPIC, g_strdup(title));
-- g_hash_table_insert(ht, CHAT_KEY_INVITE, g_strdup(message));
-- g_hash_table_insert(ht, CHAT_KEY_IS_PLACE, g_strdup("")); /* ugh */
--
-- if(! title) title = "(no title)";
-- if(! message) message = "(no message)";
-- serv_got_chat_invite(pd->gc, title, idb->user, message, ht);
--
-- mwConversation_close(conv, ERR_SUCCESS);
-- mwConversation_free(conv);
--}
--
--
--static void mw_im_clear(struct mwServiceIm *srvc) {
-- ;
--}
--
--
--static struct mwImHandler mw_im_handler = {
-- mw_conversation_opened,
-- mw_conversation_closed,
-- mw_conversation_recv,
-- mw_place_invite,
-- mw_im_clear,
--};
--
--
--static struct mwServiceIm *mw_srvc_im_new(struct mwSession *s) {
-- struct mwServiceIm *srvc;
-- srvc = mwServiceIm_new(s, &mw_im_handler);
-- mwServiceIm_setClientType(srvc, mwImClient_NOTESBUDDY);
-- return srvc;
--}
--
--
--/* The following helps us relate a mwPlace to a PurpleConvChat in the
-- various forms by which either may be indicated. Uses some of
-- the similar macros from the conference service above */
--
--#define PLACE_TO_ID(place) (GPOINTER_TO_INT(place))
--#define ID_TO_PLACE(pd, id) (place_find_by_id((pd), (id)))
--
--#define CHAT_TO_PLACE(pd, chat) (ID_TO_PLACE((pd), CHAT_TO_ID(chat)))
--#define PLACE_TO_CHAT(place) (ID_TO_CHAT(PLACE_TO_ID(place)))
--
--
--static struct mwPlace *
--place_find_by_id(struct mwPurplePluginData *pd, int id) {
-- struct mwServicePlace *srvc = pd->srvc_place;
-- struct mwPlace *place = NULL;
-- GList *l;
--
-- l = (GList *) mwServicePlace_getPlaces(srvc);
-- for(; l; l = l->next) {
-- struct mwPlace *p = l->data;
-- PurpleConvChat *h = PURPLE_CONV_CHAT(mwPlace_getClientData(p));
--
-- if(CHAT_TO_ID(h) == id) {
-- place = p;
-- break;
-- }
-- }
--
-- return place;
--}
--
--
--static void mw_place_opened(struct mwPlace *place) {
-- struct mwServicePlace *srvc;
-- struct mwSession *session;
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
-- PurpleConversation *gconf;
--
-- GList *members, *l;
--
-- const char *n = mwPlace_getName(place);
-- const char *t = mwPlace_getTitle(place);
--
-- srvc = mwPlace_getService(place);
-- session = mwService_getSession(MW_SERVICE(srvc));
-- pd = mwSession_getClientData(session);
-- gc = pd->gc;
--
-- members = mwPlace_getMembers(place);
--
-- DEBUG_INFO("place %s opened, %u initial members\n",
-- NSTR(n), g_list_length(members));
--
-- if(! t) t = "(no title)";
-- gconf = serv_got_joined_chat(gc, PLACE_TO_ID(place), t);
--
-- mwPlace_setClientData(place, gconf, NULL);
--
-- for(l = members; l; l = l->next) {
-- struct mwIdBlock *idb = l->data;
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(gconf), idb->user,
-- NULL, PURPLE_CBFLAGS_NONE, FALSE);
-- }
-- g_list_free(members);
--}
--
--
--static void mw_place_closed(struct mwPlace *place, guint32 code) {
-- struct mwServicePlace *srvc;
-- struct mwSession *session;
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
--
-- const char *n = mwPlace_getName(place);
-- char *msg = mwError(code);
--
-- DEBUG_INFO("place %s closed, 0x%08x\n", NSTR(n), code);
--
-- srvc = mwPlace_getService(place);
-- session = mwService_getSession(MW_SERVICE(srvc));
-- pd = mwSession_getClientData(session);
-- gc = pd->gc;
--
-- serv_got_chat_left(gc, PLACE_TO_ID(place));
--
-- purple_notify_error(gc, _("Place Closed"), NULL, msg);
-- g_free(msg);
--}
--
--
--static void mw_place_peerJoined(struct mwPlace *place,
-- const struct mwIdBlock *peer) {
-- struct mwServicePlace *srvc;
-- struct mwSession *session;
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
-- PurpleConversation *gconf;
--
-- const char *n = mwPlace_getName(place);
--
-- DEBUG_INFO("%s joined place %s\n", NSTR(peer->user), NSTR(n));
--
-- srvc = mwPlace_getService(place);
-- session = mwService_getSession(MW_SERVICE(srvc));
-- pd = mwSession_getClientData(session);
-- gc = pd->gc;
--
-- gconf = mwPlace_getClientData(place);
-- g_return_if_fail(gconf != NULL);
--
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(gconf), peer->user,
-- NULL, PURPLE_CBFLAGS_NONE, TRUE);
--}
--
--
--static void mw_place_peerParted(struct mwPlace *place,
-- const struct mwIdBlock *peer) {
-- struct mwServicePlace *srvc;
-- struct mwSession *session;
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
-- PurpleConversation *gconf;
--
-- const char *n = mwPlace_getName(place);
--
-- DEBUG_INFO("%s left place %s\n", NSTR(peer->user), NSTR(n));
--
-- srvc = mwPlace_getService(place);
-- session = mwService_getSession(MW_SERVICE(srvc));
-- pd = mwSession_getClientData(session);
-- gc = pd->gc;
--
-- gconf = mwPlace_getClientData(place);
-- g_return_if_fail(gconf != NULL);
--
-- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(gconf), peer->user, NULL);
--}
--
--
--static void mw_place_peerSetAttribute(struct mwPlace *place,
-- const struct mwIdBlock *peer,
-- guint32 attr, struct mwOpaque *o) {
-- ;
--}
--
--
--static void mw_place_peerUnsetAttribute(struct mwPlace *place,
-- const struct mwIdBlock *peer,
-- guint32 attr) {
-- ;
--}
--
--
--static void mw_place_message(struct mwPlace *place,
-- const struct mwIdBlock *who,
-- const char *msg) {
-- struct mwServicePlace *srvc;
-- struct mwSession *session;
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
-- char *esc;
--
-- if(! msg) return;
--
-- srvc = mwPlace_getService(place);
-- session = mwService_getSession(MW_SERVICE(srvc));
-- pd = mwSession_getClientData(session);
-- gc = pd->gc;
--
-- esc = g_markup_escape_text(msg, -1);
-- serv_got_chat_in(gc, PLACE_TO_ID(place), who->user, 0, esc, time(NULL));
-- g_free(esc);
--}
--
--
--static void mw_place_clear(struct mwServicePlace *srvc) {
-- ;
--}
--
--
--static struct mwPlaceHandler mw_place_handler = {
-- mw_place_opened,
-- mw_place_closed,
-- mw_place_peerJoined,
-- mw_place_peerParted,
-- mw_place_peerSetAttribute,
-- mw_place_peerUnsetAttribute,
-- mw_place_message,
-- mw_place_clear,
--};
--
--
--static struct mwServicePlace *mw_srvc_place_new(struct mwSession *s) {
-- struct mwServicePlace *srvc;
-- srvc = mwServicePlace_new(s, &mw_place_handler);
-- return srvc;
--}
--
--
--static struct mwServiceResolve *mw_srvc_resolve_new(struct mwSession *s) {
-- struct mwServiceResolve *srvc;
-- srvc = mwServiceResolve_new(s);
-- return srvc;
--}
--
--
--static struct mwServiceStorage *mw_srvc_store_new(struct mwSession *s) {
-- struct mwServiceStorage *srvc;
-- srvc = mwServiceStorage_new(s);
-- return srvc;
--}
--
--
--/** allocate and associate a mwPurplePluginData with a PurpleConnection */
--static struct mwPurplePluginData *mwPurplePluginData_new(PurpleConnection *gc) {
-- struct mwPurplePluginData *pd;
--
-- g_return_val_if_fail(gc != NULL, NULL);
--
-- pd = g_new0(struct mwPurplePluginData, 1);
-- pd->gc = gc;
-- pd->session = mwSession_new(&mw_session_handler);
-- pd->srvc_aware = mw_srvc_aware_new(pd->session);
-- pd->srvc_conf = mw_srvc_conf_new(pd->session);
-- pd->srvc_ft = mw_srvc_ft_new(pd->session);
-- pd->srvc_im = mw_srvc_im_new(pd->session);
-- pd->srvc_place = mw_srvc_place_new(pd->session);
-- pd->srvc_resolve = mw_srvc_resolve_new(pd->session);
-- pd->srvc_store = mw_srvc_store_new(pd->session);
-- pd->group_list_map = g_hash_table_new(g_direct_hash, g_direct_equal);
-- pd->sock_buf = purple_circ_buffer_new(0);
--
-- mwSession_addService(pd->session, MW_SERVICE(pd->srvc_aware));
-- mwSession_addService(pd->session, MW_SERVICE(pd->srvc_conf));
-- mwSession_addService(pd->session, MW_SERVICE(pd->srvc_ft));
-- mwSession_addService(pd->session, MW_SERVICE(pd->srvc_im));
-- mwSession_addService(pd->session, MW_SERVICE(pd->srvc_place));
-- mwSession_addService(pd->session, MW_SERVICE(pd->srvc_resolve));
-- mwSession_addService(pd->session, MW_SERVICE(pd->srvc_store));
--
-- mwSession_addCipher(pd->session, mwCipher_new_RC2_40(pd->session));
-- mwSession_addCipher(pd->session, mwCipher_new_RC2_128(pd->session));
--
-- mwSession_setClientData(pd->session, pd, NULL);
-- gc->proto_data = pd;
--
-- return pd;
--}
--
--
--static void mwPurplePluginData_free(struct mwPurplePluginData *pd) {
-- g_return_if_fail(pd != NULL);
--
-- pd->gc->proto_data = NULL;
--
-- mwSession_removeService(pd->session, mwService_AWARE);
-- mwSession_removeService(pd->session, mwService_CONFERENCE);
-- mwSession_removeService(pd->session, mwService_FILE_TRANSFER);
-- mwSession_removeService(pd->session, mwService_IM);
-- mwSession_removeService(pd->session, mwService_PLACE);
-- mwSession_removeService(pd->session, mwService_RESOLVE);
-- mwSession_removeService(pd->session, mwService_STORAGE);
--
-- mwService_free(MW_SERVICE(pd->srvc_aware));
-- mwService_free(MW_SERVICE(pd->srvc_conf));
-- mwService_free(MW_SERVICE(pd->srvc_ft));
-- mwService_free(MW_SERVICE(pd->srvc_im));
-- mwService_free(MW_SERVICE(pd->srvc_place));
-- mwService_free(MW_SERVICE(pd->srvc_resolve));
-- mwService_free(MW_SERVICE(pd->srvc_store));
--
-- mwCipher_free(mwSession_getCipher(pd->session, mwCipher_RC2_40));
-- mwCipher_free(mwSession_getCipher(pd->session, mwCipher_RC2_128));
--
-- mwSession_free(pd->session);
--
-- g_hash_table_destroy(pd->group_list_map);
-- purple_circ_buffer_destroy(pd->sock_buf);
--
-- g_free(pd);
--}
--
--
--static const char *mw_prpl_list_icon(PurpleAccount *a, PurpleBuddy *b) {
-- /* my little green dude is a chopped up version of the aim running
-- guy. First, cut off the head and store someplace safe. Then,
-- take the left-half side of the body and throw it away. Make a
-- copy of the remaining body, and flip it horizontally. Now attach
-- the two pieces into an X shape, and drop the head back on the
-- top, being careful to center it. Then, just change the color
-- saturation to bring the red down a bit, and voila! */
--
-- /* then, throw all of that away and use sodipodi to make a new
-- icon. You know, LIKE A REAL MAN. */
--
-- return "meanwhile";
--}
--
--
--static const char* mw_prpl_list_emblem(PurpleBuddy *b)
--{
-- if(buddy_is_external(b))
-- return "external";
--
-- return NULL;
--}
--
--
--static char *mw_prpl_status_text(PurpleBuddy *b) {
-- PurpleConnection *gc;
-- struct mwPurplePluginData *pd;
-- struct mwAwareIdBlock t = { mwAware_USER, (char *)purple_buddy_get_name(b), NULL };
-- const char *ret = NULL;
--
-- if ((gc = purple_account_get_connection(purple_buddy_get_account(b)))
-- && (pd = gc->proto_data))
-- ret = mwServiceAware_getText(pd->srvc_aware, &t);
--
-- return (ret && g_utf8_validate(ret, -1, NULL)) ? g_markup_escape_text(ret, -1): NULL;
--}
--
--
--static const char *status_text(PurpleBuddy *b) {
-- PurplePresence *presence;
-- PurpleStatus *status;
--
-- presence = purple_buddy_get_presence(b);
-- status = purple_presence_get_active_status(presence);
--
-- return purple_status_get_name(status);
--}
--
--
--static gboolean user_supports(struct mwServiceAware *srvc,
-- const char *who, guint32 feature) {
--
-- const struct mwAwareAttribute *attr;
-- struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL };
--
-- attr = mwServiceAware_getAttribute(srvc, &idb, feature);
-- return (attr != NULL) && mwAwareAttribute_asBoolean(attr);
--}
--
--
--static char *user_supports_text(struct mwServiceAware *srvc, const char *who) {
-- const char *feat[] = {NULL, NULL, NULL, NULL, NULL};
-- const char **f = feat;
--
-- if(user_supports(srvc, who, mwAttribute_AV_PREFS_SET)) {
-- gboolean mic, speak, video;
--
-- mic = user_supports(srvc, who, mwAttribute_MICROPHONE);
-- speak = user_supports(srvc, who, mwAttribute_SPEAKERS);
-- video = user_supports(srvc, who, mwAttribute_VIDEO_CAMERA);
--
-- if(mic) *f++ = _("Microphone");
-- if(speak) *f++ = _("Speakers");
-- if(video) *f++ = _("Video Camera");
-- }
--
-- if(user_supports(srvc, who, mwAttribute_FILE_TRANSFER))
-- *f++ = _("File Transfer");
--
-- return (*feat)? g_strjoinv(", ", (char **)feat): NULL;
-- /* jenni loves siege */
--}
--
--
--static void mw_prpl_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) {
-- PurpleConnection *gc;
-- struct mwPurplePluginData *pd = NULL;
-- struct mwAwareIdBlock idb = { mwAware_USER, (char *)purple_buddy_get_name(b), NULL };
--
-- const char *message = NULL;
-- const char *status;
-- char *tmp;
--
-- if ((gc = purple_account_get_connection(purple_buddy_get_account(b)))
-- && (pd = gc->proto_data))
-- message = mwServiceAware_getText(pd->srvc_aware, &idb);
--
-- status = status_text(b);
--
-- if(message != NULL && g_utf8_validate(message, -1, NULL) && purple_utf8_strcasecmp(status, message)) {
-- tmp = g_markup_escape_text(message, -1);
-- purple_notify_user_info_add_pair(user_info, status, tmp);
-- g_free(tmp);
--
-- } else {
-- purple_notify_user_info_add_pair(user_info, _("Status"), status);
-- }
--
-- if(full && pd != NULL) {
-- tmp = user_supports_text(pd->srvc_aware, purple_buddy_get_name(b));
-- if(tmp) {
-- purple_notify_user_info_add_pair(user_info, _("Supports"), tmp);
-- g_free(tmp);
-- }
--
-- if(buddy_is_external(b)) {
-- purple_notify_user_info_add_pair(user_info, NULL, _("External User"));
-- }
-- }
--}
--
--static GList *mw_prpl_status_types(PurpleAccount *acct)
--{
-- GList *types = NULL;
-- PurpleStatusType *type;
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
-- MW_STATE_ACTIVE, NULL, TRUE, TRUE, FALSE,
-- MW_STATE_MESSAGE, _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- types = g_list_append(types, type);
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY,
-- MW_STATE_AWAY, NULL, TRUE, TRUE, FALSE,
-- MW_STATE_MESSAGE, _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- types = g_list_append(types, type);
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE,
-- MW_STATE_BUSY, _("Do Not Disturb"), TRUE, TRUE, FALSE,
-- MW_STATE_MESSAGE, _("Message"), purple_value_new(PURPLE_TYPE_STRING),
-- NULL);
-- types = g_list_append(types, type);
--
-- type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE,
-- MW_STATE_OFFLINE, NULL, TRUE, TRUE, FALSE);
-- types = g_list_append(types, type);
--
-- return types;
--}
--
--
--static void conf_create_prompt_cancel(PurpleBuddy *buddy,
-- PurpleRequestFields *fields) {
-- ; /* nothing to do */
--}
--
--
--static void conf_create_prompt_join(PurpleBuddy *buddy,
-- PurpleRequestFields *fields) {
-- PurpleAccount *acct;
-- PurpleConnection *gc;
-- struct mwPurplePluginData *pd;
-- struct mwServiceConference *srvc;
--
-- PurpleRequestField *f;
--
-- const char *topic, *invite;
-- struct mwConference *conf;
-- struct mwIdBlock idb = { NULL, NULL };
--
-- acct = purple_buddy_get_account(buddy);
-- gc = purple_account_get_connection(acct);
-- pd = gc->proto_data;
-- srvc = pd->srvc_conf;
--
-- f = purple_request_fields_get_field(fields, CHAT_KEY_TOPIC);
-- topic = purple_request_field_string_get_value(f);
--
-- f = purple_request_fields_get_field(fields, CHAT_KEY_INVITE);
-- invite = purple_request_field_string_get_value(f);
--
-- conf = mwConference_new(srvc, topic);
-- mwConference_open(conf);
--
-- idb.user = (char *)purple_buddy_get_name(buddy);
-- mwConference_invite(conf, &idb, invite);
--}
--
--
--static void blist_menu_conf_create(PurpleBuddy *buddy, const char *msg) {
--
-- PurpleRequestFields *fields;
-- PurpleRequestFieldGroup *g;
-- PurpleRequestField *f;
--
-- PurpleAccount *acct;
-- PurpleConnection *gc;
--
-- const char *msgA;
-- const char *msgB;
-- char *msg1;
--
-- g_return_if_fail(buddy != NULL);
--
-- acct = purple_buddy_get_account(buddy);
-- g_return_if_fail(acct != NULL);
--
-- gc = purple_account_get_connection(acct);
-- g_return_if_fail(gc != NULL);
--
-- fields = purple_request_fields_new();
--
-- g = purple_request_field_group_new(NULL);
-- purple_request_fields_add_group(fields, g);
--
-- f = purple_request_field_string_new(CHAT_KEY_TOPIC, _("Topic"), NULL, FALSE);
-- purple_request_field_group_add_field(g, f);
--
-- f = purple_request_field_string_new(CHAT_KEY_INVITE, _("Message"), msg, FALSE);
-- purple_request_field_group_add_field(g, f);
--
-- msgA = _("Create conference with user");
-- msgB = _("Please enter a topic for the new conference, and an invitation"
-- " message to be sent to %s");
-- msg1 = g_strdup_printf(msgB, purple_buddy_get_name(buddy));
--
-- purple_request_fields(gc, _("New Conference"),
-- msgA, msg1, fields,
-- _("Create"), G_CALLBACK(conf_create_prompt_join),
-- _("Cancel"), G_CALLBACK(conf_create_prompt_cancel),
-- acct, purple_buddy_get_name(buddy), NULL,
-- buddy);
-- g_free(msg1);
--}
--
--
--static void conf_select_prompt_cancel(PurpleBuddy *buddy,
-- PurpleRequestFields *fields) {
-- ;
--}
--
--
--static void conf_select_prompt_invite(PurpleBuddy *buddy,
-- PurpleRequestFields *fields) {
-- PurpleRequestField *f;
-- GList *l;
-- const char *msg;
--
-- f = purple_request_fields_get_field(fields, CHAT_KEY_INVITE);
-- msg = purple_request_field_string_get_value(f);
--
-- f = purple_request_fields_get_field(fields, "conf");
-- l = purple_request_field_list_get_selected(f);
--
-- if(l) {
-- gpointer d = purple_request_field_list_get_data(f, l->data);
--
-- if(GPOINTER_TO_INT(d) == 0x01) {
-- blist_menu_conf_create(buddy, msg);
--
-- } else {
-- struct mwIdBlock idb = { (char *)purple_buddy_get_name(buddy), NULL };
-- mwConference_invite(d, &idb, msg);
-- }
-- }
--}
--
--
--static void blist_menu_conf_list(PurpleBuddy *buddy,
-- GList *confs) {
--
-- PurpleRequestFields *fields;
-- PurpleRequestFieldGroup *g;
-- PurpleRequestField *f;
--
-- PurpleAccount *acct;
-- PurpleConnection *gc;
--
-- const char *msgA;
-- const char *msgB;
-- char *msg;
--
-- acct = purple_buddy_get_account(buddy);
-- g_return_if_fail(acct != NULL);
--
-- gc = purple_account_get_connection(acct);
-- g_return_if_fail(gc != NULL);
--
-- fields = purple_request_fields_new();
--
-- g = purple_request_field_group_new(NULL);
-- purple_request_fields_add_group(fields, g);
--
-- f = purple_request_field_list_new("conf", _("Available Conferences"));
-- purple_request_field_list_set_multi_select(f, FALSE);
-- for(; confs; confs = confs->next) {
-- struct mwConference *c = confs->data;
-- purple_request_field_list_add_icon(f, mwConference_getTitle(c), NULL, c);
-- }
-- purple_request_field_list_add_icon(f, _("Create New Conference..."),
-- NULL, GINT_TO_POINTER(0x01));
-- purple_request_field_group_add_field(g, f);
--
-- f = purple_request_field_string_new(CHAT_KEY_INVITE, "Message", NULL, FALSE);
-- purple_request_field_group_add_field(g, f);
--
-- msgA = _("Invite user to a conference");
-- msgB = _("Select a conference from the list below to send an invite to"
-- " user %s. Select \"Create New Conference\" if you'd like to"
-- " create a new conference to invite this user to.");
-- msg = g_strdup_printf(msgB, purple_buddy_get_name(buddy));
--
-- purple_request_fields(gc, _("Invite to Conference"),
-- msgA, msg, fields,
-- _("Invite"), G_CALLBACK(conf_select_prompt_invite),
-- _("Cancel"), G_CALLBACK(conf_select_prompt_cancel),
-- acct, purple_buddy_get_name(buddy), NULL,
-- buddy);
-- g_free(msg);
--}
--
--
--static void blist_menu_conf(PurpleBlistNode *node, gpointer data) {
-- PurpleBuddy *buddy = (PurpleBuddy *) node;
-- PurpleAccount *acct;
-- PurpleConnection *gc;
-- struct mwPurplePluginData *pd;
-- GList *l;
--
-- g_return_if_fail(node != NULL);
-- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
--
-- acct = purple_buddy_get_account(buddy);
-- g_return_if_fail(acct != NULL);
--
-- gc = purple_account_get_connection(acct);
-- g_return_if_fail(gc != NULL);
--
-- pd = gc->proto_data;
-- g_return_if_fail(pd != NULL);
--
-- /*
-- - get a list of all conferences on this session
-- - if none, prompt to create one, and invite buddy to it
-- - else, prompt to select a conference or create one
-- */
--
-- l = mwServiceConference_getConferences(pd->srvc_conf);
-- if(l) {
-- blist_menu_conf_list(buddy, l);
-- g_list_free(l);
--
-- } else {
-- blist_menu_conf_create(buddy, NULL);
-- }
--}
--
--
--#if 0
--static void blist_menu_announce(PurpleBlistNode *node, gpointer data) {
-- PurpleBuddy *buddy = (PurpleBuddy *) node;
-- PurpleAccount *acct;
-- PurpleConnection *gc;
-- struct mwPurplePluginData *pd;
-- struct mwSession *session;
-- char *rcpt_name;
-- GList *rcpt;
--
-- g_return_if_fail(node != NULL);
-- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
--
-- acct = buddy->account;
-- g_return_if_fail(acct != NULL);
--
-- gc = purple_account_get_connection(acct);
-- g_return_if_fail(gc != NULL);
--
-- pd = gc->proto_data;
-- g_return_if_fail(pd != NULL);
--
-- rcpt_name = g_strdup_printf("@U %s", buddy->name);
-- rcpt = g_list_prepend(NULL, rcpt_name);
--
-- session = pd->session;
-- mwSession_sendAnnounce(session, FALSE,
-- "This is a TEST announcement. Please ignore.",
-- rcpt);
--
-- g_list_free(rcpt);
-- g_free(rcpt_name);
--}
--#endif
--
--
--static GList *mw_prpl_blist_node_menu(PurpleBlistNode *node) {
-- GList *l = NULL;
-- PurpleMenuAction *act;
--
-- if(! PURPLE_BLIST_NODE_IS_BUDDY(node))
-- return l;
--
-- l = g_list_append(l, NULL);
--
-- act = purple_menu_action_new(_("Invite to Conference..."),
-- PURPLE_CALLBACK(blist_menu_conf), NULL, NULL);
-- l = g_list_append(l, act);
--
--#if 0
-- act = purple_menu_action_new(_("Send TEST Announcement"),
-- PURPLE_CALLBACK(blist_menu_announce), NULL, NULL);
-- l = g_list_append(l, act);
--#endif
--
-- /** note: this never gets called for a PurpleGroup, have to use the
-- blist-node-extended-menu signal for that. The function
-- blist_node_menu_cb is assigned to this signal in the function
-- services_starting */
--
-- return l;
--}
--
--
--static GList *mw_prpl_chat_info(PurpleConnection *gc) {
-- GList *l = NULL;
-- struct proto_chat_entry *pce;
--
-- pce = g_new0(struct proto_chat_entry, 1);
-- pce->label = _("Topic:");
-- pce->identifier = CHAT_KEY_TOPIC;
-- l = g_list_append(l, pce);
--
-- return l;
--}
--
--
--static GHashTable *mw_prpl_chat_info_defaults(PurpleConnection *gc,
-- const char *name) {
-- GHashTable *table;
--
-- g_return_val_if_fail(gc != NULL, NULL);
--
-- table = g_hash_table_new_full(g_str_hash, g_str_equal,
-- NULL, g_free);
--
-- g_hash_table_insert(table, CHAT_KEY_NAME, g_strdup(name));
-- g_hash_table_insert(table, CHAT_KEY_INVITE, NULL);
--
-- return table;
--}
--
--
--static void mw_prpl_login(PurpleAccount *acct);
--
--
--static void mw_prpl_login(PurpleAccount *account) {
-- PurpleConnection *gc;
-- struct mwPurplePluginData *pd;
--
-- char *user, *pass, *host;
-- guint port;
--
-- gc = purple_account_get_connection(account);
-- pd = mwPurplePluginData_new(gc);
--
-- /* while we do support images, the default is to not offer it */
-- gc->flags |= PURPLE_CONNECTION_NO_IMAGES;
--
-- user = g_strdup(purple_account_get_username(account));
--
-- host = strrchr(user, ':');
-- if(host) {
-- /* annoying user split from 1.2.0, need to undo it */
-- *host++ = '\0';
-- purple_account_set_string(account, MW_KEY_HOST, host);
-- purple_account_set_username(account, user);
--
-- } else {
-- host = (char *) purple_account_get_string(account, MW_KEY_HOST,
-- MW_PLUGIN_DEFAULT_HOST);
-- }
--
-- if(! host || ! *host) {
-- /* somehow, we don't have a host to connect to. Well, we need one
-- to actually continue, so let's ask the user directly. */
-- g_free(user);
-- purple_connection_error_reason(gc,
-- PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
-- _("A server is required to connect this account"));
-- return;
-- }
--
-- pass = g_strdup(purple_account_get_password(account));
-- port = purple_account_get_int(account, MW_KEY_PORT, MW_PLUGIN_DEFAULT_PORT);
--
-- DEBUG_INFO("user: '%s'\n", user);
-- DEBUG_INFO("host: '%s'\n", host);
-- DEBUG_INFO("port: %u\n", port);
--
-- mwSession_setProperty(pd->session, mwSession_NO_SECRET,
-- (char *) no_secret, NULL);
-- mwSession_setProperty(pd->session, mwSession_AUTH_USER_ID, user, g_free);
-- mwSession_setProperty(pd->session, mwSession_AUTH_PASSWORD, pass, g_free);
--
-- if(purple_account_get_bool(account, MW_KEY_FAKE_IT, FALSE)) {
-- guint client, major, minor;
--
-- /* if we're faking the login, let's also fake the version we're
-- reporting. Let's also allow the actual values to be specified */
--
-- client = purple_account_get_int(account, MW_KEY_CLIENT, mwLogin_BINARY);
-- major = purple_account_get_int(account, MW_KEY_MAJOR, 0x001e);
-- minor = purple_account_get_int(account, MW_KEY_MINOR, 0x196f);
--
-- DEBUG_INFO("client id: 0x%04x\n", client);
-- DEBUG_INFO("client major: 0x%04x\n", major);
-- DEBUG_INFO("client minor: 0x%04x\n", minor);
--
-- mwSession_setProperty(pd->session, mwSession_CLIENT_TYPE_ID,
-- GUINT_TO_POINTER(client), NULL);
--
-- mwSession_setProperty(pd->session, mwSession_CLIENT_VER_MAJOR,
-- GUINT_TO_POINTER(major), NULL);
--
-- mwSession_setProperty(pd->session, mwSession_CLIENT_VER_MINOR,
-- GUINT_TO_POINTER(minor), NULL);
-- }
--
-- purple_connection_update_progress(gc, _("Connecting"), 1, MW_CONNECT_STEPS);
--
-- if (purple_proxy_connect(gc, account, host, port, connect_cb, pd) == NULL) {
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Unable to connect"));
-- }
--}
--
--
--static void mw_prpl_close(PurpleConnection *gc) {
-- struct mwPurplePluginData *pd;
--
-- g_return_if_fail(gc != NULL);
--
-- pd = gc->proto_data;
-- g_return_if_fail(pd != NULL);
--
-- /* get rid of the blist save timeout */
-- if(pd->save_event) {
-- purple_timeout_remove(pd->save_event);
-- pd->save_event = 0;
-- blist_store(pd);
-- }
--
-- /* stop the session */
-- mwSession_stop(pd->session, 0x00);
--
-- /* no longer necessary */
-- gc->proto_data = NULL;
--
-- /* stop watching the socket */
-- if(gc->inpa) {
-- purple_input_remove(gc->inpa);
-- gc->inpa = 0;
-- }
--
-- /* clean up the rest */
-- mwPurplePluginData_free(pd);
--}
--
--
--static int mw_rand(void) {
-- static int seed = 0;
--
-- /* for diversity, not security. don't touch */
-- srand(time(NULL) ^ seed);
-- seed = rand();
--
-- return seed;
--}
--
--
--/** generates a random-ish content id string */
--static char *im_mime_content_id(void) {
-- return g_strdup_printf("%03x@%05xmeanwhile",
-- mw_rand() & 0xfff, mw_rand() & 0xfffff);
--}
--
--
--/** generates a multipart/related content type with a random-ish
-- boundary value */
--static char *im_mime_content_type(void) {
-- return g_strdup_printf("multipart/related; boundary=related_MW%03x_%04x",
-- mw_rand() & 0xfff, mw_rand() & 0xffff);
--}
--
--
--/** determine content type from extension. Not so happy about this,
-- but I don't want to actually write image type detection */
--static char *im_mime_img_content_type(PurpleStoredImage *img) {
-- const char *fn = purple_imgstore_get_filename(img);
-- const char *ct = NULL;
--
-- ct = strrchr(fn, '.');
-- if(! ct) {
-- ct = "image";
--
-- } else if(! strcmp(".png", ct)) {
-- ct = "image/png";
--
-- } else if(! strcmp(".jpg", ct)) {
-- ct = "image/jpeg";
--
-- } else if(! strcmp(".jpeg", ct)) {
-- ct = "image/jpeg";
--
-- } else if(! strcmp(".gif", ct)) {
-- ct = "image/gif";
--
-- } else {
-- ct = "image";
-- }
--
-- return g_strdup_printf("%s; name=\"%s\"", ct, fn);
--}
--
--
--static char *im_mime_img_content_disp(PurpleStoredImage *img) {
-- const char *fn = purple_imgstore_get_filename(img);
-- return g_strdup_printf("attachment; filename=\"%s\"", fn);
--}
--
--
--/** turn an IM with embedded images into a multi-part mime document */
--static char *im_mime_convert(PurpleConnection *gc,
-- struct mwConversation *conv,
-- const char *message) {
-- GString *str;
-- PurpleMimeDocument *doc;
-- PurpleMimePart *part;
--
-- GData *attr;
-- char *tmp, *start, *end;
--
-- str = g_string_new(NULL);
--
-- doc = purple_mime_document_new();
--
-- purple_mime_document_set_field(doc, "Mime-Version", "1.0");
-- purple_mime_document_set_field(doc, "Content-Disposition", "inline");
--
-- tmp = im_mime_content_type();
-- purple_mime_document_set_field(doc, "Content-Type", tmp);
-- g_free(tmp);
--
-- tmp = (char *) message;
-- while(*tmp && purple_markup_find_tag("img", tmp, (const char **) &start,
-- (const char **) &end, &attr)) {
-- char *id;
-- PurpleStoredImage *img = NULL;
--
-- gsize len = (start - tmp);
--
-- /* append the in-between-tags text */
-- if(len) g_string_append_len(str, tmp, len);
--
-- /* find the imgstore data by the id tag */
-- id = g_datalist_get_data(&attr, "id");
-- if(id && *id)
-- img = purple_imgstore_find_by_id(atoi(id));
--
-- if(img) {
-- char *cid;
-- gpointer data;
-- size_t size;
--
-- part = purple_mime_part_new(doc);
--
-- data = im_mime_img_content_disp(img);
-- purple_mime_part_set_field(part, "Content-Disposition", data);
-- g_free(data);
--
-- data = im_mime_img_content_type(img);
-- purple_mime_part_set_field(part, "Content-Type", data);
-- g_free(data);
--
-- cid = im_mime_content_id();
-- data = g_strdup_printf("<%s>", cid);
-- purple_mime_part_set_field(part, "Content-ID", data);
-- g_free(data);
--
-- purple_mime_part_set_field(part, "Content-transfer-encoding", "base64");
--
-- /* obtain and base64 encode the image data, and put it in the
-- mime part */
-- size = purple_imgstore_get_size(img);
-- data = purple_base64_encode(purple_imgstore_get_data(img), (gsize) size);
-- purple_mime_part_set_data(part, data);
-- g_free(data);
--
-- /* append the modified tag */
-- g_string_append_printf(str, "<img src=\"cid:%s\">", cid);
-- g_free(cid);
--
-- } else {
-- /* append the literal image tag, since we couldn't find a
-- relative imgstore object */
-- gsize len = (end - start) + 1;
-- g_string_append_len(str, start, len);
-- }
--
-- g_datalist_clear(&attr);
-- tmp = end + 1;
-- }
--
-- /* append left-overs */
-- g_string_append(str, tmp);
--
-- /* add the text/html part */
-- part = purple_mime_part_new(doc);
-- purple_mime_part_set_field(part, "Content-Disposition", "inline");
--
-- tmp = purple_utf8_ncr_encode(str->str);
-- purple_mime_part_set_field(part, "Content-Type", "text/html");
-- purple_mime_part_set_field(part, "Content-Transfer-Encoding", "7bit");
-- purple_mime_part_set_data(part, tmp);
-- g_free(tmp);
--
-- g_string_free(str, TRUE);
--
-- str = g_string_new(NULL);
-- purple_mime_document_write(doc, str);
-- tmp = str->str;
-- g_string_free(str, FALSE);
--
-- return tmp;
--}
--
--
--static int mw_prpl_send_im(PurpleConnection *gc,
-- const char *name,
-- const char *message,
-- PurpleMessageFlags flags) {
--
-- struct mwPurplePluginData *pd;
-- struct mwIdBlock who = { (char *) name, NULL };
-- struct mwConversation *conv;
--
-- g_return_val_if_fail(gc != NULL, 0);
-- pd = gc->proto_data;
--
-- g_return_val_if_fail(pd != NULL, 0);
--
-- conv = mwServiceIm_getConversation(pd->srvc_im, &who);
--
-- /* this detection of features to determine how to send the message
-- (plain, html, or mime) is flawed because the other end of the
-- conversation could close their channel at any time, rendering any
-- existing formatting in an outgoing message innapropriate. The end
-- result is that it may be possible that the other side of the
-- conversation will receive a plaintext message with html contents,
-- which is bad. I'm not sure how to fix this correctly. */
--
-- if(strstr(message, "<img ") || strstr(message, "<IMG "))
-- flags |= PURPLE_MESSAGE_IMAGES;
--
-- if(mwConversation_isOpen(conv)) {
-- char *tmp;
-- int ret;
--
-- if((flags & PURPLE_MESSAGE_IMAGES) &&
-- mwConversation_supports(conv, mwImSend_MIME)) {
-- /* send a MIME message */
--
-- tmp = im_mime_convert(gc, conv, message);
-- ret = mwConversation_send(conv, mwImSend_MIME, tmp);
-- g_free(tmp);
--
-- } else if(mwConversation_supports(conv, mwImSend_HTML)) {
-- /* send an HTML message */
--
-- char *ncr;
-- ncr = purple_utf8_ncr_encode(message);
-- tmp = purple_strdup_withhtml(ncr);
-- g_free(ncr);
--
-- ret = mwConversation_send(conv, mwImSend_HTML, tmp);
-- g_free(tmp);
--
-- } else {
-- /* default to text */
-- tmp = purple_markup_strip_html(message);
-- ret = mwConversation_send(conv, mwImSend_PLAIN, tmp);
-- g_free(tmp);
-- }
--
-- return !ret;
--
-- } else {
--
-- /* queue up the message safely as plain text */
-- char *tmp = purple_markup_strip_html(message);
-- convo_queue(conv, mwImSend_PLAIN, tmp);
-- g_free(tmp);
--
-- if(! mwConversation_isPending(conv))
-- mwConversation_open(conv);
--
-- return 1;
-- }
--}
--
--
--static unsigned int mw_prpl_send_typing(PurpleConnection *gc,
-- const char *name,
-- PurpleTypingState state) {
--
-- struct mwPurplePluginData *pd;
-- struct mwIdBlock who = { (char *) name, NULL };
-- struct mwConversation *conv;
--
-- gpointer t = GINT_TO_POINTER(!! state);
--
-- g_return_val_if_fail(gc != NULL, 0);
-- pd = gc->proto_data;
--
-- g_return_val_if_fail(pd != NULL, 0);
--
-- conv = mwServiceIm_getConversation(pd->srvc_im, &who);
--
-- if(mwConversation_isOpen(conv)) {
-- mwConversation_send(conv, mwImSend_TYPING, t);
--
-- } else if((state == PURPLE_TYPING) || (state == PURPLE_TYPED)) {
-- /* only open a channel for sending typing notification, not for
-- when typing has stopped. There's no point in re-opening a
-- channel just to tell someone that this side isn't typing. */
--
-- convo_queue(conv, mwImSend_TYPING, t);
--
-- if(! mwConversation_isPending(conv)) {
-- mwConversation_open(conv);
-- }
-- }
--
-- return 0;
--}
--
--
--static const char *mw_client_name(guint16 type) {
-- switch(type) {
-- case mwLogin_LIB:
-- return "Lotus Binary Library";
--
-- case mwLogin_JAVA_WEB:
-- return "Lotus Java Client Applet";
--
-- case mwLogin_BINARY:
-- return "Lotus Sametime Connect";
--
-- case mwLogin_JAVA_APP:
-- return "Lotus Java Client Application";
--
-- case mwLogin_LINKS:
-- return "Lotus Sametime Links";
--
-- case mwLogin_NOTES_6_5:
-- case mwLogin_NOTES_6_5_3:
-- case mwLogin_NOTES_7_0_beta:
-- case mwLogin_NOTES_7_0:
-- return "Lotus Notes Client";
--
-- case mwLogin_ICT:
-- case mwLogin_ICT_1_7_8_2:
-- case mwLogin_ICT_SIP:
-- return "IBM Community Tools";
--
-- case mwLogin_NOTESBUDDY_4_14:
-- case mwLogin_NOTESBUDDY_4_15:
-- case mwLogin_NOTESBUDDY_4_16:
-- return "Alphaworks NotesBuddy";
--
-- case 0x1305:
-- case 0x1306:
-- case 0x1307:
-- return "Lotus Sametime Connect 7.5";
--
-- case mwLogin_SANITY:
-- return "Sanity";
--
-- case mwLogin_ST_PERL:
-- return "ST-Send-Message";
--
-- case mwLogin_TRILLIAN:
-- case mwLogin_TRILLIAN_IBM:
-- return "Trillian";
--
-- case mwLogin_MEANWHILE:
-- return "Meanwhile";
--
-- default:
-- return NULL;
-- }
--}
--
--
--static void mw_prpl_get_info(PurpleConnection *gc, const char *who) {
--
-- struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL };
--
-- struct mwPurplePluginData *pd;
-- PurpleAccount *acct;
-- PurpleBuddy *b;
-- PurpleNotifyUserInfo *user_info;
-- char *tmp;
-- const char *tmp2;
--
-- g_return_if_fail(who != NULL);
-- g_return_if_fail(*who != '\0');
--
-- pd = gc->proto_data;
--
-- acct = purple_connection_get_account(gc);
-- b = purple_find_buddy(acct, who);
-- user_info = purple_notify_user_info_new();
--
-- if(purple_str_has_prefix(who, "@E ")) {
-- purple_notify_user_info_add_pair(user_info, _("External User"), NULL);
-- }
--
-- purple_notify_user_info_add_pair(user_info, _("User ID"), who);
--
-- if(b) {
-- guint32 type;
--
-- if(purple_buddy_get_server_alias(b)) {
-- purple_notify_user_info_add_pair(user_info, _("Full Name"), purple_buddy_get_server_alias(b));
-- }
--
-- type = purple_blist_node_get_int((PurpleBlistNode *) b, BUDDY_KEY_CLIENT);
-- if(type) {
-- tmp = g_strdup(mw_client_name(type));
-- if (!tmp)
-- tmp = g_strdup_printf(_("Unknown (0x%04x)<br>"), type);
--
-- purple_notify_user_info_add_pair(user_info, _("Last Known Client"), tmp);
--
-- g_free(tmp);
-- }
-- }
--
-- tmp = user_supports_text(pd->srvc_aware, who);
-- if(tmp) {
-- purple_notify_user_info_add_pair(user_info, _("Supports"), tmp);
-- g_free(tmp);
-- }
--
-- if(b) {
-- purple_notify_user_info_add_pair(user_info, _("Status"), status_text(b));
--
-- /* XXX Is this adding a status message in its own section rather than with the "Status" label? */
-- tmp2 = mwServiceAware_getText(pd->srvc_aware, &idb);
-- if(tmp2 && g_utf8_validate(tmp2, -1, NULL)) {
-- tmp = g_markup_escape_text(tmp2, -1);
-- purple_notify_user_info_add_section_break(user_info);
-- purple_notify_user_info_add_pair(user_info, NULL, tmp);
-- g_free(tmp);
-- }
-- }
--
-- /* @todo emit a signal to allow a plugin to override the display of
-- this notification, so that it can create its own */
--
-- purple_notify_userinfo(gc, who, user_info, NULL, NULL);
-- purple_notify_user_info_destroy(user_info);
--}
--
--
--static void mw_prpl_set_status(PurpleAccount *acct, PurpleStatus *status) {
-- PurpleConnection *gc;
-- const char *state;
-- char *message = NULL;
-- struct mwSession *session;
-- struct mwUserStatus stat;
--
-- g_return_if_fail(acct != NULL);
-- gc = purple_account_get_connection(acct);
--
-- state = purple_status_get_id(status);
--
-- DEBUG_INFO("Set status to %s\n", purple_status_get_name(status));
--
-- g_return_if_fail(gc != NULL);
--
-- session = gc_to_session(gc);
-- g_return_if_fail(session != NULL);
--
-- /* get a working copy of the current status */
-- mwUserStatus_clone(&stat, mwSession_getUserStatus(session));
--
-- /* determine the state */
-- if(! strcmp(state, MW_STATE_ACTIVE)) {
-- stat.status = mwStatus_ACTIVE;
--
-- } else if(! strcmp(state, MW_STATE_AWAY)) {
-- stat.status = mwStatus_AWAY;
--
-- } else if(! strcmp(state, MW_STATE_BUSY)) {
-- stat.status = mwStatus_BUSY;
-- }
--
-- /* determine the message */
-- message = (char *) purple_status_get_attr_string(status, MW_STATE_MESSAGE);
--
-- if(message) {
-- /* all the possible non-NULL values of message up to this point
-- are const, so we don't need to free them */
-- message = purple_markup_strip_html(message);
-- }
--
-- /* out with the old */
-- g_free(stat.desc);
--
-- /* in with the new */
-- stat.desc = (char *) message;
--
-- mwSession_setUserStatus(session, &stat);
-- mwUserStatus_clear(&stat);
--}
--
--
--static void mw_prpl_set_idle(PurpleConnection *gc, int t) {
-- struct mwSession *session;
-- struct mwUserStatus stat;
--
--
-- session = gc_to_session(gc);
-- g_return_if_fail(session != NULL);
--
-- mwUserStatus_clone(&stat, mwSession_getUserStatus(session));
--
-- if(t) {
-- time_t now = time(NULL);
-- stat.time = now - t;
--
-- } else {
-- stat.time = 0;
-- }
--
-- if(t > 0 && stat.status == mwStatus_ACTIVE) {
-- /* we were active and went idle, so change the status to IDLE. */
-- stat.status = mwStatus_IDLE;
--
-- } else if(t == 0 && stat.status == mwStatus_IDLE) {
-- /* we only become idle automatically, so change back to ACTIVE */
-- stat.status = mwStatus_ACTIVE;
-- }
--
-- mwSession_setUserStatus(session, &stat);
-- mwUserStatus_clear(&stat);
--}
--
--
--static void notify_im(PurpleConnection *gc, GList *row, void *user_data) {
-- PurpleAccount *acct;
-- PurpleConversation *conv;
-- char *id;
--
-- acct = purple_connection_get_account(gc);
-- id = g_list_nth_data(row, 1);
-- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, id, acct);
-- if(! conv) conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, id);
-- purple_conversation_present(conv);
--}
--
--
--static void notify_add(PurpleConnection *gc, GList *row, void *user_data) {
-- BuddyAddData *data = user_data;
-- const char *group_name = NULL;
--
-- if (data && data->group) {
-- group_name = purple_group_get_name(data->group);
-- }
--
-- purple_blist_request_add_buddy(purple_connection_get_account(gc),
-- g_list_nth_data(row, 1), group_name,
-- g_list_nth_data(row, 0));
--}
--
--
--static void notify_close(gpointer data) {
-- if (data) {
-- g_free(data);
-- }
--}
--
--
--static void multi_resolved_query(struct mwResolveResult *result,
-- PurpleConnection *gc, gpointer data) {
-- GList *l;
-- const char *msgA;
-- const char *msgB;
-- char *msg;
--
-- PurpleNotifySearchResults *sres;
-- PurpleNotifySearchColumn *scol;
--
-- sres = purple_notify_searchresults_new();
--
-- scol = purple_notify_searchresults_column_new(_("User Name"));
-- purple_notify_searchresults_column_add(sres, scol);
--
-- scol = purple_notify_searchresults_column_new(_("Sametime ID"));
-- purple_notify_searchresults_column_add(sres, scol);
--
-- purple_notify_searchresults_button_add(sres, PURPLE_NOTIFY_BUTTON_IM,
-- notify_im);
--
-- purple_notify_searchresults_button_add(sres, PURPLE_NOTIFY_BUTTON_ADD,
-- notify_add);
--
-- for(l = result->matches; l; l = l->next) {
-- struct mwResolveMatch *match = l->data;
-- GList *row = NULL;
--
-- DEBUG_INFO("multi resolve: %s, %s\n",
-- NSTR(match->id), NSTR(match->name));
--
-- if(!match->id || !match->name)
-- continue;
--
-- row = g_list_append(row, g_strdup(match->name));
-- row = g_list_append(row, g_strdup(match->id));
-- purple_notify_searchresults_row_add(sres, row);
-- }
--
-- msgA = _("An ambiguous user ID was entered");
-- msgB = _("The identifier '%s' may possibly refer to any of the following"
-- " users. Please select the correct user from the list below to"
-- " add them to your buddy list.");
-- msg = g_strdup_printf(msgB, result->name);
--
-- purple_notify_searchresults(gc, _("Select User"),
-- msgA, msg, sres, notify_close, data);
--
-- g_free(msg);
--}
--
--
--static void add_buddy_resolved(struct mwServiceResolve *srvc,
-- guint32 id, guint32 code, GList *results,
-- gpointer b) {
--
-- struct mwResolveResult *res = NULL;
-- BuddyAddData *data = b;
-- PurpleBuddy *buddy = NULL;
-- PurpleConnection *gc;
-- struct mwPurplePluginData *pd;
--
-- g_return_if_fail(data != NULL);
--
-- buddy = data->buddy;
--
-- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-- pd = gc->proto_data;
--
-- if(results)
-- res = results->data;
--
-- if(!code && res && res->matches) {
-- if(!res->matches->next) {
-- struct mwResolveMatch *match = res->matches->data;
--
-- /* only one? that might be the right one! */
-- if(strcmp(res->name, match->id)) {
-- /* uh oh, the single result isn't identical to the search
-- term, better safe then sorry, so let's make sure it's who
-- the user meant to add */
-- purple_blist_remove_buddy(buddy);
-- multi_resolved_query(res, gc, data);
--
-- } else {
--
-- /* same person, set the server alias */
-- purple_blist_server_alias_buddy(buddy, match->name);
-- purple_blist_node_set_string((PurpleBlistNode *) buddy,
-- BUDDY_KEY_NAME, match->name);
--
-- /* subscribe to awareness */
-- buddy_add(pd, buddy);
--
-- blist_schedule(pd);
--
-- g_free(data);
-- }
--
-- } else {
-- /* prompt user if more than one match was returned */
-- purple_blist_remove_buddy(buddy);
-- multi_resolved_query(res, gc, data);
-- }
--
-- return;
-- }
--
--#if 0
-- /* fall-through indicates that we couldn't find a matching user in
-- the resolve service (ether error or zero results), so we remove
-- this buddy */
--
-- /* note: I can't really think of a good reason to alter the buddy
-- list in any way. There has been at least one report where the
-- resolve service isn't returning correct results anyway, so let's
-- just leave them in the list. I'm just going to if0 this section
-- out unless I can think of a very good reason to do this. -siege */
--
-- DEBUG_INFO("no such buddy in community\n");
-- purple_blist_remove_buddy(buddy);
-- blist_schedule(pd);
--
-- if(res && res->name) {
-- /* compose and display an error message */
-- const char *msgA;
-- const char *msgB;
-- char *msg;
--
-- msgA = _("Unable to add user: user not found");
--
-- msgB = _("The identifier '%s' did not match any users in your"
-- " Sametime community. This entry has been removed from"
-- " your buddy list.");
-- msg = g_strdup_printf(msgB, NSTR(res->name));
--
-- purple_notify_error(gc, _("Unable to add user"), msgA, msg);
--
-- g_free(msg);
-- }
--#endif
--}
--
--
--static void mw_prpl_add_buddy(PurpleConnection *gc,
-- PurpleBuddy *buddy,
-- PurpleGroup *group) {
--
-- struct mwPurplePluginData *pd = gc->proto_data;
-- struct mwServiceResolve *srvc;
-- GList *query;
-- enum mwResolveFlag flags;
-- guint32 req;
-- BuddyAddData *data;
--
-- /* catch external buddies. They won't be in the resolve service */
-- if(buddy_is_external(buddy)) {
-- buddy_add(pd, buddy);
-- return;
-- }
--
-- data = g_new0(BuddyAddData, 1);
-- data->buddy = buddy;
-- data->group = group;
--
-- srvc = pd->srvc_resolve;
--
-- query = g_list_prepend(NULL, (char *)purple_buddy_get_name(buddy));
-- flags = mwResolveFlag_FIRST | mwResolveFlag_USERS;
--
-- req = mwServiceResolve_resolve(srvc, query, flags, add_buddy_resolved,
-- data, NULL);
-- g_list_free(query);
--
-- if(req == SEARCH_ERROR) {
-- purple_blist_remove_buddy(buddy);
-- blist_schedule(pd);
-- }
--}
--
--
--static void foreach_add_buddies(PurpleGroup *group, GList *buddies,
-- struct mwPurplePluginData *pd) {
-- struct mwAwareList *list;
--
-- list = list_ensure(pd, group);
-- mwAwareList_addAware(list, buddies);
-- g_list_free(buddies);
--}
--
--
--static void mw_prpl_add_buddies(PurpleConnection *gc,
-- GList *buddies,
-- GList *groups) {
--
-- struct mwPurplePluginData *pd;
-- GHashTable *group_sets;
-- struct mwAwareIdBlock *idbs, *idb;
--
-- pd = gc->proto_data;
--
-- /* map PurpleGroup:GList of mwAwareIdBlock */
-- group_sets = g_hash_table_new(g_direct_hash, g_direct_equal);
--
-- /* bunch of mwAwareIdBlock allocated at once, free'd at once */
-- idb = idbs = g_new(struct mwAwareIdBlock, g_list_length(buddies));
--
-- /* first pass collects mwAwareIdBlock lists for each group */
-- for(; buddies; buddies = buddies->next) {
-- PurpleBuddy *b = buddies->data;
-- PurpleGroup *g;
-- const char *fn;
-- GList *l;
--
-- /* nab the saved server alias and stick it on the buddy */
-- fn = purple_blist_node_get_string((PurpleBlistNode *) b, BUDDY_KEY_NAME);
-- purple_blist_server_alias_buddy(b, fn);
--
-- /* convert PurpleBuddy into a mwAwareIdBlock */
-- idb->type = mwAware_USER;
-- idb->user = (char *) purple_buddy_get_name(b);
-- idb->community = NULL;
--
-- /* put idb into the list associated with the buddy's group */
-- g = purple_buddy_get_group(b);
-- l = g_hash_table_lookup(group_sets, g);
-- l = g_list_prepend(l, idb++);
-- g_hash_table_insert(group_sets, g, l);
-- }
--
-- /* each group's buddies get added in one shot, and schedule the blist
-- for saving */
-- g_hash_table_foreach(group_sets, (GHFunc) foreach_add_buddies, pd);
-- blist_schedule(pd);
--
-- /* cleanup */
-- g_hash_table_destroy(group_sets);
-- g_free(idbs);
--}
--
--
--static void mw_prpl_remove_buddy(PurpleConnection *gc,
-- PurpleBuddy *buddy, PurpleGroup *group) {
--
-- struct mwPurplePluginData *pd;
-- struct mwAwareIdBlock idb = { mwAware_USER, (char *)purple_buddy_get_name(buddy), NULL };
-- struct mwAwareList *list;
--
-- GList *rem = g_list_prepend(NULL, &idb);
--
-- pd = gc->proto_data;
-- group = purple_buddy_get_group(buddy);
-- list = list_ensure(pd, group);
--
-- mwAwareList_removeAware(list, rem);
-- blist_schedule(pd);
--
-- g_list_free(rem);
--}
--
--
--static void privacy_fill(struct mwPrivacyInfo *priv,
-- GSList *members) {
--
-- struct mwUserItem *u;
-- guint count;
--
-- count = g_slist_length(members);
-- DEBUG_INFO("privacy_fill: %u members\n", count);
--
-- priv->count = count;
-- priv->users = g_new0(struct mwUserItem, count);
--
-- while(count--) {
-- u = priv->users + count;
-- u->id = members->data;
-- members = members->next;
-- }
--}
--
--
--static void mw_prpl_set_permit_deny(PurpleConnection *gc) {
-- PurpleAccount *acct;
-- struct mwPurplePluginData *pd;
-- struct mwSession *session;
--
-- struct mwPrivacyInfo privacy = {
-- FALSE, /* deny */
-- 0, /* count */
-- NULL, /* users */
-- };
--
-- g_return_if_fail(gc != NULL);
--
-- acct = purple_connection_get_account(gc);
-- g_return_if_fail(acct != NULL);
--
-- pd = gc->proto_data;
-- g_return_if_fail(pd != NULL);
--
-- session = pd->session;
-- g_return_if_fail(session != NULL);
--
-- switch(acct->perm_deny) {
-- case PURPLE_PRIVACY_DENY_USERS:
-- DEBUG_INFO("PURPLE_PRIVACY_DENY_USERS\n");
-- privacy_fill(&privacy, acct->deny);
-- privacy.deny = TRUE;
-- break;
--
-- case PURPLE_PRIVACY_ALLOW_ALL:
-- DEBUG_INFO("PURPLE_PRIVACY_ALLOW_ALL\n");
-- privacy.deny = TRUE;
-- break;
--
-- case PURPLE_PRIVACY_ALLOW_USERS:
-- DEBUG_INFO("PURPLE_PRIVACY_ALLOW_USERS\n");
-- privacy_fill(&privacy, acct->permit);
-- privacy.deny = FALSE;
-- break;
--
-- case PURPLE_PRIVACY_DENY_ALL:
-- DEBUG_INFO("PURPLE_PRIVACY_DENY_ALL\n");
-- privacy.deny = FALSE;
-- break;
--
-- default:
-- DEBUG_INFO("acct->perm_deny is 0x%x\n", acct->perm_deny);
-- return;
-- }
--
-- mwSession_setPrivacyInfo(session, &privacy);
-- g_free(privacy.users);
--}
--
--
--static void mw_prpl_add_permit(PurpleConnection *gc, const char *name) {
-- mw_prpl_set_permit_deny(gc);
--}
--
--
--static void mw_prpl_add_deny(PurpleConnection *gc, const char *name) {
-- mw_prpl_set_permit_deny(gc);
--}
--
--
--static void mw_prpl_rem_permit(PurpleConnection *gc, const char *name) {
-- mw_prpl_set_permit_deny(gc);
--}
--
--
--static void mw_prpl_rem_deny(PurpleConnection *gc, const char *name) {
-- mw_prpl_set_permit_deny(gc);
--}
--
--
--static struct mwConference *conf_find(struct mwServiceConference *srvc,
-- const char *name) {
-- GList *l, *ll;
-- struct mwConference *conf = NULL;
--
-- ll = mwServiceConference_getConferences(srvc);
-- for(l = ll; l; l = l->next) {
-- struct mwConference *c = l->data;
-- if(! strcmp(name, mwConference_getName(c))) {
-- conf = c;
-- break;
-- }
-- }
-- g_list_free(ll);
--
-- return conf;
--}
--
--
--static void mw_prpl_join_chat(PurpleConnection *gc,
-- GHashTable *components) {
--
-- struct mwPurplePluginData *pd;
-- char *c, *t;
--
-- pd = gc->proto_data;
--
-- c = g_hash_table_lookup(components, CHAT_KEY_NAME);
-- t = g_hash_table_lookup(components, CHAT_KEY_TOPIC);
--
-- if(g_hash_table_lookup(components, CHAT_KEY_IS_PLACE)) {
-- /* use place service */
-- struct mwServicePlace *srvc;
-- struct mwPlace *place = NULL;
--
-- srvc = pd->srvc_place;
-- place = mwPlace_new(srvc, c, t);
-- mwPlace_open(place);
--
-- } else {
-- /* use conference service */
-- struct mwServiceConference *srvc;
-- struct mwConference *conf = NULL;
--
-- srvc = pd->srvc_conf;
-- if(c) conf = conf_find(srvc, c);
--
-- if(conf) {
-- DEBUG_INFO("accepting conference invitation\n");
-- mwConference_accept(conf);
--
-- } else {
-- DEBUG_INFO("creating new conference\n");
-- conf = mwConference_new(srvc, t);
-- mwConference_open(conf);
-- }
-- }
--}
--
--
--static void mw_prpl_reject_chat(PurpleConnection *gc,
-- GHashTable *components) {
--
-- struct mwPurplePluginData *pd;
-- struct mwServiceConference *srvc;
-- char *c;
--
-- pd = gc->proto_data;
-- srvc = pd->srvc_conf;
--
-- if(g_hash_table_lookup(components, CHAT_KEY_IS_PLACE)) {
-- ; /* nothing needs doing */
--
-- } else {
-- /* reject conference */
-- c = g_hash_table_lookup(components, CHAT_KEY_NAME);
-- if(c) {
-- struct mwConference *conf = conf_find(srvc, c);
-- if(conf) mwConference_reject(conf, ERR_SUCCESS, "Declined");
-- }
-- }
--}
--
--
--static char *mw_prpl_get_chat_name(GHashTable *components) {
-- return g_hash_table_lookup(components, CHAT_KEY_NAME);
--}
--
--
--static void mw_prpl_chat_invite(PurpleConnection *gc,
-- int id,
-- const char *invitation,
-- const char *who) {
--
-- struct mwPurplePluginData *pd;
-- struct mwConference *conf;
-- struct mwPlace *place;
-- struct mwIdBlock idb = { (char *) who, NULL };
--
-- pd = gc->proto_data;
-- g_return_if_fail(pd != NULL);
--
-- conf = ID_TO_CONF(pd, id);
--
-- if(conf) {
-- mwConference_invite(conf, &idb, invitation);
-- return;
-- }
--
-- place = ID_TO_PLACE(pd, id);
-- g_return_if_fail(place != NULL);
--
-- /* @todo: use the IM service for invitation */
-- mwPlace_legacyInvite(place, &idb, invitation);
--}
--
--
--static void mw_prpl_chat_leave(PurpleConnection *gc,
-- int id) {
--
-- struct mwPurplePluginData *pd;
-- struct mwConference *conf;
--
-- pd = gc->proto_data;
--
-- g_return_if_fail(pd != NULL);
-- conf = ID_TO_CONF(pd, id);
--
-- if(conf) {
-- mwConference_destroy(conf, ERR_SUCCESS, "Leaving");
--
-- } else {
-- struct mwPlace *place = ID_TO_PLACE(pd, id);
-- g_return_if_fail(place != NULL);
--
-- mwPlace_destroy(place, ERR_SUCCESS);
-- }
--}
--
--
--static void mw_prpl_chat_whisper(PurpleConnection *gc,
-- int id,
-- const char *who,
-- const char *message) {
--
-- mw_prpl_send_im(gc, who, message, 0);
--}
--
--
--static int mw_prpl_chat_send(PurpleConnection *gc,
-- int id,
-- const char *message,
-- PurpleMessageFlags flags) {
--
-- struct mwPurplePluginData *pd;
-- struct mwConference *conf;
-- char *msg;
-- int ret;
--
-- pd = gc->proto_data;
--
-- g_return_val_if_fail(pd != NULL, 0);
-- conf = ID_TO_CONF(pd, id);
--
-- msg = purple_markup_strip_html(message);
--
-- if(conf) {
-- ret = ! mwConference_sendText(conf, msg);
--
-- } else {
-- struct mwPlace *place = ID_TO_PLACE(pd, id);
-- g_return_val_if_fail(place != NULL, 0);
--
-- ret = ! mwPlace_sendText(place, msg);
-- }
--
-- g_free(msg);
-- return ret;
--}
--
--
--static void mw_prpl_keepalive(PurpleConnection *gc) {
-- struct mwSession *session;
--
-- g_return_if_fail(gc != NULL);
--
-- session = gc_to_session(gc);
-- g_return_if_fail(session != NULL);
--
-- mwSession_sendKeepalive(session);
--}
--
--
--static void mw_prpl_alias_buddy(PurpleConnection *gc,
-- const char *who,
-- const char *alias) {
--
-- struct mwPurplePluginData *pd = gc->proto_data;
-- g_return_if_fail(pd != NULL);
--
-- /* it's a change to the buddy list, so we've gotta reflect that in
-- the server copy */
--
-- blist_schedule(pd);
--}
--
--
--static void mw_prpl_group_buddy(PurpleConnection *gc,
-- const char *who,
-- const char *old_group,
-- const char *new_group) {
--
-- struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL };
-- GList *gl = g_list_prepend(NULL, &idb);
--
-- struct mwPurplePluginData *pd = gc->proto_data;
-- PurpleGroup *group;
-- struct mwAwareList *list;
--
-- /* add who to new_group's aware list */
-- group = purple_find_group(new_group);
-- list = list_ensure(pd, group);
-- mwAwareList_addAware(list, gl);
--
-- /* remove who from old_group's aware list */
-- group = purple_find_group(old_group);
-- list = list_ensure(pd, group);
-- mwAwareList_removeAware(list, gl);
--
-- g_list_free(gl);
--
-- /* schedule the changes to be saved */
-- blist_schedule(pd);
--}
--
--
--static void mw_prpl_rename_group(PurpleConnection *gc,
-- const char *old,
-- PurpleGroup *group,
-- GList *buddies) {
--
-- struct mwPurplePluginData *pd = gc->proto_data;
-- g_return_if_fail(pd != NULL);
--
-- /* it's a change in the buddy list, so we've gotta reflect that in
-- the server copy. Also, having this function should prevent all
-- those buddies from being removed and re-added. We don't really
-- give a crap what the group is named in Purple other than to record
-- that as the group name/alias */
--
-- blist_schedule(pd);
--}
--
--
--static void mw_prpl_buddy_free(PurpleBuddy *buddy) {
-- /* I don't think we have any cleanup for buddies yet */
-- ;
--}
--
--
--static void mw_prpl_convo_closed(PurpleConnection *gc, const char *who) {
-- struct mwPurplePluginData *pd = gc->proto_data;
-- struct mwServiceIm *srvc;
-- struct mwConversation *conv;
-- struct mwIdBlock idb = { (char *) who, NULL };
--
-- g_return_if_fail(pd != NULL);
--
-- srvc = pd->srvc_im;
-- g_return_if_fail(srvc != NULL);
--
-- conv = mwServiceIm_findConversation(srvc, &idb);
-- if(! conv) return;
--
-- if(mwConversation_isOpen(conv))
-- mwConversation_free(conv);
--}
--
--
--static const char *mw_prpl_normalize(const PurpleAccount *account,
-- const char *id) {
--
-- /* code elsewhere assumes that the return value points to different
-- memory than the passed value, but it won't free the normalized
-- data. wtf? */
--
-- static char buf[BUF_LEN];
-- g_strlcpy(buf, id, sizeof(buf));
-- return buf;
--}
--
--
--static void mw_prpl_remove_group(PurpleConnection *gc, PurpleGroup *group) {
-- struct mwPurplePluginData *pd;
-- struct mwAwareList *list;
--
-- pd = gc->proto_data;
-- g_return_if_fail(pd != NULL);
-- g_return_if_fail(pd->group_list_map != NULL);
--
-- list = g_hash_table_lookup(pd->group_list_map, group);
--
-- if(list) {
-- g_hash_table_remove(pd->group_list_map, list);
-- g_hash_table_remove(pd->group_list_map, group);
-- mwAwareList_free(list);
--
-- blist_schedule(pd);
-- }
--}
--
--
--static gboolean mw_prpl_can_receive_file(PurpleConnection *gc,
-- const char *who) {
-- struct mwPurplePluginData *pd;
-- struct mwServiceAware *srvc;
-- PurpleAccount *acct;
--
-- g_return_val_if_fail(gc != NULL, FALSE);
--
-- pd = gc->proto_data;
-- g_return_val_if_fail(pd != NULL, FALSE);
--
-- srvc = pd->srvc_aware;
-- g_return_val_if_fail(srvc != NULL, FALSE);
--
-- acct = purple_connection_get_account(gc);
-- g_return_val_if_fail(acct != NULL, FALSE);
--
-- return purple_find_buddy(acct, who) &&
-- user_supports(srvc, who, mwAttribute_FILE_TRANSFER);
--}
--
--
--static void ft_outgoing_init(PurpleXfer *xfer) {
-- PurpleAccount *acct;
-- PurpleConnection *gc;
--
-- struct mwPurplePluginData *pd;
-- struct mwServiceFileTransfer *srvc;
-- struct mwFileTransfer *ft;
--
-- const char *filename;
-- gsize filesize;
-- FILE *fp;
--
-- struct mwIdBlock idb = { NULL, NULL };
--
-- DEBUG_INFO("ft_outgoing_init\n");
--
-- acct = purple_xfer_get_account(xfer);
-- gc = purple_account_get_connection(acct);
-- pd = gc->proto_data;
-- srvc = pd->srvc_ft;
--
-- filename = purple_xfer_get_local_filename(xfer);
-- filesize = purple_xfer_get_size(xfer);
-- idb.user = xfer->who;
--
-- purple_xfer_update_progress(xfer);
--
-- /* test that we can actually send the file */
-- fp = g_fopen(filename, "rb");
-- if(! fp) {
-- char *msg = g_strdup_printf(_("Error reading file %s: \n%s\n"),
-- filename, g_strerror(errno));
-- purple_xfer_error(purple_xfer_get_type(xfer), acct, xfer->who, msg);
-- g_free(msg);
-- return;
-- }
-- fclose(fp);
--
-- {
-- char *tmp = strrchr(filename, G_DIR_SEPARATOR);
-- if(tmp++) filename = tmp;
-- }
--
-- ft = mwFileTransfer_new(srvc, &idb, NULL, filename, filesize);
--
-- purple_xfer_ref(xfer);
-- mwFileTransfer_setClientData(ft, xfer, (GDestroyNotify) purple_xfer_unref);
-- xfer->data = ft;
--
-- mwFileTransfer_offer(ft);
--}
--
--
--static void ft_outgoing_cancel(PurpleXfer *xfer) {
-- struct mwFileTransfer *ft = xfer->data;
--
-- DEBUG_INFO("ft_outgoing_cancel called\n");
--
-- if(ft) mwFileTransfer_cancel(ft);
--}
--
--
--static PurpleXfer *mw_prpl_new_xfer(PurpleConnection *gc, const char *who) {
-- PurpleAccount *acct;
-- PurpleXfer *xfer;
--
-- acct = purple_connection_get_account(gc);
--
-- xfer = purple_xfer_new(acct, PURPLE_XFER_SEND, who);
-- if (xfer)
-- {
-- purple_xfer_set_init_fnc(xfer, ft_outgoing_init);
-- purple_xfer_set_cancel_send_fnc(xfer, ft_outgoing_cancel);
-- }
--
-- return xfer;
--}
--
--static void mw_prpl_send_file(PurpleConnection *gc,
-- const char *who, const char *file) {
--
-- PurpleXfer *xfer = mw_prpl_new_xfer(gc, who);
--
-- if(file) {
-- DEBUG_INFO("file != NULL\n");
-- purple_xfer_request_accepted(xfer, file);
--
-- } else {
-- DEBUG_INFO("file == NULL\n");
-- purple_xfer_request(xfer);
-- }
--}
--
--
--static PurplePluginProtocolInfo mw_prpl_info = {
-- OPT_PROTO_IM_IMAGE,
-- NULL, /*< set in mw_plugin_init */
-- NULL, /*< set in mw_plugin_init */
-- NO_BUDDY_ICONS,
-- mw_prpl_list_icon,
-- mw_prpl_list_emblem,
-- mw_prpl_status_text,
-- mw_prpl_tooltip_text,
-- mw_prpl_status_types,
-- mw_prpl_blist_node_menu,
-- mw_prpl_chat_info,
-- mw_prpl_chat_info_defaults,
-- mw_prpl_login,
-- mw_prpl_close,
-- mw_prpl_send_im,
-- NULL,
-- mw_prpl_send_typing,
-- mw_prpl_get_info,
-- mw_prpl_set_status,
-- mw_prpl_set_idle,
-- NULL,
-- mw_prpl_add_buddy,
-- mw_prpl_add_buddies,
-- mw_prpl_remove_buddy,
-- NULL,
-- mw_prpl_add_permit,
-- mw_prpl_add_deny,
-- mw_prpl_rem_permit,
-- mw_prpl_rem_deny,
-- mw_prpl_set_permit_deny,
-- mw_prpl_join_chat,
-- mw_prpl_reject_chat,
-- mw_prpl_get_chat_name,
-- mw_prpl_chat_invite,
-- mw_prpl_chat_leave,
-- mw_prpl_chat_whisper,
-- mw_prpl_chat_send,
-- mw_prpl_keepalive,
-- NULL,
-- NULL,
-- NULL,
-- mw_prpl_alias_buddy,
-- mw_prpl_group_buddy,
-- mw_prpl_rename_group,
-- mw_prpl_buddy_free,
-- mw_prpl_convo_closed,
-- mw_prpl_normalize,
-- NULL,
-- mw_prpl_remove_group,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- mw_prpl_can_receive_file,
-- mw_prpl_send_file,
-- mw_prpl_new_xfer,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- sizeof(PurplePluginProtocolInfo),
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL
--};
--
--
--static PurplePluginPrefFrame *
--mw_plugin_get_plugin_pref_frame(PurplePlugin *plugin) {
-- PurplePluginPrefFrame *frame;
-- PurplePluginPref *pref;
--
-- frame = purple_plugin_pref_frame_new();
--
-- pref = purple_plugin_pref_new_with_label(_("Remotely Stored Buddy List"));
-- purple_plugin_pref_frame_add(frame, pref);
--
--
-- pref = purple_plugin_pref_new_with_name(MW_PRPL_OPT_BLIST_ACTION);
-- purple_plugin_pref_set_label(pref, _("Buddy List Storage Mode"));
--
-- purple_plugin_pref_set_type(pref, PURPLE_PLUGIN_PREF_CHOICE);
-- purple_plugin_pref_add_choice(pref, _("Local Buddy List Only"),
-- GINT_TO_POINTER(blist_choice_LOCAL));
-- purple_plugin_pref_add_choice(pref, _("Merge List from Server"),
-- GINT_TO_POINTER(blist_choice_MERGE));
-- purple_plugin_pref_add_choice(pref, _("Merge and Save List to Server"),
-- GINT_TO_POINTER(blist_choice_STORE));
-- purple_plugin_pref_add_choice(pref, _("Synchronize List with Server"),
-- GINT_TO_POINTER(blist_choice_SYNCH));
--
-- purple_plugin_pref_frame_add(frame, pref);
--
-- return frame;
--}
--
--
--static PurplePluginUiInfo mw_plugin_ui_info = {
-- mw_plugin_get_plugin_pref_frame,
-- 0, /* page_num */
-- NULL, /* frame */
-- NULL,
-- NULL,
-- NULL,
-- NULL
--};
--
--
--static void st_import_action_cb(PurpleConnection *gc, char *filename) {
-- struct mwSametimeList *l;
--
-- FILE *file;
-- char buf[BUF_LEN];
-- size_t len;
--
-- GString *str;
--
-- file = g_fopen(filename, "r");
-- g_return_if_fail(file != NULL);
--
-- str = g_string_new(NULL);
-- while( (len = fread(buf, 1, BUF_LEN, file)) ) {
-- g_string_append_len(str, buf, len);
-- }
--
-- fclose(file);
--
-- l = mwSametimeList_load(str->str);
-- g_string_free(str, TRUE);
--
-- blist_merge(gc, l);
-- mwSametimeList_free(l);
--}
--
--
--/** prompts for a file to import blist from */
--static void st_import_action(PurplePluginAction *act) {
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- char *title;
--
-- gc = act->context;
-- account = purple_connection_get_account(gc);
-- title = g_strdup_printf(_("Import Sametime List for Account %s"),
-- purple_account_get_username(account));
--
-- purple_request_file(gc, title, NULL, FALSE,
-- G_CALLBACK(st_import_action_cb), NULL,
-- account, NULL, NULL,
-- gc);
--
-- g_free(title);
--}
--
--
--static void st_export_action_cb(PurpleConnection *gc, char *filename) {
-- struct mwSametimeList *l;
-- char *str;
-- FILE *file;
--
-- file = g_fopen(filename, "w");
-- g_return_if_fail(file != NULL);
--
-- l = mwSametimeList_new();
-- blist_export(gc, l);
-- str = mwSametimeList_store(l);
-- mwSametimeList_free(l);
--
-- fprintf(file, "%s", str);
-- fclose(file);
--
-- g_free(str);
--}
--
--
--/** prompts for a file to export blist to */
--static void st_export_action(PurplePluginAction *act) {
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- char *title;
--
-- gc = act->context;
-- account = purple_connection_get_account(gc);
-- title = g_strdup_printf(_("Export Sametime List for Account %s"),
-- purple_account_get_username(account));
--
-- purple_request_file(gc, title, NULL, TRUE,
-- G_CALLBACK(st_export_action_cb), NULL,
-- account, NULL, NULL,
-- gc);
--
-- g_free(title);
--}
--
--
--static void remote_group_multi_cleanup(gpointer ignore,
-- PurpleRequestFields *fields) {
--
-- PurpleRequestField *f;
-- GList *l;
--
-- f = purple_request_fields_get_field(fields, "group");
-- l = purple_request_field_list_get_items(f);
--
-- for(; l; l = l->next) {
-- const char *i = l->data;
-- struct named_id *res;
--
-- res = purple_request_field_list_get_data(f, i);
--
-- g_free(res->id);
-- g_free(res->name);
-- g_free(res);
-- }
--}
--
--
--static void remote_group_done(struct mwPurplePluginData *pd,
-- const char *id, const char *name) {
-- PurpleConnection *gc;
-- PurpleAccount *acct;
-- PurpleGroup *group;
-- PurpleBlistNode *gn;
-- const char *owner;
--
-- g_return_if_fail(pd != NULL);
--
-- gc = pd->gc;
-- acct = purple_connection_get_account(gc);
--
-- /* collision checking */
-- group = purple_find_group(name);
-- if(group) {
-- const char *msgA;
-- const char *msgB;
-- char *msg;
--
-- msgA = _("Unable to add group: group exists");
-- msgB = _("A group named '%s' already exists in your buddy list.");
-- msg = g_strdup_printf(msgB, name);
--
-- purple_notify_error(gc, _("Unable to add group"), msgA, msg);
--
-- g_free(msg);
-- return;
-- }
--
-- group = purple_group_new(name);
-- gn = (PurpleBlistNode *) group;
--
-- owner = purple_account_get_username(acct);
--
-- purple_blist_node_set_string(gn, GROUP_KEY_NAME, id);
-- purple_blist_node_set_int(gn, GROUP_KEY_TYPE, mwSametimeGroup_DYNAMIC);
-- purple_blist_node_set_string(gn, GROUP_KEY_OWNER, owner);
-- purple_blist_add_group(group, NULL);
--
-- group_add(pd, group);
-- blist_schedule(pd);
--}
--
--
--static void remote_group_multi_cb(struct mwPurplePluginData *pd,
-- PurpleRequestFields *fields) {
-- PurpleRequestField *f;
-- GList *l;
--
-- f = purple_request_fields_get_field(fields, "group");
-- l = purple_request_field_list_get_selected(f);
--
-- if(l) {
-- const char *i = l->data;
-- struct named_id *res;
--
-- res = purple_request_field_list_get_data(f, i);
-- remote_group_done(pd, res->id, res->name);
-- }
--
-- remote_group_multi_cleanup(NULL, fields);
--}
--
--
--static void remote_group_multi(struct mwResolveResult *result,
-- struct mwPurplePluginData *pd) {
--
-- PurpleRequestFields *fields;
-- PurpleRequestFieldGroup *g;
-- PurpleRequestField *f;
-- GList *l;
-- const char *msgA;
-- const char *msgB;
-- char *msg;
--
-- PurpleConnection *gc = pd->gc;
--
-- fields = purple_request_fields_new();
--
-- g = purple_request_field_group_new(NULL);
-- purple_request_fields_add_group(fields, g);
--
-- f = purple_request_field_list_new("group", _("Possible Matches"));
-- purple_request_field_list_set_multi_select(f, FALSE);
-- purple_request_field_set_required(f, TRUE);
--
-- for(l = result->matches; l; l = l->next) {
-- struct mwResolveMatch *match = l->data;
-- struct named_id *res = g_new0(struct named_id, 1);
--
-- res->id = g_strdup(match->id);
-- res->name = g_strdup(match->name);
--
-- purple_request_field_list_add_icon(f, res->name, NULL, res);
-- }
--
-- purple_request_field_group_add_field(g, f);
--
-- msgA = _("Notes Address Book group results");
-- msgB = _("The identifier '%s' may possibly refer to any of the following"
-- " Notes Address Book groups. Please select the correct group from"
-- " the list below to add it to your buddy list.");
-- msg = g_strdup_printf(msgB, result->name);
--
-- purple_request_fields(gc, _("Select Notes Address Book"),
-- msgA, msg, fields,
-- _("Add Group"), G_CALLBACK(remote_group_multi_cb),
-- _("Cancel"), G_CALLBACK(remote_group_multi_cleanup),
-- purple_connection_get_account(gc), result->name, NULL,
-- pd);
--
-- g_free(msg);
--}
--
--
--static void remote_group_resolved(struct mwServiceResolve *srvc,
-- guint32 id, guint32 code, GList *results,
-- gpointer b) {
--
-- struct mwResolveResult *res = NULL;
-- struct mwSession *session;
-- struct mwPurplePluginData *pd;
-- PurpleConnection *gc;
--
-- session = mwService_getSession(MW_SERVICE(srvc));
-- g_return_if_fail(session != NULL);
--
-- pd = mwSession_getClientData(session);
-- g_return_if_fail(pd != NULL);
--
-- gc = pd->gc;
-- g_return_if_fail(gc != NULL);
--
-- if(!code && results) {
-- res = results->data;
--
-- if(res->matches) {
-- remote_group_multi(res, pd);
-- return;
-- }
-- }
--
-- if(res && res->name) {
-- const char *msgA;
-- const char *msgB;
-- char *msg;
--
-- msgA = _("Unable to add group: group not found");
--
-- msgB = _("The identifier '%s' did not match any Notes Address Book"
-- " groups in your Sametime community.");
-- msg = g_strdup_printf(msgB, res->name);
--
-- purple_notify_error(gc, _("Unable to add group"), msgA, msg);
--
-- g_free(msg);
-- }
--}
--
--
--static void remote_group_action_cb(PurpleConnection *gc, const char *name) {
-- struct mwPurplePluginData *pd;
-- struct mwServiceResolve *srvc;
-- GList *query;
-- enum mwResolveFlag flags;
-- guint32 req;
--
-- pd = gc->proto_data;
-- srvc = pd->srvc_resolve;
--
-- query = g_list_prepend(NULL, (char *) name);
-- flags = mwResolveFlag_FIRST | mwResolveFlag_GROUPS;
--
-- req = mwServiceResolve_resolve(srvc, query, flags, remote_group_resolved,
-- NULL, NULL);
-- g_list_free(query);
--
-- if(req == SEARCH_ERROR) {
-- /** @todo display error */
-- }
--}
--
--
--static void remote_group_action(PurplePluginAction *act) {
-- PurpleConnection *gc;
-- const char *msgA;
-- const char *msgB;
--
-- gc = act->context;
--
-- msgA = _("Notes Address Book Group");
-- msgB = _("Enter the name of a Notes Address Book group in the field below"
-- " to add the group and its members to your buddy list.");
--
-- purple_request_input(gc, _("Add Group"), msgA, msgB, NULL,
-- FALSE, FALSE, NULL,
-- _("Add"), G_CALLBACK(remote_group_action_cb),
-- _("Cancel"), NULL,
-- purple_connection_get_account(gc), NULL, NULL,
-- gc);
--}
--
--
--static void search_notify(struct mwResolveResult *result,
-- PurpleConnection *gc) {
-- GList *l;
-- const char *msgA;
-- const char *msgB;
-- char *msg1;
-- char *msg2;
--
-- PurpleNotifySearchResults *sres;
-- PurpleNotifySearchColumn *scol;
--
-- sres = purple_notify_searchresults_new();
--
-- scol = purple_notify_searchresults_column_new(_("User Name"));
-- purple_notify_searchresults_column_add(sres, scol);
--
-- scol = purple_notify_searchresults_column_new(_("Sametime ID"));
-- purple_notify_searchresults_column_add(sres, scol);
--
-- purple_notify_searchresults_button_add(sres, PURPLE_NOTIFY_BUTTON_IM,
-- notify_im);
--
-- purple_notify_searchresults_button_add(sres, PURPLE_NOTIFY_BUTTON_ADD,
-- notify_add);
--
-- for(l = result->matches; l; l = l->next) {
-- struct mwResolveMatch *match = l->data;
-- GList *row = NULL;
--
-- if(!match->id || !match->name)
-- continue;
--
-- row = g_list_append(row, g_strdup(match->name));
-- row = g_list_append(row, g_strdup(match->id));
-- purple_notify_searchresults_row_add(sres, row);
-- }
--
-- msgA = _("Search results for '%s'");
-- msgB = _("The identifier '%s' may possibly refer to any of the following"
-- " users. You may add these users to your buddy list or send them"
-- " messages with the action buttons below.");
--
-- msg1 = g_strdup_printf(msgA, result->name);
-- msg2 = g_strdup_printf(msgB, result->name);
--
-- purple_notify_searchresults(gc, _("Search Results"),
-- msg1, msg2, sres, notify_close, NULL);
--
-- g_free(msg1);
-- g_free(msg2);
--}
--
--
--static void search_resolved(struct mwServiceResolve *srvc,
-- guint32 id, guint32 code, GList *results,
-- gpointer b) {
--
-- PurpleConnection *gc = b;
-- struct mwResolveResult *res = NULL;
--
-- if(results) res = results->data;
--
-- if(!code && res && res->matches) {
-- search_notify(res, gc);
--
-- } else {
-- const char *msgA;
-- const char *msgB;
-- char *msg;
--
-- msgA = _("No matches");
-- msgB = _("The identifier '%s' did not match any users in your"
-- " Sametime community.");
-- msg = g_strdup_printf(msgB, (res && res->name) ? NSTR(res->name) : "");
--
-- purple_notify_error(gc, _("No Matches"), msgA, msg);
--
-- g_free(msg);
-- }
--}
--
--
--static void search_action_cb(PurpleConnection *gc, const char *name) {
-- struct mwPurplePluginData *pd;
-- struct mwServiceResolve *srvc;
-- GList *query;
-- enum mwResolveFlag flags;
-- guint32 req;
--
-- pd = gc->proto_data;
-- srvc = pd->srvc_resolve;
--
-- query = g_list_prepend(NULL, (char *) name);
-- flags = mwResolveFlag_FIRST | mwResolveFlag_USERS;
--
-- req = mwServiceResolve_resolve(srvc, query, flags, search_resolved,
-- gc, NULL);
-- g_list_free(query);
--
-- if(req == SEARCH_ERROR) {
-- /** @todo display error */
-- }
--}
--
--
--static void search_action(PurplePluginAction *act) {
-- PurpleConnection *gc;
-- const char *msgA;
-- const char *msgB;
--
-- gc = act->context;
--
-- msgA = _("Search for a user");
-- msgB = _("Enter a name or partial ID in the field below to search"
-- " for matching users in your Sametime community.");
--
-- purple_request_input(gc, _("User Search"), msgA, msgB, NULL,
-- FALSE, FALSE, NULL,
-- _("Search"), G_CALLBACK(search_action_cb),
-- _("Cancel"), NULL,
-- purple_connection_get_account(gc), NULL, NULL,
-- gc);
--}
--
--
--static GList *mw_plugin_actions(PurplePlugin *plugin, gpointer context) {
-- PurplePluginAction *act;
-- GList *l = NULL;
--
-- act = purple_plugin_action_new(_("Import Sametime List..."),
-- st_import_action);
-- l = g_list_append(l, act);
--
-- act = purple_plugin_action_new(_("Export Sametime List..."),
-- st_export_action);
-- l = g_list_append(l, act);
--
-- act = purple_plugin_action_new(_("Add Notes Address Book Group..."),
-- remote_group_action);
-- l = g_list_append(l, act);
--
-- act = purple_plugin_action_new(_("User Search..."),
-- search_action);
-- l = g_list_append(l, act);
--
-- return l;
--}
--
--
--static gboolean mw_plugin_load(PurplePlugin *plugin) {
-- return TRUE;
--}
--
--
--static gboolean mw_plugin_unload(PurplePlugin *plugin) {
-- return TRUE;
--}
--
--
--static void mw_plugin_destroy(PurplePlugin *plugin) {
-- g_log_remove_handler(G_LOG_DOMAIN, log_handler[0]);
-- g_log_remove_handler("meanwhile", log_handler[1]);
--}
--
--static PurplePluginInfo mw_plugin_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 */
--
-- PLUGIN_ID, /**< id */
-- PLUGIN_NAME, /**< name */
-- DISPLAY_VERSION, /**< version */
-- PLUGIN_SUMMARY, /**< summary */
-- PLUGIN_DESC, /**< description */
-- PLUGIN_AUTHOR, /**< author */
-- PLUGIN_HOMEPAGE, /**< homepage */
--
-- mw_plugin_load, /**< load */
-- mw_plugin_unload, /**< unload */
-- mw_plugin_destroy, /**< destroy */
--
-- NULL, /**< ui_info */
-- &mw_prpl_info, /**< extra_info */
-- &mw_plugin_ui_info, /**< prefs_info */
-- mw_plugin_actions,
--
-- /* padding */
-- NULL,
-- NULL,
-- NULL,
-- NULL
--};
--
--
--static void mw_log_handler(const gchar *domain, GLogLevelFlags flags,
-- const gchar *msg, gpointer data) {
--
-- if(! (msg && *msg)) return;
--
-- /* handle g_log requests via purple's built-in debug logging */
-- if(flags & G_LOG_LEVEL_ERROR) {
-- purple_debug_error(domain, "%s\n", msg);
--
-- } else if(flags & G_LOG_LEVEL_WARNING) {
-- purple_debug_warning(domain, "%s\n", msg);
--
-- } else {
-- purple_debug_info(domain, "%s\n", msg);
-- }
--}
--
--
--static void mw_plugin_init(PurplePlugin *plugin) {
-- PurpleAccountUserSplit *split;
-- PurpleAccountOption *opt;
-- GList *l = NULL;
--
-- GLogLevelFlags logflags =
-- G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION;
--
-- /* set up the preferences */
-- purple_prefs_add_none(MW_PRPL_OPT_BASE);
-- purple_prefs_add_int(MW_PRPL_OPT_BLIST_ACTION, BLIST_CHOICE_DEFAULT);
--
-- /* set up account ID as user:server */
-- split = purple_account_user_split_new(_("Server"),
-- MW_PLUGIN_DEFAULT_HOST, ':');
-- mw_prpl_info.user_splits = g_list_append(mw_prpl_info.user_splits, split);
--
-- /* remove dead preferences */
-- purple_prefs_remove(MW_PRPL_OPT_PSYCHIC);
-- purple_prefs_remove(MW_PRPL_OPT_SAVE_DYNAMIC);
--
-- /* port to connect to */
-- opt = purple_account_option_int_new(_("Port"), MW_KEY_PORT,
-- MW_PLUGIN_DEFAULT_PORT);
-- l = g_list_append(l, opt);
--
-- { /* copy the old force login setting from prefs if it's
-- there. Don't delete the preference, since there may be more
-- than one account that wants to check for it. */
-- gboolean b = FALSE;
-- const char *label = _("Force login (ignore server redirects)");
--
-- if(purple_prefs_exists(MW_PRPL_OPT_FORCE_LOGIN))
-- b = purple_prefs_get_bool(MW_PRPL_OPT_FORCE_LOGIN);
--
-- opt = purple_account_option_bool_new(label, MW_KEY_FORCE, b);
-- l = g_list_append(l, opt);
-- }
--
-- /* pretend to be Sametime Connect */
-- opt = purple_account_option_bool_new(_("Hide client identity"),
-- MW_KEY_FAKE_IT, FALSE);
-- l = g_list_append(l, opt);
--
-- mw_prpl_info.protocol_options = l;
-- l = NULL;
--
-- /* forward all our g_log messages to purple. Generally all the logging
-- calls are using purple_log directly, but the g_return macros will
-- get caught here */
-- log_handler[0] = g_log_set_handler(G_LOG_DOMAIN, logflags,
-- mw_log_handler, NULL);
--
-- /* redirect meanwhile's logging to purple's */
-- log_handler[1] = g_log_set_handler("meanwhile", logflags,
-- mw_log_handler, NULL);
--}
--
--
--PURPLE_INIT_PLUGIN(sametime, mw_plugin_init, mw_plugin_info);
--/* The End. */
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/sametime/sametime.h pidgin-2.10.7-nonprism/libpurple/protocols/sametime/sametime.h
---- pidgin-2.10.7/libpurple/protocols/sametime/sametime.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/sametime/sametime.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,26 +0,0 @@
--
--
--/* CFLAGS trumps configure values */
--
--
--/** default host for the purple plugin. You can specialize a build to
-- default to your server by supplying this at compile time */
--#ifndef MW_PLUGIN_DEFAULT_HOST
--#define MW_PLUGIN_DEFAULT_HOST ""
--#endif
--/* "" */
--
--
--/** default port for the purple plugin. You can specialize a build to
-- default to your server by supplying this at compile time */
--#ifndef MW_PLUGIN_DEFAULT_PORT
--#define MW_PLUGIN_DEFAULT_PORT 1533
--#endif
--/* 1533 */
--
--
--/** default encoding for the purple plugin.*/
--#ifndef MW_PLUGIN_DEFAULT_ENCODING
--#define MW_PLUGIN_DEFAULT_ENCODING "ISO-8859-1"
--#endif
--/* ISO-8859-1 */
-diff -Nur pidgin-2.10.7/libpurple/protocols/silc/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/silc/Makefile.in
---- pidgin-2.10.7/libpurple/protocols/silc/Makefile.in 2013-02-11 07:17:22.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/silc/Makefile.in 2013-08-16 23:50:52.621915468 -0300
-@@ -196,8 +196,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -259,8 +257,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/libpurple/protocols/silc/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/silc/Makefile.mingw
---- pidgin-2.10.7/libpurple/protocols/silc/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/silc/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -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)/bin/libsilc-1-1-2.dll \
-- $(SILC_TOOLKIT)/bin/libsilcclient-1-1-3.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,0x74000000 -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -f $(OBJECTS)
-- rm -f $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/silc10/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/silc10/Makefile.in
---- pidgin-2.10.7/libpurple/protocols/silc10/Makefile.in 2013-02-11 07:17:22.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/silc10/Makefile.in 2013-08-16 23:51:39.120015095 -0300
-@@ -196,8 +196,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -259,8 +257,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/libpurple/protocols/silc10/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/silc10/Makefile.mingw
---- pidgin-2.10.7/libpurple/protocols/silc10/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/silc10/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,93 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of libsilc protocol plugin
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES))
--
--TARGET = libsilc
--NEEDED_DLLS = $(SILC_TOOLKIT)/lib/silc.dll \
-- $(SILC_TOOLKIT)/lib/silcclient.dll
--TYPE = PLUGIN
--
--# Static or Plugin...
--ifeq ($(TYPE),STATIC)
-- DEFINES += -DSTATIC
-- DLL_INSTALL_DIR = $(PURPLE_INSTALL_DIR)
--else
--ifeq ($(TYPE),PLUGIN)
-- DLL_INSTALL_DIR = $(PURPLE_INSTALL_PLUGINS_DIR)
--endif
--endif
--
--##
--## INCLUDE PATHS
--##
--INCLUDE_PATHS += -I. \
-- -I$(GTK_TOP)/include \
-- -I$(GTK_TOP)/include/glib-2.0 \
-- -I$(GTK_TOP)/lib/glib-2.0/include \
-- -I$(PURPLE_TOP) \
-- -I$(PURPLE_TOP)/win32 \
-- -I$(PIDGIN_TREE_TOP) \
-- -I$(SILC_TOOLKIT)/include
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP) \
-- -L$(SILC_TOOLKIT)/lib
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = silc.c \
-- buddy.c \
-- chat.c \
-- ft.c \
-- ops.c \
-- pk.c \
-- util.c \
-- wb.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lws2_32 \
-- -lintl \
-- -lpurple \
-- -lsilc \
-- -lsilcclient
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll
--
--install: all $(DLL_INSTALL_DIR) $(PURPLE_INSTALL_DIR)
-- cp $(TARGET).dll $(DLL_INSTALL_DIR)
-- cp $(NEEDED_DLLS) $(PURPLE_INSTALL_DIR)
--
--$(OBJECTS): $(PURPLE_CONFIG_H)
--
--$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--image-base,0x64000000 -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -f $(OBJECTS)
-- rm -f $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/simple/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/simple/Makefile.in
---- pidgin-2.10.7/libpurple/protocols/simple/Makefile.in 2013-02-11 07:17:22.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/simple/Makefile.in 2013-08-16 23:51:48.486970456 -0300
-@@ -189,8 +189,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -252,8 +250,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/libpurple/protocols/simple/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/simple/Makefile.mingw
---- pidgin-2.10.7/libpurple/protocols/simple/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/simple/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,78 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of libsimple
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = libsimple
--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)
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = simple.c \
-- sipmsg.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lws2_32 \
-- -lintl \
-- -lpurple
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll
--
--install: all $(DLL_INSTALL_DIR)
-- cp $(TARGET).dll $(DLL_INSTALL_DIR)
--
--$(OBJECTS): $(PURPLE_CONFIG_H)
--
--$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -f $(OBJECTS)
-- rm -f $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/libyahoo.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/libyahoo.c
---- pidgin-2.10.7/libpurple/protocols/yahoo/libyahoo.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/libyahoo.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,348 +0,0 @@
--/*
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include "internal.h"
--
--#include <account.h>
--#include <core.h>
--
--#include "libymsg.h"
--#include "yahoochat.h"
--#include "yahoo_aliases.h"
--#include "yahoo_doodle.h"
--#include "yahoo_filexfer.h"
--#include "yahoo_picture.h"
--
--static PurplePlugin *my_protocol = NULL;
--
--static void yahoo_register_commands(void)
--{
-- purple_cmd_register("join", "s", PURPLE_CMD_P_PRPL,
-- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-- PURPLE_CMD_FLAG_PRPL_ONLY,
-- "prpl-yahoo", yahoopurple_cmd_chat_join,
-- _("join &lt;room&gt;: Join a chat room on the Yahoo network"), NULL);
-- purple_cmd_register("list", "", PURPLE_CMD_P_PRPL,
-- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-- PURPLE_CMD_FLAG_PRPL_ONLY,
-- "prpl-yahoo", yahoopurple_cmd_chat_list,
-- _("list: List rooms on the Yahoo network"), NULL);
-- purple_cmd_register("buzz", "", PURPLE_CMD_P_PRPL,
-- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
-- "prpl-yahoo", yahoopurple_cmd_buzz,
-- _("buzz: Buzz a user to get their attention"), NULL);
-- purple_cmd_register("doodle", "", PURPLE_CMD_P_PRPL,
-- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
-- "prpl-yahoo", yahoo_doodle_purple_cmd_start,
-- _("doodle: Request user to start a Doodle session"), NULL);
--}
--
--static PurpleAccount *find_acct(const char *prpl, const char *acct_id)
--{
-- PurpleAccount *acct = NULL;
--
-- /* If we have a specific acct, use it */
-- if (acct_id) {
-- acct = purple_accounts_find(acct_id, prpl);
-- if (acct && !purple_account_is_connected(acct))
-- acct = NULL;
-- } else { /* Otherwise find an active account for the protocol */
-- GList *l = purple_accounts_get_all();
-- while (l) {
-- if (!strcmp(prpl, purple_account_get_protocol_id(l->data))
-- && purple_account_is_connected(l->data)) {
-- acct = l->data;
-- break;
-- }
-- l = l->next;
-- }
-- }
--
-- return acct;
--}
--
--/* This may not be the best way to do this, but we find the first key w/o a value
-- * and assume it is the buddy name */
--static void yahoo_find_uri_novalue_param(gpointer key, gpointer value, gpointer user_data)
--{
-- char **retval = user_data;
--
-- if (value == NULL && *retval == NULL) {
-- *retval = key;
-- }
--}
--
--static gboolean yahoo_uri_handler(const char *proto, const char *cmd, GHashTable *params)
--{
-- char *acct_id = g_hash_table_lookup(params, "account");
-- PurpleAccount *acct;
--
-- if (g_ascii_strcasecmp(proto, "ymsgr"))
-- return FALSE;
--
-- acct = find_acct(purple_plugin_get_id(my_protocol), acct_id);
--
-- if (!acct)
-- return FALSE;
--
-- /* ymsgr:SendIM?screename&m=The+Message */
-- if (!g_ascii_strcasecmp(cmd, "SendIM")) {
-- char *sname = NULL;
-- g_hash_table_foreach(params, yahoo_find_uri_novalue_param, &sname);
-- if (sname) {
-- char *message = g_hash_table_lookup(params, "m");
--
-- PurpleConversation *conv = purple_find_conversation_with_account(
-- PURPLE_CONV_TYPE_IM, sname, acct);
-- if (conv == NULL)
-- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, sname);
-- purple_conversation_present(conv);
--
-- if (message) {
-- /* Spaces are encoded as '+' */
-- g_strdelimit(message, "+", ' ');
-- purple_conv_send_confirm(conv, message);
-- }
-- }
-- /* else
-- **If pidgindialogs_im() was in the core, we could use it here.
-- * It is all purple_request_* based, but I'm not sure it really belongs in the core
-- pidgindialogs_im(); */
--
-- return TRUE;
-- }
-- /* ymsgr:Chat?roomname */
-- else if (!g_ascii_strcasecmp(cmd, "Chat")) {
-- char *rname = NULL;
-- g_hash_table_foreach(params, yahoo_find_uri_novalue_param, &rname);
-- if (rname) {
-- /* This is somewhat hacky, but the params aren't useful after this command */
-- g_hash_table_insert(params, g_strdup("room"), g_strdup(rname));
-- g_hash_table_insert(params, g_strdup("type"), g_strdup("Chat"));
-- serv_join_chat(purple_account_get_connection(acct), params);
-- }
-- /* else
-- ** Same as above (except that this would have to be re-written using purple_request_*)
-- pidgin_blist_joinchat_show(); */
--
-- return TRUE;
-- }
-- /* ymsgr:AddFriend?name */
-- else if (!g_ascii_strcasecmp(cmd, "AddFriend")) {
-- char *name = NULL;
-- g_hash_table_foreach(params, yahoo_find_uri_novalue_param, &name);
-- purple_blist_request_add_buddy(acct, name, NULL, NULL);
-- return TRUE;
-- }
--
-- return FALSE;
--}
--
--static GHashTable *
--yahoo_get_account_text_table(PurpleAccount *account)
--{
-- GHashTable *table;
-- table = g_hash_table_new(g_str_hash, g_str_equal);
-- g_hash_table_insert(table, "login_label", (gpointer)_("Yahoo ID..."));
-- return table;
--}
--
--static gboolean yahoo_unload_plugin(PurplePlugin *plugin)
--{
-- yahoo_dest_colorht();
--
-- return TRUE;
--}
--
--static PurpleWhiteboardPrplOps yahoo_whiteboard_prpl_ops =
--{
-- yahoo_doodle_start,
-- yahoo_doodle_end,
-- yahoo_doodle_get_dimensions,
-- NULL,
-- yahoo_doodle_get_brush,
-- yahoo_doodle_set_brush,
-- yahoo_doodle_send_draw_list,
-- yahoo_doodle_clear,
--
-- /* padding */
-- NULL,
-- NULL,
-- NULL,
-- NULL
--};
--
--static PurplePluginProtocolInfo prpl_info =
--{
-- OPT_PROTO_MAIL_CHECK | OPT_PROTO_CHAT_TOPIC,
-- NULL, /* user_splits */
-- NULL, /* protocol_options */
-- {"png,gif,jpeg", 96, 96, 96, 96, 0, PURPLE_ICON_SCALE_SEND},
-- yahoo_list_icon,
-- yahoo_list_emblem,
-- yahoo_status_text,
-- yahoo_tooltip_text,
-- yahoo_status_types,
-- yahoo_blist_node_menu,
-- yahoo_c_info,
-- yahoo_c_info_defaults,
-- yahoo_login,
-- yahoo_close,
-- yahoo_send_im,
-- NULL, /* set info */
-- yahoo_send_typing,
-- yahoo_get_info,
-- yahoo_set_status,
-- yahoo_set_idle,
-- NULL, /* change_passwd*/
-- yahoo_add_buddy,
-- NULL, /* add_buddies */
-- yahoo_remove_buddy,
-- NULL, /* remove_buddies */
-- NULL, /* add_permit */
-- yahoo_add_deny,
-- NULL, /* rem_permit */
-- yahoo_rem_deny,
-- yahoo_set_permit_deny,
-- yahoo_c_join,
-- NULL, /* reject chat invite */
-- yahoo_get_chat_name,
-- yahoo_c_invite,
-- yahoo_c_leave,
-- NULL, /* chat whisper */
-- yahoo_c_send,
-- yahoo_keepalive,
-- NULL, /* register_user */
-- NULL, /* get_cb_info */
-- NULL, /* get_cb_away */
-- yahoo_update_alias, /* alias_buddy */
-- yahoo_change_buddys_group,
-- yahoo_rename_group,
-- NULL, /* buddy_free */
-- NULL, /* convo_closed */
-- purple_normalize_nocase, /* normalize */
-- yahoo_set_buddy_icon,
-- NULL, /* void (*remove_group)(PurpleConnection *gc, const char *group);*/
-- NULL, /* char *(*get_cb_real_name)(PurpleConnection *gc, int id, const char *who); */
-- NULL, /* set_chat_topic */
-- NULL, /* find_blist_chat */
-- yahoo_roomlist_get_list,
-- yahoo_roomlist_cancel,
-- yahoo_roomlist_expand_category,
-- yahoo_can_receive_file, /* can_receive_file */
-- yahoo_send_file,
-- yahoo_new_xfer,
-- yahoo_offline_message, /* offline_message */
-- &yahoo_whiteboard_prpl_ops,
-- NULL, /* send_raw */
-- NULL, /* roomlist_room_serialize */
-- NULL, /* unregister_user */
--
-- yahoo_send_attention,
-- yahoo_attention_types,
--
-- sizeof(PurplePluginProtocolInfo), /* struct_size */
-- yahoo_get_account_text_table, /* 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-yahoo", /**< id */
-- "Yahoo", /**< name */
-- DISPLAY_VERSION, /**< version */
-- /** summary */
-- N_("Yahoo! Protocol Plugin"),
-- /** description */
-- N_("Yahoo! Protocol Plugin"),
-- NULL, /**< author */
-- PURPLE_WEBSITE, /**< homepage */
-- NULL, /**< load */
-- yahoo_unload_plugin, /**< unload */
-- NULL, /**< destroy */
-- NULL, /**< ui_info */
-- &prpl_info, /**< extra_info */
-- NULL,
-- yahoo_actions,
--
-- /* padding */
-- NULL,
-- NULL,
-- NULL,
-- NULL
--};
--
--static void
--init_plugin(PurplePlugin *plugin)
--{
-- PurpleAccountOption *option;
--
-- option = purple_account_option_int_new(_("Pager port"), "port", YAHOO_PAGER_PORT);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
-- option = purple_account_option_string_new(_("File transfer server"), "xfer_host", YAHOO_XFER_HOST);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
-- option = purple_account_option_int_new(_("File transfer port"), "xfer_port", YAHOO_XFER_PORT);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
-- option = purple_account_option_string_new(_("Chat room locale"), "room_list_locale", YAHOO_ROOMLIST_LOCALE);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
-- option = purple_account_option_string_new(_("Encoding"), "local_charset", "UTF-8");
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
-- option = purple_account_option_bool_new(_("Ignore conference and chatroom invitations"), "ignore_invites", FALSE);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
-- option = purple_account_option_bool_new(_("Use account proxy for HTTP and HTTPS connections"), "proxy_ssl", FALSE);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
--#if 0
-- option = purple_account_option_string_new(_("Chat room list URL"), "room_list", YAHOO_ROOMLIST_URL);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--#endif
--
-- my_protocol = plugin;
-- yahoo_register_commands();
-- yahoo_init_colorht();
--
-- purple_signal_connect(purple_get_core(), "uri-handler", plugin,
-- PURPLE_CALLBACK(yahoo_uri_handler), NULL);
--}
--
--PURPLE_INIT_PLUGIN(yahoo, init_plugin, info);
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/libyahoojp.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/libyahoojp.c
---- pidgin-2.10.7/libpurple/protocols/yahoo/libyahoojp.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/libyahoojp.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,241 +0,0 @@
--/*
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include "internal.h"
--
--#include <account.h>
--
--#include "libymsg.h"
--#include "yahoochat.h"
--#include "yahoo_aliases.h"
--#include "yahoo_doodle.h"
--#include "yahoo_filexfer.h"
--#include "yahoo_picture.h"
--
--static void yahoojp_register_commands(void)
--{
-- purple_cmd_register("join", "s", PURPLE_CMD_P_PRPL,
-- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-- PURPLE_CMD_FLAG_PRPL_ONLY,
-- "prpl-yahoojp", yahoopurple_cmd_chat_join,
-- _("join &lt;room&gt;: Join a chat room on the Yahoo network"), NULL);
-- purple_cmd_register("list", "", PURPLE_CMD_P_PRPL,
-- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-- PURPLE_CMD_FLAG_PRPL_ONLY,
-- "prpl-yahoojp", yahoopurple_cmd_chat_list,
-- _("list: List rooms on the Yahoo network"), NULL);
-- purple_cmd_register("buzz", "", PURPLE_CMD_P_PRPL,
-- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
-- "prpl-yahoojp", yahoopurple_cmd_buzz,
-- _("buzz: Buzz a user to get their attention"), NULL);
-- purple_cmd_register("doodle", "", PURPLE_CMD_P_PRPL,
-- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
-- "prpl-yahoojp", yahoo_doodle_purple_cmd_start,
-- _("doodle: Request user to start a Doodle session"), NULL);
--}
--
--static GHashTable *
--yahoojp_get_account_text_table(PurpleAccount *account)
--{
-- GHashTable *table;
-- table = g_hash_table_new(g_str_hash, g_str_equal);
-- g_hash_table_insert(table, "login_label", (gpointer)_("Yahoo JAPAN ID..."));
-- return table;
--}
--
--static gboolean yahoojp_unload_plugin(PurplePlugin *plugin)
--{
-- yahoo_dest_colorht();
--
-- return TRUE;
--}
--
--static PurpleWhiteboardPrplOps yahoo_whiteboard_prpl_ops =
--{
-- yahoo_doodle_start,
-- yahoo_doodle_end,
-- yahoo_doodle_get_dimensions,
-- NULL,
-- yahoo_doodle_get_brush,
-- yahoo_doodle_set_brush,
-- yahoo_doodle_send_draw_list,
-- yahoo_doodle_clear,
--
-- /* padding */
-- NULL,
-- NULL,
-- NULL,
-- NULL
--};
--
--static PurplePluginProtocolInfo prpl_info =
--{
-- OPT_PROTO_MAIL_CHECK | OPT_PROTO_CHAT_TOPIC,
-- NULL, /* user_splits */
-- NULL, /* protocol_options */
-- {"png,gif,jpeg", 96, 96, 96, 96, 0, PURPLE_ICON_SCALE_SEND},
-- yahoo_list_icon,
-- yahoo_list_emblem,
-- yahoo_status_text,
-- yahoo_tooltip_text,
-- yahoo_status_types,
-- yahoo_blist_node_menu,
-- yahoo_c_info,
-- yahoo_c_info_defaults,
-- yahoo_login,
-- yahoo_close,
-- yahoo_send_im,
-- NULL, /* set info */
-- yahoo_send_typing,
-- yahoo_get_info,
-- yahoo_set_status,
-- yahoo_set_idle,
-- NULL, /* change_passwd*/
-- yahoo_add_buddy,
-- NULL, /* add_buddies */
-- yahoo_remove_buddy,
-- NULL, /* remove_buddies */
-- NULL, /* add_permit */
-- yahoo_add_deny,
-- NULL, /* rem_permit */
-- yahoo_rem_deny,
-- yahoo_set_permit_deny,
-- yahoo_c_join,
-- NULL, /* reject chat invite */
-- yahoo_get_chat_name,
-- yahoo_c_invite,
-- yahoo_c_leave,
-- NULL, /* chat whisper */
-- yahoo_c_send,
-- yahoo_keepalive,
-- NULL, /* register_user */
-- NULL, /* get_cb_info */
-- NULL, /* get_cb_away */
-- yahoo_update_alias, /* alias_buddy */
-- yahoo_change_buddys_group,
-- yahoo_rename_group,
-- NULL, /* buddy_free */
-- NULL, /* convo_closed */
-- purple_normalize_nocase, /* normalize */
-- yahoo_set_buddy_icon,
-- NULL, /* void (*remove_group)(PurpleConnection *gc, const char *group);*/
-- NULL, /* char *(*get_cb_real_name)(PurpleConnection *gc, int id, const char *who); */
-- NULL, /* set_chat_topic */
-- NULL, /* find_blist_chat */
-- yahoo_roomlist_get_list,
-- yahoo_roomlist_cancel,
-- yahoo_roomlist_expand_category,
-- NULL, /* can_receive_file */
-- yahoo_send_file,
-- yahoo_new_xfer,
-- yahoo_offline_message, /* offline_message */
-- &yahoo_whiteboard_prpl_ops,
-- NULL, /* send_raw */
-- NULL, /* roomlist_room_serialize */
-- NULL, /* unregister_user */
--
-- yahoo_send_attention,
-- yahoo_attention_types,
--
-- sizeof(PurplePluginProtocolInfo), /* struct_size */
-- yahoojp_get_account_text_table, /* 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-yahoojp", /**< id */
-- "Yahoo JAPAN", /**< name */
-- DISPLAY_VERSION, /**< version */
-- /** summary */
-- N_("Yahoo! JAPAN Protocol Plugin"),
-- /** description */
-- N_("Yahoo! JAPAN Protocol Plugin"),
-- NULL, /**< author */
-- PURPLE_WEBSITE, /**< homepage */
-- NULL, /**< load */
-- yahoojp_unload_plugin, /**< unload */
-- NULL, /**< destroy */
-- NULL, /**< ui_info */
-- &prpl_info, /**< extra_info */
-- NULL,
-- yahoo_actions,
--
-- /* padding */
-- NULL,
-- NULL,
-- NULL,
-- NULL
--};
--
--static void
--init_plugin(PurplePlugin *plugin)
--{
-- PurpleAccountOption *option;
--
-- option = purple_account_option_int_new(_("Pager port"), "port", YAHOO_PAGER_PORT);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
-- option = purple_account_option_string_new(_("File transfer server"), "xfer_host", YAHOOJP_XFER_HOST);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
-- option = purple_account_option_int_new(_("File transfer port"), "xfer_port", YAHOO_XFER_PORT);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
-- option = purple_account_option_string_new(_("Chat room locale"), "room_list_locale", YAHOOJP_ROOMLIST_LOCALE);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
-- option = purple_account_option_string_new(_("Encoding"), "local_charset", "UTF-8");
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
-- option = purple_account_option_bool_new(_("Ignore conference and chatroom invitations"), "ignore_invites", FALSE);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
-- option = purple_account_option_bool_new(_("Use account proxy for HTTP and HTTPS connections"), "proxy_ssl", FALSE);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--
--#if 0
-- option = purple_account_option_string_new(_("Chat room list URL"), "room_list", YAHOO_ROOMLIST_URL);
-- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
--#endif
--
-- yahoojp_register_commands();
-- yahoo_init_colorht();
--}
--
--PURPLE_INIT_PLUGIN(yahoojp, init_plugin, info);
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/libymsg.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/libymsg.c
---- pidgin-2.10.7/libpurple/protocols/yahoo/libymsg.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/libymsg.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,5298 +0,0 @@
--/*
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include "internal.h"
--
--#include "account.h"
--#include "accountopt.h"
--#include "blist.h"
--#include "cipher.h"
--#include "cmds.h"
--#include "core.h"
--#include "debug.h"
--#include "network.h"
--#include "notify.h"
--#include "privacy.h"
--#include "prpl.h"
--#include "proxy.h"
--#include "request.h"
--#include "server.h"
--#include "util.h"
--#include "version.h"
--#include "xmlnode.h"
--
--#include "libymsg.h"
--#include "yahoochat.h"
--#include "yahoo_aliases.h"
--#include "yahoo_doodle.h"
--#include "yahoo_filexfer.h"
--#include "yahoo_friend.h"
--#include "yahoo_packet.h"
--#include "yahoo_picture.h"
--#include "ycht.h"
--
--/* #define YAHOO_DEBUG */
--
--/* #define TRY_WEBMESSENGER_LOGIN 0 */
--
--/* One hour */
--#define PING_TIMEOUT 3600
--
--/* One minute */
--#define KEEPALIVE_TIMEOUT 60
--
--#ifdef TRY_WEBMESSENGER_LOGIN
--static void yahoo_login_page_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message);
--#endif /* TRY_WEBMESSENGER_LOGIN */
--
--static gboolean yahoo_is_japan(PurpleAccount *account)
--{
-- return purple_strequal(purple_account_get_protocol_id(account), "prpl-yahoojp");
--}
--
--static void yahoo_update_status(PurpleConnection *gc, const char *name, YahooFriend *f)
--{
-- char *status = NULL;
--
-- if (!gc || !name || !f || !purple_find_buddy(purple_connection_get_account(gc), name))
-- return;
--
-- switch (f->status) {
-- case YAHOO_STATUS_OFFLINE:
-- status = YAHOO_STATUS_TYPE_OFFLINE;
-- break;
-- case YAHOO_STATUS_AVAILABLE:
-- status = YAHOO_STATUS_TYPE_AVAILABLE;
-- break;
-- case YAHOO_STATUS_BRB:
-- status = YAHOO_STATUS_TYPE_BRB;
-- break;
-- case YAHOO_STATUS_BUSY:
-- status = YAHOO_STATUS_TYPE_BUSY;
-- break;
-- case YAHOO_STATUS_NOTATHOME:
-- status = YAHOO_STATUS_TYPE_NOTATHOME;
-- break;
-- case YAHOO_STATUS_NOTATDESK:
-- status = YAHOO_STATUS_TYPE_NOTATDESK;
-- break;
-- case YAHOO_STATUS_NOTINOFFICE:
-- status = YAHOO_STATUS_TYPE_NOTINOFFICE;
-- break;
-- case YAHOO_STATUS_ONPHONE:
-- status = YAHOO_STATUS_TYPE_ONPHONE;
-- break;
-- case YAHOO_STATUS_ONVACATION:
-- status = YAHOO_STATUS_TYPE_ONVACATION;
-- break;
-- case YAHOO_STATUS_OUTTOLUNCH:
-- status = YAHOO_STATUS_TYPE_OUTTOLUNCH;
-- break;
-- case YAHOO_STATUS_STEPPEDOUT:
-- status = YAHOO_STATUS_TYPE_STEPPEDOUT;
-- break;
-- case YAHOO_STATUS_INVISIBLE: /* this should never happen? */
-- status = YAHOO_STATUS_TYPE_INVISIBLE;
-- break;
-- case YAHOO_STATUS_CUSTOM:
-- case YAHOO_STATUS_IDLE:
-- if (!f->away)
-- status = YAHOO_STATUS_TYPE_AVAILABLE;
-- else
-- status = YAHOO_STATUS_TYPE_AWAY;
-- break;
-- default:
-- purple_debug_warning("yahoo", "Warning, unknown status %d\n", f->status);
-- break;
-- }
--
-- if (status) {
-- if (f->status == YAHOO_STATUS_CUSTOM)
-- purple_prpl_got_user_status(purple_connection_get_account(gc), name, status, "message",
-- yahoo_friend_get_status_message(f), NULL);
-- else
-- purple_prpl_got_user_status(purple_connection_get_account(gc), name, status, NULL);
-- }
--
-- if (f->idle != 0)
-- purple_prpl_got_user_idle(purple_connection_get_account(gc), name, TRUE, f->idle);
-- else
-- purple_prpl_got_user_idle(purple_connection_get_account(gc), name, FALSE, 0);
--
-- if (f->sms)
-- purple_prpl_got_user_status(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE, NULL);
-- else
-- purple_prpl_got_user_status_deactive(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE);
--}
--
--static void yahoo_process_status(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- PurpleAccount *account = purple_connection_get_account(gc);
-- GSList *l = pkt->hash;
-- YahooFriend *f = NULL;
-- char *name = NULL;
-- gboolean unicode = FALSE;
-- char *message = NULL;
-- YahooFederation fed = YAHOO_FEDERATION_NONE;
-- char *fedname = NULL;
--
-- if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) {
-- if (!purple_account_get_remember_password(account))
-- purple_account_set_password(account, NULL);
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NAME_IN_USE,
-- _("You have signed on from another location"));
-- return;
-- }
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 0: /* we won't actually do anything with this */
-- case 1: /* we won't actually do anything with this */
-- break;
-- case 8: /* how many online buddies we have */
-- break;
-- case 7: /* the current buddy */
-- /* update the previous buddy before changing the variables */
-- if (f) {
-- if (message)
-- yahoo_friend_set_status_message(f, yahoo_string_decode(gc, message, unicode));
-- if (name)
-- yahoo_update_status(gc, name, f);
-- }
-- name = message = NULL;
-- f = NULL;
-- if (pair->value && g_utf8_validate(pair->value, -1, NULL)) {
-- GSList *tmplist;
--
-- name = pair->value;
--
-- /* Look ahead to see if we have the federation info about the buddy */
-- for (tmplist = l->next; tmplist; tmplist = tmplist->next) {
-- struct yahoo_pair *p = tmplist->data;
-- if (p->key == 7)
-- break;
-- if (p->key == 241) {
-- fed = strtol(p->value, NULL, 10);
-- g_free(fedname);
-- switch (fed) {
-- case YAHOO_FEDERATION_MSN:
-- name = fedname = g_strconcat("msn/", name, NULL);
-- break;
-- case YAHOO_FEDERATION_OCS:
-- name = fedname = g_strconcat("ocs/", name, NULL);
-- break;
-- case YAHOO_FEDERATION_IBM:
-- name = fedname = g_strconcat("ibm/", name, NULL);
-- break;
-- case YAHOO_FEDERATION_NONE:
-- default:
-- fedname = NULL;
-- break;
-- }
-- break;
-- }
-- }
-- f = yahoo_friend_find_or_new(gc, name);
-- f->fed = fed;
-- }
-- break;
-- case 10: /* state */
-- if (!f)
-- break;
--
-- f->status = strtol(pair->value, NULL, 10);
-- if ((f->status >= YAHOO_STATUS_BRB) && (f->status <= YAHOO_STATUS_STEPPEDOUT))
-- f->away = 1;
-- else
-- f->away = 0;
--
-- if (f->status == YAHOO_STATUS_IDLE) {
-- /* Idle may have already been set in a more precise way in case 137 */
-- if (f->idle == 0)
-- {
-- if(pkt->service == YAHOO_SERVICE_STATUS_15)
-- f->idle = -1;
-- else
-- f->idle = time(NULL);
-- }
-- } else
-- f->idle = 0;
--
-- if (f->status != YAHOO_STATUS_CUSTOM)
-- yahoo_friend_set_status_message(f, NULL);
--
-- f->sms = 0;
-- break;
-- case 19: /* custom message */
-- if (f)
-- message = pair->value;
-- break;
-- case 11: /* this is the buddy's session id */
-- if (f)
-- f->session_id = strtol(pair->value, NULL, 10);
-- break;
-- case 17: /* in chat? */
-- break;
-- case 47: /* is custom status away or not? 2=idle*/
-- if (!f)
-- break;
--
-- /* I have no idea what it means when this is
-- * set when someone's available, but it doesn't
-- * mean idle. */
-- if (f->status == YAHOO_STATUS_AVAILABLE)
-- break;
--
-- f->away = strtol(pair->value, NULL, 10);
-- if (f->away == 2) {
-- /* Idle may have already been set in a more precise way in case 137 */
-- if (f->idle == 0)
-- {
-- if(pkt->service == YAHOO_SERVICE_STATUS_15)
-- f->idle = -1;
-- else
-- f->idle = time(NULL);
-- }
-- }
--
-- break;
-- case 138: /* when value is 1, either we're not idle, or we are but won't say how long */
-- if (!f)
-- break;
--
-- if( (strtol(pair->value, NULL, 10) == 1) && (f->idle) )
-- f->idle = -1;
-- break;
-- case 137: /* usually idle time in seconds, sometimes login time */
-- if (!f)
-- break;
--
-- if (f->status != YAHOO_STATUS_AVAILABLE)
-- f->idle = time(NULL) - strtol(pair->value, NULL, 10);
-- break;
-- case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */
-- if (strtol(pair->value, NULL, 10) == 0) {
-- if (f)
-- f->status = YAHOO_STATUS_OFFLINE;
-- if (name) {
-- purple_prpl_got_user_status(account, name, "offline", NULL);
-- purple_prpl_got_user_status_deactive(account, name, YAHOO_STATUS_TYPE_MOBILE);
-- }
-- break;
-- }
-- break;
-- case 60: /* SMS */
-- if (f) {
-- f->sms = strtol(pair->value, NULL, 10);
-- yahoo_update_status(gc, name, f);
-- }
-- break;
-- case 197: /* Avatars */
-- {
-- guchar *decoded;
-- char *tmp;
-- gsize len;
--
-- if (pair->value) {
-- decoded = purple_base64_decode(pair->value, &len);
-- if (decoded && len > 0) {
-- tmp = purple_str_binary_to_ascii(decoded, len);
-- purple_debug_info("yahoo", "Got key 197, value = %s\n", tmp);
-- g_free(tmp);
-- }
-- g_free(decoded);
-- }
-- break;
-- }
-- case 192: /* Pictures, aka Buddy Icons, checksum */
-- {
-- /* FIXME: Please, if you know this protocol,
-- * FIXME: fix up the strtol() stuff if possible. */
-- int cksum = strtol(pair->value, NULL, 10);
-- const char *locksum = NULL;
-- PurpleBuddy *b;
--
-- if (!name)
-- break;
--
-- b = purple_find_buddy(gc->account, name);
--
-- if (!cksum || (cksum == -1)) {
-- if (f)
-- yahoo_friend_set_buddy_icon_need_request(f, TRUE);
-- purple_buddy_icons_set_for_user(gc->account, name, NULL, 0, NULL);
-- break;
-- }
--
-- if (!f)
-- break;
--
-- yahoo_friend_set_buddy_icon_need_request(f, FALSE);
-- if (b) {
-- locksum = purple_buddy_icons_get_checksum_for_user(b);
-- if (!locksum || (cksum != strtol(locksum, NULL, 10)))
-- yahoo_send_picture_request(gc, name);
-- }
--
-- break;
-- }
-- case 16: /* Custom error message */
-- {
-- char *tmp = yahoo_string_decode(gc, pair->value, TRUE);
-- purple_notify_error(gc, NULL, tmp, NULL);
-- g_free(tmp);
-- }
-- break;
-- case 97: /* Unicode status message */
-- unicode = !strcmp(pair->value, "1");
-- break;
-- case 244: /* client version number. Yahoo Client Detection */
-- if(f && strtol(pair->value, NULL, 10))
-- f->version_id = strtol(pair->value, NULL, 10);
-- break;
-- case 241: /* Federated network buddy belongs to */
-- break; /* We process this when get '7' */
-- default:
-- purple_debug_warning("yahoo",
-- "Unknown status key %d\n", pair->key);
-- break;
-- }
--
-- l = l->next;
-- }
--
-- if (f) {
-- if (pkt->service == YAHOO_SERVICE_LOGOFF)
-- f->status = YAHOO_STATUS_OFFLINE;
-- if (message)
-- yahoo_friend_set_status_message(f, yahoo_string_decode(gc, message, unicode));
--
-- if (name) /* update the last buddy */
-- yahoo_update_status(gc, name, f);
-- }
--
-- g_free(fedname);
--}
--
--static void yahoo_do_group_check(PurpleAccount *account, GHashTable *ht, const char *name, const char *group)
--{
-- PurpleBuddy *b;
-- PurpleGroup *g;
-- GSList *list, *i;
-- gboolean onlist = FALSE;
-- char *oname = NULL;
--
-- if (g_hash_table_lookup_extended(ht, name, (gpointer *)&oname, (gpointer *)&list))
-- g_hash_table_steal(ht, oname);
-- else
-- list = purple_find_buddies(account, name);
--
-- for (i = list; i; i = i->next) {
-- b = i->data;
-- g = purple_buddy_get_group(b);
-- if (!purple_utf8_strcasecmp(group, purple_group_get_name(g))) {
-- purple_debug_misc("yahoo",
-- "Oh good, %s is in the right group (%s).\n", name, group);
-- list = g_slist_delete_link(list, i);
-- onlist = TRUE;
-- break;
-- }
-- }
--
-- if (!onlist) {
-- purple_debug_misc("yahoo",
-- "Uhoh, %s isn't on the list (or not in this group), adding him to group %s.\n", name, group);
-- if (!(g = purple_find_group(group))) {
-- g = purple_group_new(group);
-- purple_blist_add_group(g, NULL);
-- }
-- b = purple_buddy_new(account, name, NULL);
-- purple_blist_add_buddy(b, NULL, g, NULL);
-- }
--
-- if (list) {
-- if (!oname)
-- oname = g_strdup(name);
-- g_hash_table_insert(ht, oname, list);
-- } else
-- g_free(oname);
--}
--
--static void yahoo_do_group_cleanup(gpointer key, gpointer value, gpointer user_data)
--{
-- char *name = key;
-- GSList *list = value, *i;
-- PurpleBuddy *b;
-- PurpleGroup *g;
--
-- for (i = list; i; i = i->next) {
-- b = i->data;
-- g = purple_buddy_get_group(b);
-- purple_debug_misc("yahoo", "Deleting Buddy %s from group %s.\n", name,
-- purple_group_get_name(g));
-- purple_blist_remove_buddy(b);
-- }
--}
--
--static char *_getcookie(char *rawcookie)
--{
-- char *cookie = NULL;
-- char *tmpcookie;
-- char *cookieend;
--
-- if (strlen(rawcookie) < 2)
-- return NULL;
-- tmpcookie = g_strdup(rawcookie+2);
-- cookieend = strchr(tmpcookie, ';');
--
-- if (cookieend)
-- *cookieend = '\0';
--
-- cookie = g_strdup(tmpcookie);
-- g_free(tmpcookie);
--
-- return cookie;
--}
--
--static void yahoo_process_cookie(YahooData *yd, char *c)
--{
-- if (c[0] == 'Y') {
-- if (yd->cookie_y)
-- g_free(yd->cookie_y);
-- yd->cookie_y = _getcookie(c);
-- } else if (c[0] == 'T') {
-- if (yd->cookie_t)
-- g_free(yd->cookie_t);
-- yd->cookie_t = _getcookie(c);
-- } else
-- purple_debug_info("yahoo", "Unrecognized cookie '%c'\n", c[0]);
-- yd->cookies = g_slist_prepend(yd->cookies, g_strdup(c));
--}
--
--static void yahoo_process_list_15(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- GSList *l = pkt->hash;
--
-- PurpleAccount *account = purple_connection_get_account(gc);
-- YahooData *yd = gc->proto_data;
-- GHashTable *ht;
-- char *norm_bud = NULL;
-- char *temp = NULL;
-- YahooFriend *f = NULL; /* It's your friends. They're going to want you to share your StarBursts. */
-- /* But what if you had no friends? */
-- YahooFederation fed = YAHOO_FEDERATION_NONE;
-- int stealth = 0;
--
-- ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_slist_free);
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
-- l = l->next;
--
-- switch (pair->key) {
-- case 302:
-- /* This is always 318 before a group, 319 before the first s/n in a group, 320 before any ignored s/n.
-- * It is not sent for s/n's in a group after the first.
-- * All ignored s/n's are listed last, so when we see a 320 we clear the group and begin marking the
-- * s/n's as ignored. It is always followed by an identical 300 key.
-- */
-- if (pair->value && !strcmp(pair->value, "320")) {
-- /* No longer in any group; this indicates the start of the ignore list. */
-- g_free(yd->current_list15_grp);
-- yd->current_list15_grp = NULL;
-- }
--
-- break;
-- case 301: /* This is 319 before all s/n's in a group after the first. It is followed by an identical 300. */
-- if(temp != NULL) {
-- switch (fed) {
-- case YAHOO_FEDERATION_MSN:
-- norm_bud = g_strconcat("msn/", temp, NULL);
-- break;
-- case YAHOO_FEDERATION_OCS:
-- norm_bud = g_strconcat("ocs/", temp, NULL);
-- break;
-- case YAHOO_FEDERATION_IBM:
-- norm_bud = g_strconcat("ibm/", temp, NULL);
-- break;
-- case YAHOO_FEDERATION_PBX:
-- norm_bud = g_strconcat("pbx/", temp, NULL);
-- break;
-- case YAHOO_FEDERATION_NONE:
-- norm_bud = g_strdup(temp);
-- break;
-- }
-- if (yd->current_list15_grp) {
-- /* This buddy is in a group */
-- f = yahoo_friend_find_or_new(gc, norm_bud);
-- if (!purple_find_buddy(account, norm_bud)) {
-- PurpleBuddy *b;
-- PurpleGroup *g;
-- if (!(g = purple_find_group(yd->current_list15_grp))) {
-- g = purple_group_new(yd->current_list15_grp);
-- purple_blist_add_group(g, NULL);
-- }
-- b = purple_buddy_new(account, norm_bud, NULL);
-- purple_blist_add_buddy(b, NULL, g, NULL);
-- }
-- yahoo_do_group_check(account, ht, norm_bud, yd->current_list15_grp);
-- if(fed) {
-- f->fed = fed;
-- purple_debug_info("yahoo", "Setting federation to %d\n", f->fed);
-- }
-- if(stealth == 2)
-- f->presence = YAHOO_PRESENCE_PERM_OFFLINE;
--
-- /* set p2p status not connected and no p2p packet sent */
-- if(fed == YAHOO_FEDERATION_NONE) {
-- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED);
-- f->p2p_packet_sent = 0;
-- } else
-- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_DO_NOT_CONNECT);
-- } else {
-- /* This buddy is on the ignore list (and therefore in no group) */
-- purple_debug_info("yahoo", "%s adding %s to the deny list because of the ignore list / no group was found\n",account->username, norm_bud);
-- purple_privacy_deny_add(account, norm_bud, 1);
-- }
--
-- g_free(norm_bud);
-- norm_bud=NULL;
-- fed = YAHOO_FEDERATION_NONE;
-- stealth = 0;
-- g_free(temp);
-- temp = NULL;
-- }
-- break;
-- case 300: /* This is 318 before a group, 319 before any s/n in a group, and 320 before any ignored s/n. */
-- break;
-- case 65: /* This is the group */
-- g_free(yd->current_list15_grp);
-- yd->current_list15_grp = yahoo_string_decode(gc, pair->value, FALSE);
-- break;
-- case 7: /* buddy's s/n */
-- g_free(temp);
-- temp = g_strdup(purple_normalize(account, pair->value));
-- break;
-- case 241: /* user on federated network */
-- fed = strtol(pair->value, NULL, 10);
-- break;
-- case 59: /* somebody told cookies come here too, but im not sure */
-- yahoo_process_cookie(yd, pair->value);
-- break;
-- case 317: /* Stealth Setting */
-- stealth = strtol(pair->value, NULL, 10);
-- break;
-- /* case 242: */ /* this seems related to 241 */
-- /* break; */
-- }
-- }
--
-- g_hash_table_foreach(ht, yahoo_do_group_cleanup, NULL);
--
-- /* The reporter of ticket #9745 determined that we weren't retrieving the
-- * aliases during buddy list retrieval, so we never updated aliases that
-- * changed while we were signed off. */
-- yahoo_fetch_aliases(gc);
--
-- /* Now that we have processed the buddy list, we can say yahoo has connected */
-- purple_connection_set_display_name(gc, purple_normalize(account, purple_account_get_username(account)));
-- yd->logged_in = TRUE;
-- purple_debug_info("yahoo","Authentication: Connection established\n");
-- purple_connection_set_state(gc, PURPLE_CONNECTED);
-- if (yd->picture_upload_todo) {
-- yahoo_buddy_icon_upload(gc, yd->picture_upload_todo);
-- yd->picture_upload_todo = NULL;
-- }
-- yahoo_set_status(account, purple_account_get_active_status(account));
--
-- g_hash_table_destroy(ht);
-- g_free(temp);
--}
--
--static void yahoo_process_list(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- GSList *l = pkt->hash;
-- gboolean export = FALSE;
-- gboolean got_serv_list = FALSE;
-- YahooFriend *f = NULL;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- YahooData *yd = gc->proto_data;
-- GHashTable *ht;
--
-- char **lines;
-- char **split;
-- char **buddies;
-- char **tmp, **bud, *norm_bud;
-- char *grp = NULL;
--
-- if (pkt->id)
-- yd->session_id = pkt->id;
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
-- l = l->next;
--
-- switch (pair->key) {
-- case 87:
-- if (!yd->tmp_serv_blist)
-- yd->tmp_serv_blist = g_string_new(pair->value);
-- else
-- g_string_append(yd->tmp_serv_blist, pair->value);
-- break;
-- case 88:
-- if (!yd->tmp_serv_ilist)
-- yd->tmp_serv_ilist = g_string_new(pair->value);
-- else
-- g_string_append(yd->tmp_serv_ilist, pair->value);
-- break;
-- case 89:
-- yd->profiles = g_strsplit(pair->value, ",", -1);
-- break;
-- case 59: /* cookies, yum */
-- yahoo_process_cookie(yd, pair->value);
-- break;
-- case YAHOO_SERVICE_PRESENCE_PERM:
-- if (!yd->tmp_serv_plist)
-- yd->tmp_serv_plist = g_string_new(pair->value);
-- else
-- g_string_append(yd->tmp_serv_plist, pair->value);
-- break;
-- }
-- }
--
-- if (pkt->status != 0)
-- return;
--
-- if (yd->tmp_serv_blist) {
-- ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_slist_free);
--
-- lines = g_strsplit(yd->tmp_serv_blist->str, "\n", -1);
-- for (tmp = lines; *tmp; tmp++) {
-- split = g_strsplit(*tmp, ":", 2);
-- if (!split)
-- continue;
-- if (!split[0] || !split[1]) {
-- g_strfreev(split);
-- continue;
-- }
-- grp = yahoo_string_decode(gc, split[0], FALSE);
-- buddies = g_strsplit(split[1], ",", -1);
-- for (bud = buddies; bud && *bud; bud++) {
-- norm_bud = g_strdup(purple_normalize(account, *bud));
-- f = yahoo_friend_find_or_new(gc, norm_bud);
--
-- if (!purple_find_buddy(account, norm_bud)) {
-- PurpleBuddy *b;
-- PurpleGroup *g;
-- if (!(g = purple_find_group(grp))) {
-- g = purple_group_new(grp);
-- purple_blist_add_group(g, NULL);
-- }
-- b = purple_buddy_new(account, norm_bud, NULL);
-- purple_blist_add_buddy(b, NULL, g, NULL);
-- export = TRUE;
-- }
--
-- yahoo_do_group_check(account, ht, norm_bud, grp);
-- /* set p2p status not connected and no p2p packet sent */
-- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED);
-- f->p2p_packet_sent = 0;
--
-- g_free(norm_bud);
-- }
-- g_strfreev(buddies);
-- g_strfreev(split);
-- g_free(grp);
-- }
-- g_strfreev(lines);
--
-- g_string_free(yd->tmp_serv_blist, TRUE);
-- yd->tmp_serv_blist = NULL;
-- g_hash_table_foreach(ht, yahoo_do_group_cleanup, NULL);
-- g_hash_table_destroy(ht);
-- }
--
-- if (yd->tmp_serv_ilist) {
-- buddies = g_strsplit(yd->tmp_serv_ilist->str, ",", -1);
-- for (bud = buddies; bud && *bud; bud++) {
-- /* The server is already ignoring the user */
-- got_serv_list = TRUE;
-- purple_privacy_deny_add(account, *bud, 1);
-- }
-- g_strfreev(buddies);
--
-- g_string_free(yd->tmp_serv_ilist, TRUE);
-- yd->tmp_serv_ilist = NULL;
-- }
--
-- if (got_serv_list &&
-- ((account->perm_deny != PURPLE_PRIVACY_ALLOW_BUDDYLIST) &&
-- (account->perm_deny != PURPLE_PRIVACY_DENY_ALL) &&
-- (account->perm_deny != PURPLE_PRIVACY_ALLOW_USERS)))
-- {
-- account->perm_deny = PURPLE_PRIVACY_DENY_USERS;
-- purple_debug_info("yahoo", "%s privacy defaulting to PURPLE_PRIVACY_DENY_USERS.\n",
-- account->username);
-- }
--
-- if (yd->tmp_serv_plist) {
-- buddies = g_strsplit(yd->tmp_serv_plist->str, ",", -1);
-- for (bud = buddies; bud && *bud; bud++) {
-- f = yahoo_friend_find(gc, *bud);
-- if (f) {
-- purple_debug_info("yahoo", "%s setting presence for %s to PERM_OFFLINE\n",
-- account->username, *bud);
-- f->presence = YAHOO_PRESENCE_PERM_OFFLINE;
-- }
-- }
-- g_strfreev(buddies);
-- g_string_free(yd->tmp_serv_plist, TRUE);
-- yd->tmp_serv_plist = NULL;
--
-- }
-- /* Now that we've got the list, request aliases */
-- yahoo_fetch_aliases(gc);
--}
--
--/* pkt_type is YAHOO_PKT_TYPE_SERVER if pkt arrives from yahoo server, YAHOO_PKT_TYPE_P2P if pkt arrives through p2p */
--static void yahoo_process_notify(PurpleConnection *gc, struct yahoo_packet *pkt, yahoo_pkt_type pkt_type)
--{
-- PurpleAccount *account;
-- char *msg = NULL;
-- char *from = NULL;
-- char *stat = NULL;
-- char *game = NULL;
-- YahooFriend *f = NULL;
-- GSList *l = pkt->hash;
-- gint val_11 = 0;
-- YahooData *yd = gc->proto_data;
-- YahooFederation fed = YAHOO_FEDERATION_NONE;
--
-- account = purple_connection_get_account(gc);
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
-- if (pair->key == 4 || pair->key == 1)
-- from = pair->value;
-- if (pair->key == 49)
-- msg = pair->value;
-- if (pair->key == 13)
-- stat = pair->value;
-- if (pair->key == 14)
-- game = pair->value;
-- if (pair->key == 11)
-- val_11 = strtol(pair->value, NULL, 10);
-- if (pair->key == 241)
-- fed = strtol(pair->value, NULL, 10);
-- l = l->next;
-- }
--
-- if (!from || !msg)
-- return;
--
-- /* disconnect the peer if connected through p2p and sends wrong value for session id */
-- if( (pkt_type == YAHOO_PKT_TYPE_P2P) && (val_11 != yd->session_id) ) {
-- purple_debug_warning("yahoo","p2p: %s sent us notify with wrong session id. Disconnecting p2p connection to peer\n", from);
-- /* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */
-- g_hash_table_remove(yd->peers, from);
-- return;
-- }
--
-- if (!g_ascii_strncasecmp(msg, "TYPING", strlen("TYPING"))
-- && (purple_privacy_check(account, from)))
-- {
-- char *fed_from = from;
-- switch (fed) {
-- case YAHOO_FEDERATION_MSN:
-- fed_from = g_strconcat("msn/", from, NULL);
-- break;
-- case YAHOO_FEDERATION_OCS:
-- fed_from = g_strconcat("ocs/", from, NULL);
-- break;
-- case YAHOO_FEDERATION_IBM:
-- fed_from = g_strconcat("ibm/", from, NULL);
-- break;
-- case YAHOO_FEDERATION_PBX:
-- fed_from = g_strconcat("pbx/", from, NULL);
-- break;
-- case YAHOO_FEDERATION_NONE:
-- default:
-- break;
-- }
--
-- if (stat && *stat == '1')
-- serv_got_typing(gc, fed_from, 0, PURPLE_TYPING);
-- else
-- serv_got_typing_stopped(gc, fed_from);
--
-- if (fed_from != from)
-- g_free(fed_from);
--
-- } else if (!g_ascii_strncasecmp(msg, "GAME", strlen("GAME"))) {
-- PurpleBuddy *bud = purple_find_buddy(account, from);
--
-- if (!bud) {
-- purple_debug_warning("yahoo",
-- "%s is playing a game, and doesn't want you to know.\n", from);
-- }
--
-- f = yahoo_friend_find(gc, from);
-- if (!f)
-- return; /* if they're not on the list, don't bother */
--
-- yahoo_friend_set_game(f, NULL);
--
-- if (stat && *stat == '1') {
-- yahoo_friend_set_game(f, game);
-- if (bud)
-- yahoo_update_status(gc, from, f);
-- }
-- } else if (!g_ascii_strncasecmp(msg, "WEBCAMINVITE", strlen("WEBCAMINVITE"))) {
-- PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, account);
-- char *buf = g_strdup_printf(_("%s has sent you a webcam invite, which is not yet supported."), from);
-- purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NOTIFY, time(NULL));
-- g_free(buf);
-- }
--}
--
--
--struct _yahoo_im {
-- char *from;
-- char *active_id;
-- int time;
-- int utf8;
-- int buddy_icon;
-- char *id;
-- char *msg;
-- YahooFederation fed;
-- char *fed_from;
--};
--
--static void yahoo_process_sms_message(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- PurpleAccount *account;
-- GSList *l = pkt->hash;
-- struct _yahoo_im *sms = NULL;
-- YahooData *yd;
-- char *server_msg = NULL;
-- char *m;
--
-- yd = gc->proto_data;
-- account = purple_connection_get_account(gc);
--
-- while (l != NULL) {
-- struct yahoo_pair *pair = l->data;
-- if (pair->key == 4) {
-- sms = g_new0(struct _yahoo_im, 1);
-- sms->from = g_strdup_printf("+%s", pair->value);
-- sms->time = time(NULL);
-- sms->utf8 = TRUE;
-- }
-- if (pair->key == 14) {
-- if (sms)
-- sms->msg = pair->value;
-- }
-- if (pair->key == 68)
-- if(sms)
-- g_hash_table_insert(yd->sms_carrier, g_strdup(sms->from), g_strdup(pair->value));
-- if (pair->key == 16)
-- server_msg = pair->value;
-- l = l->next;
-- }
--
-- if(!sms) {
-- purple_debug_info("yahoo", "Received a malformed SMS packet!\n");
-- return;
-- }
--
-- if( (pkt->status == -1) || (pkt->status == YAHOO_STATUS_DISCONNECTED) ) {
-- if (server_msg) {
-- PurpleConversation *c;
-- c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms->from, account);
-- if (c == NULL)
-- c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sms->from);
-- purple_conversation_write(c, NULL, server_msg, PURPLE_MESSAGE_SYSTEM, time(NULL));
-- }
-- else
-- purple_notify_error(gc, NULL, _("Your SMS was not delivered"), NULL);
--
-- g_free(sms->from);
-- g_free(sms);
-- return ;
-- }
--
-- if (!sms->from || !sms->msg) {
-- g_free(sms);
-- return;
-- }
--
-- m = yahoo_string_decode(gc, sms->msg, sms->utf8);
-- serv_got_im(gc, sms->from, m, 0, sms->time);
--
-- g_free(m);
-- g_free(sms->from);
-- g_free(sms);
--}
--
--/* pkt_type is YAHOO_PKT_TYPE_SERVER if pkt arrives from yahoo server, YAHOO_PKT_TYPE_P2P if pkt arrives through p2p */
--static void yahoo_process_message(PurpleConnection *gc, struct yahoo_packet *pkt, yahoo_pkt_type pkt_type)
--{
-- PurpleAccount *account;
-- YahooData *yd = gc->proto_data;
-- GSList *l = pkt->hash;
-- GSList *list = NULL;
-- struct _yahoo_im *im = NULL;
--
-- account = purple_connection_get_account(gc);
--
-- if (pkt->status <= 1 || pkt->status == 5 || pkt->status == YAHOO_STATUS_OFFLINE) {
-- /* messages are received with status YAHOO_STATUS_OFFLINE in case of p2p */
-- while (l != NULL) {
-- struct yahoo_pair *pair = l->data;
-- if (pair->key == 4 || pair->key == 1) {
-- im = g_new0(struct _yahoo_im, 1);
-- list = g_slist_append(list, im);
-- im->from = pair->value;
-- im->time = time(NULL);
-- im->utf8 = TRUE;
-- im->fed = YAHOO_FEDERATION_NONE;
-- im->fed_from = g_strdup(im->from);
-- }
-- if (im && pair->key == 5)
-- im->active_id = pair->value;
-- if (pair->key == 97)
-- if (im)
-- im->utf8 = strtol(pair->value, NULL, 10);
-- if (pair->key == 15)
-- if (im)
-- im->time = strtol(pair->value, NULL, 10);
-- if (pair->key == 206)
-- if (im)
-- im->buddy_icon = strtol(pair->value, NULL, 10);
-- if (pair->key == 14) {
-- if (im)
-- im->msg = pair->value;
-- }
-- if (im && pair->key == 241) {
-- im->fed = strtol(pair->value, NULL, 10);
-- g_free(im->fed_from);
-- switch (im->fed) {
-- case YAHOO_FEDERATION_MSN:
-- im->fed_from = g_strconcat("msn/",im->from, NULL);
-- break;
-- case YAHOO_FEDERATION_OCS:
-- im->fed_from = g_strconcat("ocs/",im->from, NULL);
-- break;
-- case YAHOO_FEDERATION_IBM:
-- im->fed_from = g_strconcat("ibm/",im->from, NULL);
-- break;
-- case YAHOO_FEDERATION_PBX:
-- im->fed_from = g_strconcat("pbx/",im->from, NULL);
-- break;
-- case YAHOO_FEDERATION_NONE:
-- default:
-- im->fed_from = g_strdup(im->from);
-- break;
-- }
-- purple_debug_info("yahoo", "Message from federated (%d) buddy %s.\n", im->fed, im->fed_from);
--
-- }
-- /* peer session id */
-- if (im && (pair->key == 11)) {
-- /* disconnect the peer if connected through p2p and sends wrong value for session id */
-- if( (im->fed == YAHOO_FEDERATION_NONE) && (pkt_type == YAHOO_PKT_TYPE_P2P)
-- && (yd->session_id != strtol(pair->value, NULL, 10)) )
-- {
-- purple_debug_warning("yahoo","p2p: %s sent us message with wrong session id. Disconnecting p2p connection to peer\n", im->fed_from);
-- /* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */
-- g_hash_table_remove(yd->peers, im->fed_from);
-- g_free(im->fed_from);
-- g_free(im);
-- return; /* Not sure whether we should process remaining IMs in this packet */
-- }
-- }
-- /* IMV key */
-- if (im && pair->key == 63)
-- {
-- /* Check for the Doodle IMV, no IMvironment for federated buddies */
-- if (im->from != NULL && im->fed == YAHOO_FEDERATION_NONE)
-- {
-- g_hash_table_replace(yd->imvironments, g_strdup(im->from), g_strdup(pair->value));
--
-- if (strstr(pair->value, "doodle;") != NULL)
-- {
-- PurpleWhiteboard *wb;
--
-- if (!purple_privacy_check(account, im->from)) {
-- purple_debug_info("yahoo", "Doodle request from %s dropped.\n",
-- im->from);
-- g_free(im->fed_from);
-- g_free(im);
-- return;
-- }
-- /* I'm not sure the following ever happens -DAA */
-- wb = purple_whiteboard_get_session(account, im->from);
--
-- /* If a Doodle session doesn't exist between this user */
-- if(wb == NULL)
-- {
-- doodle_session *ds;
-- wb = purple_whiteboard_create(account, im->from,
-- DOODLE_STATE_REQUESTED);
-- ds = wb->proto_data;
-- ds->imv_key = g_strdup(pair->value);
--
-- yahoo_doodle_command_send_request(gc, im->from, pair->value);
-- yahoo_doodle_command_send_ready(gc, im->from, pair->value);
-- }
-- }
-- }
-- }
-- if (pair->key == 429)
-- if (im)
-- im->id = pair->value;
-- l = l->next;
-- }
-- } else if (pkt->status == 2) {
-- purple_notify_error(gc, NULL,
-- _("Your Yahoo! message did not get sent."), NULL);
-- }
--
-- for (l = list; l; l = l->next) {
-- YahooFriend *f;
-- char *m, *m2;
-- im = l->data;
--
-- if (!im->fed_from || !im->msg) {
-- g_free(im->fed_from);
-- g_free(im);
-- continue;
-- }
--
-- if (!purple_privacy_check(account, im->fed_from)) {
-- purple_debug_info("yahoo", "Message from %s dropped.\n", im->fed_from);
-- return;
-- }
--
-- /*
-- * TODO: Is there anything else we should check when determining whether
-- * we should send an acknowledgement?
-- */
-- if (im->id != NULL) {
-- /* Send acknowledgement. If we don't do this then the official
-- * Yahoo Messenger client for Windows will send us the same
-- * message 7 seconds later as an offline message. This is true
-- * for at least version 9.0.0.2162 on Windows XP. */
-- struct yahoo_packet *pkt2;
-- pkt2 = yahoo_packet_new(YAHOO_SERVICE_MESSAGE_ACK,
-- YAHOO_STATUS_AVAILABLE, pkt->id);
-- yahoo_packet_hash(pkt2, "ssisii",
-- 1, im->active_id, /* May not always be the connection's display name */
-- 5, im->from,
-- 302, 430,
-- 430, im->id,
-- 303, 430,
-- 450, 0);
-- yahoo_packet_send_and_free(pkt2, yd);
-- }
--
-- m = yahoo_string_decode(gc, im->msg, im->utf8);
-- /* This may actually not be necessary, but it appears
-- * that at least at one point some clients were sending
-- * "\r\n" as line delimiters, so we want to avoid double
-- * lines. */
-- m2 = purple_strreplace(m, "\r\n", "\n");
-- g_free(m);
-- m = m2;
-- purple_util_chrreplace(m, '\r', '\n');
-- if (!strcmp(m, "<ding>")) {
-- PurpleConversation *conv = NULL;
-- char *username;
--
-- username = g_markup_escape_text(im->fed_from, -1);
-- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,
-- username, account);
-- purple_prpl_got_attention(gc, username, YAHOO_BUZZ);
-- g_free(username);
-- g_free(m);
-- g_free(im->fed_from);
-- g_free(im);
-- continue;
-- }
--
-- m2 = yahoo_codes_to_html(m);
-- g_free(m);
--
-- serv_got_im(gc, im->fed_from, m2, 0, im->time);
-- g_free(m2);
--
-- /* Official clients don't share buddy images with federated buddies */
-- if (im->fed == YAHOO_FEDERATION_NONE) {
-- if ((f = yahoo_friend_find(gc, im->from)) && im->buddy_icon == 2) {
-- if (yahoo_friend_get_buddy_icon_need_request(f)) {
-- yahoo_send_picture_request(gc, im->from);
-- yahoo_friend_set_buddy_icon_need_request(f, FALSE);
-- }
-- }
-- }
--
-- g_free(im->fed_from);
-- g_free(im);
-- }
--
-- g_slist_free(list);
--}
--
--static void yahoo_process_sysmessage(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- GSList *l = pkt->hash;
-- char *prim, *me = NULL, *msg = NULL;
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
--
-- if (pair->key == 5)
-- me = pair->value;
-- if (pair->key == 14)
-- msg = pair->value;
--
-- l = l->next;
-- }
--
-- if (!msg || !g_utf8_validate(msg, -1, NULL))
-- return;
--
-- prim = g_strdup_printf(_("Yahoo! system message for %s:"),
-- me?me:purple_connection_get_display_name(gc));
-- purple_notify_info(NULL, NULL, prim, msg);
-- g_free(prim);
--}
--
--struct yahoo_add_request {
-- PurpleConnection *gc;
-- char *id;
-- char *who;
-- YahooFederation fed;
--};
--
--static void
--yahoo_buddy_add_authorize_cb(gpointer data)
--{
-- struct yahoo_add_request *add_req = data;
-- struct yahoo_packet *pkt;
-- YahooData *yd = add_req->gc->proto_data;
-- const char *who = add_req->who;
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- if (add_req->fed) {
-- who += 4;
-- yahoo_packet_hash(pkt, "ssiii",
-- 1, add_req->id,
-- 5, who,
-- 241, add_req->fed,
-- 13, 1,
-- 334, 0);
-- }
-- else {
-- yahoo_packet_hash(pkt, "ssii",
-- 1, add_req->id,
-- 5, who,
-- 13, 1,
-- 334, 0);
-- }
--
-- yahoo_packet_send_and_free(pkt, yd);
--
-- g_free(add_req->id);
-- g_free(add_req->who);
-- g_free(add_req);
--}
--
--static void
--yahoo_buddy_add_deny_cb(struct yahoo_add_request *add_req, const char *msg)
--{
-- YahooData *yd = add_req->gc->proto_data;
-- struct yahoo_packet *pkt;
-- char *encoded_msg = NULL;
-- const char *who = add_req->who;
--
-- if (msg && *msg)
-- encoded_msg = yahoo_string_encode(add_req->gc, msg, NULL);
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15,
-- YAHOO_STATUS_AVAILABLE, yd->session_id);
--
-- if (add_req->fed) {
-- who += 4; /* Skip fed identifier (msn|ocs|ibm)/' */
-- yahoo_packet_hash(pkt, "ssiiiis",
-- 1, add_req->id,
-- 5, who,
-- 241, add_req->fed,
-- 13, 2,
-- 334, 0,
-- 97, 1,
-- 14, encoded_msg ? encoded_msg : "");
-- }
-- else {
-- yahoo_packet_hash(pkt, "ssiiis",
-- 1, add_req->id,
-- 5, who,
-- 13, 2,
-- 334, 0,
-- 97, 1,
-- 14, encoded_msg ? encoded_msg : "");
-- }
--
--
-- yahoo_packet_send_and_free(pkt, yd);
--
-- g_free(encoded_msg);
--
-- g_free(add_req->id);
-- g_free(add_req->who);
-- g_free(add_req);
--}
--
--static void
--yahoo_buddy_add_deny_noreason_cb(struct yahoo_add_request *add_req, const char*msg)
--{
-- yahoo_buddy_add_deny_cb(add_req, NULL);
--}
--
--static void
--yahoo_buddy_add_deny_reason_cb(gpointer data) {
-- struct yahoo_add_request *add_req = data;
-- purple_request_input(add_req->gc, NULL, _("Authorization denied message:"),
-- NULL, _("No reason given."), TRUE, FALSE, NULL,
-- _("OK"), G_CALLBACK(yahoo_buddy_add_deny_cb),
-- _("Cancel"), G_CALLBACK(yahoo_buddy_add_deny_noreason_cb),
-- purple_connection_get_account(add_req->gc), add_req->who, NULL,
-- add_req);
--}
--
--static void yahoo_buddy_denied_our_add(PurpleConnection *gc, const char *who, const char *reason)
--{
-- char *notify_msg;
-- YahooData *yd = gc->proto_data;
--
-- if (who == NULL)
-- return;
--
-- if (reason != NULL) {
-- char *msg2 = yahoo_string_decode(gc, reason, FALSE);
-- notify_msg = g_strdup_printf(_("%s has (retroactively) denied your request to add them to your list for the following reason: %s."), who, msg2);
-- g_free(msg2);
-- } else
-- notify_msg = g_strdup_printf(_("%s has (retroactively) denied your request to add them to your list."), who);
--
-- purple_notify_info(gc, NULL, _("Add buddy rejected"), notify_msg);
-- g_free(notify_msg);
--
-- g_hash_table_remove(yd->friends, who);
-- purple_prpl_got_user_status(purple_connection_get_account(gc), who, "offline", NULL); /* FIXME: make this set not on list status instead */
-- /* TODO: Shouldn't we remove the buddy from our local list? */
--}
--
--static void yahoo_buddy_auth_req_15(PurpleConnection *gc, struct yahoo_packet *pkt) {
-- PurpleAccount *account;
-- GSList *l = pkt->hash;
-- const char *msg = NULL;
--
-- account = purple_connection_get_account(gc);
--
-- /* Buddy authorized/declined our addition */
-- if (pkt->status == 1) {
-- char *temp = NULL;
-- char *who = NULL;
-- int response = 0;
-- YahooFederation fed = YAHOO_FEDERATION_NONE;
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 4:
-- temp = pair->value;
-- break;
-- case 13:
-- response = strtol(pair->value, NULL, 10);
-- break;
-- case 14:
-- msg = pair->value;
-- break;
-- case 241:
-- fed = strtol(pair->value, NULL, 10);
-- break;
-- }
-- l = l->next;
-- }
--
-- switch (fed) {
-- case YAHOO_FEDERATION_MSN:
-- who = g_strconcat("msn/", temp, NULL);
-- break;
-- case YAHOO_FEDERATION_OCS:
-- who = g_strconcat("ocs/", temp, NULL);
-- break;
-- case YAHOO_FEDERATION_IBM:
-- who = g_strconcat("ibm/", temp, NULL);
-- break;
-- case YAHOO_FEDERATION_NONE:
-- default:
-- who = g_strdup(temp);
-- break;
-- }
--
-- if (response == 1) /* Authorized */
-- purple_debug_info("yahoo", "Received authorization from buddy '%s'.\n", who ? who : "(Unknown Buddy)");
-- else if (response == 2) { /* Declined */
-- purple_debug_info("yahoo", "Received authorization decline from buddy '%s'.\n", who ? who : "(Unknown Buddy)");
-- yahoo_buddy_denied_our_add(gc, who, msg);
-- } else
-- purple_debug_error("yahoo", "Received unknown authorization response of %d from buddy '%s'.\n", response, who ? who : "(Unknown Buddy)");
-- g_free(who);
-- }
-- /* Buddy requested authorization to add us. */
-- else if (pkt->status == 3) {
-- struct yahoo_add_request *add_req;
-- const char *firstname = NULL, *lastname = NULL;
-- char *temp = NULL;
--
-- add_req = g_new0(struct yahoo_add_request, 1);
-- add_req->gc = gc;
-- add_req->fed = YAHOO_FEDERATION_NONE;
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 4:
-- temp = pair->value;
-- break;
-- case 5:
-- add_req->id = g_strdup(pair->value);
-- break;
-- case 14:
-- msg = pair->value;
-- break;
-- case 216:
-- firstname = pair->value;
-- break;
-- case 241:
-- add_req->fed = strtol(pair->value, NULL, 10);
-- break;
-- case 254:
-- lastname = pair->value;
-- break;
--
-- }
-- l = l->next;
-- }
-- switch (add_req->fed) {
-- case YAHOO_FEDERATION_MSN:
-- add_req->who = g_strconcat("msn/", temp, NULL);
-- break;
-- case YAHOO_FEDERATION_OCS:
-- add_req->who = g_strconcat("ocs/", temp, NULL);
-- break;
-- case YAHOO_FEDERATION_IBM:
-- add_req->who = g_strconcat("ibm/", temp, NULL);
-- break;
-- case YAHOO_FEDERATION_NONE:
-- default:
-- add_req->who = g_strdup(temp);
-- break;
-- }
--
-- if (add_req->id && add_req->who) {
-- char *alias = NULL, *dec_msg = NULL;
--
-- if (!purple_privacy_check(account, add_req->who))
-- {
-- purple_debug_misc("yahoo", "Auth. request from %s dropped and automatically denied due to privacy settings!\n",
-- add_req->who);
-- yahoo_buddy_add_deny_cb(add_req, NULL);
-- return;
-- }
--
-- if (msg)
-- dec_msg = yahoo_string_decode(gc, msg, FALSE);
--
-- if (firstname && lastname)
-- alias = g_strdup_printf("%s %s", firstname, lastname);
-- else if (firstname)
-- alias = g_strdup(firstname);
-- else if (lastname)
-- alias = g_strdup(lastname);
--
-- /* DONE! this is almost exactly the same as what MSN does,
-- * this should probably be moved to the core.
-- */
-- purple_account_request_authorization(account, add_req->who, add_req->id,
-- alias, dec_msg,
-- purple_find_buddy(account, add_req->who) != NULL,
-- yahoo_buddy_add_authorize_cb,
-- yahoo_buddy_add_deny_reason_cb,
-- add_req);
-- g_free(alias);
-- g_free(dec_msg);
-- } else {
-- g_free(add_req->id);
-- g_free(add_req->who);
-- g_free(add_req);
-- }
-- } else {
-- purple_debug_error("yahoo", "Received authorization of unknown status (%d).\n", pkt->status);
-- }
--}
--
--/* I don't think this happens anymore in Version 15 */
--static void yahoo_buddy_added_us(PurpleConnection *gc, struct yahoo_packet *pkt) {
-- PurpleAccount *account;
-- struct yahoo_add_request *add_req;
-- char *msg = NULL;
-- GSList *l = pkt->hash;
--
-- account = purple_connection_get_account(gc);
--
-- add_req = g_new0(struct yahoo_add_request, 1);
-- add_req->gc = gc;
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 1:
-- add_req->id = g_strdup(pair->value);
-- break;
-- case 3:
-- add_req->who = g_strdup(pair->value);
-- break;
-- case 15: /* time, for when they add us and we're offline */
-- break;
-- case 14:
-- msg = pair->value;
-- break;
-- }
-- l = l->next;
-- }
--
-- if (add_req->id && add_req->who) {
-- char *dec_msg = NULL;
--
-- if (!purple_privacy_check(account, add_req->who)) {
-- purple_debug_misc("yahoo", "Auth. request from %s dropped and automatically denied due to privacy settings!\n",
-- add_req->who);
-- yahoo_buddy_add_deny_cb(add_req, NULL);
-- return;
-- }
--
-- if (msg)
-- dec_msg = yahoo_string_decode(gc, msg, FALSE);
--
-- /* DONE! this is almost exactly the same as what MSN does,
-- * this should probably be moved to the core.
-- */
-- purple_account_request_authorization(account, add_req->who, add_req->id,
-- NULL, dec_msg,
-- purple_find_buddy(account,add_req->who) != NULL,
-- yahoo_buddy_add_authorize_cb,
-- yahoo_buddy_add_deny_reason_cb, add_req);
-- g_free(dec_msg);
-- } else {
-- g_free(add_req->id);
-- g_free(add_req->who);
-- g_free(add_req);
-- }
--}
--
--/* I have no idea if this every gets called in version 15 */
--static void yahoo_buddy_denied_our_add_old(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- char *who = NULL;
-- char *msg = NULL;
-- GSList *l = pkt->hash;
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 3:
-- who = pair->value;
-- break;
-- case 14:
-- msg = pair->value;
-- break;
-- }
-- l = l->next;
-- }
--
-- yahoo_buddy_denied_our_add(gc, who, msg);
--}
--
--static void yahoo_process_contact(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- switch (pkt->status) {
-- case 1:
-- yahoo_process_status(gc, pkt);
-- return;
-- case 3:
-- yahoo_buddy_added_us(gc, pkt);
-- break;
-- case 7:
-- yahoo_buddy_denied_our_add_old(gc, pkt);
-- break;
-- default:
-- break;
-- }
--}
--
--#define OUT_CHARSET "utf-8"
--
--static char *yahoo_decode(const char *text)
--{
-- char *converted = NULL;
-- char *n, *new;
-- const char *end, *p;
-- int i, k;
--
-- n = new = g_malloc(strlen (text) + 1);
-- end = text + strlen(text);
--
-- for (p = text; p < end; p++, n++) {
-- if (*p == '\\') {
-- if (p[1] >= '0' && p[1] <= '7') {
-- p += 1;
-- for (i = 0, k = 0; k < 3; k += 1) {
-- char c = p[k];
-- if (c < '0' || c > '7') break;
-- i *= 8;
-- i += c - '0';
-- }
-- *n = i;
-- p += k - 1;
-- } else { /* bug 959248 */
-- /* If we see a \ not followed by an octal number,
-- * it means that it is actually a \\ with one \
-- * already eaten by some unknown function.
-- * This is arguably broken.
-- *
-- * I think wing is wrong here, there is no function
-- * called that I see that could have done it. I guess
-- * it is just really sending single \'s. That's yahoo
-- * for you.
-- */
-- *n = *p;
-- }
-- }
-- else
-- *n = *p;
-- }
--
-- *n = '\0';
--
-- if (strstr(text, "\033$B"))
-- converted = g_convert(new, n - new, OUT_CHARSET, "iso-2022-jp", NULL, NULL, NULL);
-- if (!converted)
-- converted = g_convert(new, n - new, OUT_CHARSET, "iso-8859-1", NULL, NULL, NULL);
-- g_free(new);
--
-- return converted;
--}
--
--static void yahoo_process_mail(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- PurpleAccount *account = purple_connection_get_account(gc);
-- YahooData *yd = gc->proto_data;
-- const char *who = NULL;
-- const char *email = NULL;
-- const char *subj = NULL;
-- const char *yahoo_mail_url = (yd->jp? YAHOOJP_MAIL_URL: YAHOO_MAIL_URL);
-- int count = 0;
-- GSList *l = pkt->hash;
--
-- if (!purple_account_get_check_mail(account))
-- return;
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
-- if (pair->key == 9)
-- count = strtol(pair->value, NULL, 10);
-- else if (pair->key == 43)
-- who = pair->value;
-- else if (pair->key == 42)
-- email = pair->value;
-- else if (pair->key == 18)
-- subj = pair->value;
-- l = l->next;
-- }
--
-- if (who && subj && email && *email) {
-- char *dec_who = yahoo_decode(who);
-- char *dec_subj = yahoo_decode(subj);
-- char *from = g_strdup_printf("%s (%s)", dec_who, email);
--
-- purple_notify_email(gc, dec_subj, from, purple_account_get_username(account),
-- yahoo_mail_url, NULL, NULL);
--
-- g_free(dec_who);
-- g_free(dec_subj);
-- g_free(from);
-- } else if (count > 0) {
-- const char *tos[2] = { purple_account_get_username(account) };
-- const char *urls[2] = { yahoo_mail_url };
--
-- purple_notify_emails(gc, count, FALSE, NULL, NULL, tos, urls,
-- NULL, NULL);
-- }
--}
--
--/* We use this structure once while we authenticate */
--struct yahoo_auth_data
--{
-- PurpleConnection *gc;
-- char *seed;
--};
--
--/* This is the y64 alphabet... it's like base64, but has a . and a _ */
--static const char base64digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._";
--
--/* This is taken from Sylpheed by Hiroyuki Yamamoto. We have our own tobase64 function
-- * in util.c, but it is different from the one yahoo uses */
--static void to_y64(char *out, const unsigned char *in, gsize inlen)
-- /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
--{
-- for (; inlen >= 3; inlen -= 3)
-- {
-- *out++ = base64digits[in[0] >> 2];
-- *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
-- *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
-- *out++ = base64digits[in[2] & 0x3f];
-- in += 3;
-- }
-- if (inlen > 0)
-- {
-- unsigned char fragment;
--
-- *out++ = base64digits[in[0] >> 2];
-- fragment = (in[0] << 4) & 0x30;
-- if (inlen > 1)
-- fragment |= in[1] >> 4;
-- *out++ = base64digits[fragment];
-- *out++ = (inlen < 2) ? '-' : base64digits[(in[1] << 2) & 0x3c];
-- *out++ = '-';
-- }
-- *out = '\0';
--}
--
--static void yahoo_auth16_stage3(PurpleConnection *gc, const char *crypt)
--{
-- YahooData *yd = gc->proto_data;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- const char *name = purple_normalize(account, purple_account_get_username(account));
-- PurpleCipher *md5_cipher;
-- PurpleCipherContext *md5_ctx;
-- guchar md5_digest[16];
-- gchar base64_string[25];
-- struct yahoo_packet *pkt;
--
-- purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage3\n");
--
-- md5_cipher = purple_ciphers_find_cipher("md5");
-- md5_ctx = purple_cipher_context_new(md5_cipher, NULL);
-- purple_cipher_context_append(md5_ctx, (guchar *)crypt, strlen(crypt));
-- purple_cipher_context_digest(md5_ctx, sizeof(md5_digest), md5_digest, NULL);
--
-- to_y64(base64_string, md5_digest, 16);
--
-- purple_debug_info("yahoo", "yahoo status: %d\n", yd->current_status);
-- pkt = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yd->current_status, yd->session_id);
--
-- if(yd->cookie_b) { /* send B cookie if we have it */
-- yahoo_packet_hash(pkt, "ssssssssss",
-- 1, name,
-- 0, name,
-- 277, yd->cookie_y,
-- 278, yd->cookie_t,
-- 307, base64_string,
-- 244, yd->jp ? YAHOOJP_CLIENT_VERSION_ID : YAHOO_CLIENT_VERSION_ID,
-- 2, name,
-- 2, "1",
-- 59, yd->cookie_b,
-- 98, purple_account_get_string(account, "room_list_locale", yd->jp ? "jp" : "us"),
-- 135, yd->jp ? YAHOOJP_CLIENT_VERSION : YAHOO_CLIENT_VERSION);
-- } else { /* don't try to send an empty B cookie - the server will be mad */
-- yahoo_packet_hash(pkt, "sssssssss",
-- 1, name,
-- 0, name,
-- 277, yd->cookie_y,
-- 278, yd->cookie_t,
-- 307, base64_string,
-- 244, yd->jp ? YAHOOJP_CLIENT_VERSION_ID : YAHOO_CLIENT_VERSION_ID,
-- 2, name,
-- 2, "1",
-- 98, purple_account_get_string(account, "room_list_locale", yd->jp ? "jp" : "us"),
-- 135, yd->jp ? YAHOOJP_CLIENT_VERSION : YAHOO_CLIENT_VERSION);
-- }
--
-- if (yd->picture_checksum)
-- yahoo_packet_hash_int(pkt, 192, yd->picture_checksum);
-- yahoo_packet_send_and_free(pkt, yd);
--
-- purple_cipher_context_destroy(md5_ctx);
--}
--
--static gchar *yahoo_auth16_get_cookie_b(gchar *headers)
--{
-- gchar **splits = g_strsplit(headers, "\r\n", -1);
-- gchar *tmp = NULL, *tmp2 = NULL, *sem = NULL;
-- int elements = g_strv_length(splits), i;
--
-- if(elements > 1) {
-- for(i = 0; i < elements; i++) {
-- if(g_ascii_strncasecmp(splits[i], "Set-Cookie: B=", 14) == 0) {
-- tmp = &splits[i][14];
-- sem = strchr(tmp, ';');
--
-- if (sem != NULL) {
-- tmp2 = g_strndup(tmp, sem - tmp);
-- purple_debug_info("yahoo", "Got needed part of B cookie: %s\n",
-- tmp2 ? tmp2 : "(null)");
-- break;
-- }
-- }
-- }
-- }
--
-- g_strfreev(splits);
-- return tmp2;
--}
--
--static void yahoo_auth16_stage2(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *ret_data, size_t len, const gchar *error_message)
--{
-- struct yahoo_auth_data *auth_data = user_data;
-- PurpleConnection *gc = auth_data->gc;
-- YahooData *yd = purple_connection_get_protocol_data(gc);
-- gboolean try_login_on_error = FALSE;
--
-- purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage2\n");
--
-- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
--
-- if (error_message != NULL) {
-- purple_debug_error("yahoo", "Login Failed, unable to retrieve stage 2 url: %s\n", error_message);
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message);
-- g_free(auth_data->seed);
-- g_free(auth_data);
-- return;
-- }
-- else if (len > 0 && ret_data && *ret_data) {
-- gchar **splits = g_strsplit(ret_data, "\r\n\r\n", -1), **split_data = NULL;
-- int totalelements = 0;
-- int response_no = -1;
-- char *crumb = NULL;
-- char *crypt = NULL;
--
-- if(g_strv_length(splits) > 1) {
-- yd->cookie_b = yahoo_auth16_get_cookie_b(splits[0]);
-- split_data = g_strsplit(splits[1], "\r\n", -1);
-- totalelements = g_strv_length(split_data);
-- }
--
-- if (totalelements >= 4) {
-- int i;
--
-- for(i = 0; i < totalelements; i++) {
-- /* I'm not exactly a fan of the magic numbers, but it's obvious,
-- * so no sense in wasting a bajillion vars or calls to strlen */
--
-- if(g_ascii_isdigit(split_data[i][0])) {
-- /* if the current line and the next line both start with numbers,
-- * the current line is the length of the body, so skip. If not,
-- * then the current line is the response code from the login process. */
-- if(!g_ascii_isdigit(split_data[i + 1][0])) {
-- response_no = strtol(split_data[i], NULL, 10);
-- purple_debug_info("yahoo", "Got auth16 stage 2 response code: %d\n",
-- response_no);
-- }
-- } else if(strncmp(split_data[i], "crumb=", 6) == 0) {
-- crumb = g_strdup(&split_data[i][6]);
--
-- if(purple_debug_is_unsafe())
-- purple_debug_info("yahoo", "Got crumb: %s\n", crumb);
--
-- } else if(strncmp(split_data[i], "Y=", 2) == 0) {
-- yd->cookie_y = g_strdup(&split_data[i][2]);
--
-- if(purple_debug_is_unsafe())
-- purple_debug_info("yahoo", "Got Y cookie: %s\n", yd->cookie_y);
--
-- } else if(strncmp(split_data[i], "T=", 2) == 0) {
-- yd->cookie_t = g_strdup(&split_data[i][2]);
--
-- if(purple_debug_is_unsafe())
-- purple_debug_info("yahoo", "Got T cookie: %s\n", yd->cookie_t);
-- }
-- }
-- }
--
-- g_strfreev(splits);
-- g_strfreev(split_data);
--
-- if(response_no != 0) {
-- /* Some error in the login process */
-- PurpleConnectionError error;
-- char *error_reason = NULL;
--
-- switch(response_no) {
-- case -1:
-- /* Some error in the received stream */
-- error_reason = g_strdup(_("Received invalid data"));
-- error = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-- break;
-- case 100:
-- /* Unknown error */
-- error_reason = g_strdup(_("Unknown error"));
-- error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
-- break;
-- default:
-- /* if we have everything we need, why not try to login irrespective of response */
-- if((crumb != NULL) && (yd->cookie_y != NULL) && (yd->cookie_t != NULL)) {
-- try_login_on_error = TRUE;
-- break;
-- }
-- error_reason = g_strdup(_("Unknown error"));
-- error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
-- break;
-- }
-- if(error_reason) {
-- purple_debug_error("yahoo", "Authentication error: %s. "
-- "Code %d\n", error_reason, response_no);
-- purple_connection_error_reason(gc, error, error_reason);
-- g_free(error_reason);
-- g_free(auth_data->seed);
-- g_free(auth_data);
-- return;
-- }
-- }
--
-- crypt = g_strconcat(crumb, auth_data->seed, NULL);
-- yahoo_auth16_stage3(gc, crypt);
-- g_free(crypt);
-- g_free(crumb);
-- }
-- g_free(auth_data->seed);
-- g_free(auth_data);
--}
--
--static void yahoo_auth16_stage1_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *ret_data, size_t len, const gchar *error_message)
--{
-- struct yahoo_auth_data *auth_data = user_data;
-- PurpleConnection *gc = auth_data->gc;
-- YahooData *yd = purple_connection_get_protocol_data(gc);
--
-- purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage1_cb\n");
--
-- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
--
-- if (error_message != NULL) {
-- purple_debug_error("yahoo", "Login Failed, unable to retrieve login url: %s\n", error_message);
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message);
-- g_free(auth_data->seed);
-- g_free(auth_data);
-- return;
-- }
-- else if (len > 0 && ret_data && *ret_data) {
-- PurpleAccount *account = purple_connection_get_account(gc);
-- gchar **split_data = g_strsplit(ret_data, "\r\n", -1);
-- int totalelements = 0;
-- int response_no = -1;
-- char *token = NULL;
--
-- totalelements = g_strv_length(split_data);
--
-- if(totalelements == 1) { /* Received an error code */
-- response_no = strtol(split_data[0], NULL, 10);
-- } else if(totalelements == 2 || totalelements == 3 ) { /* received valid data */
-- response_no = strtol(split_data[0], NULL, 10);
-- token = g_strdup(split_data[1] + strlen("ymsgr="));
-- } else { /* It looks like a transparent proxy has returned a document we don't want */
-- response_no = -1;
-- }
--
-- g_strfreev(split_data);
--
-- if(response_no != 0) {
-- /* Some error in the login process */
-- PurpleConnectionError error;
-- char *error_reason;
--
-- switch(response_no) {
-- case -1:
-- /* Some error in the received stream */
-- error_reason = g_strdup(_("Received invalid data"));
-- error = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-- break;
-- case 1212:
-- /* Password incorrect */
-- /* Set password to NULL. Avoids account locking. Brings dialog to enter password if clicked on Re-enable account */
-- if (!purple_account_get_remember_password(account))
-- purple_account_set_password(account, NULL);
-- error_reason = g_strdup(_("Incorrect password"));
-- error = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
-- break;
-- case 1213:
-- /* security lock from too many failed login attempts */
-- error_reason = g_strdup(_("Account locked: Too many failed login "
-- "attempts. Logging into the Yahoo! website may fix this."));
-- error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
-- break;
-- case 1235:
-- /* the username does not exist */
-- error_reason = g_strdup(_("Username does not exist"));
-- error = PURPLE_CONNECTION_ERROR_INVALID_USERNAME;
-- break;
-- case 1214:
-- /* indicates a lock of some description */
-- error_reason = g_strdup(_("Account locked: Unknown reason. Logging "
-- "into the Yahoo! website may fix this."));
-- error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
-- break;
-- case 1236:
-- /* indicates a lock due to logging in too frequently */
-- error_reason = g_strdup(_("Account locked: You have been logging in too "
-- "frequently. Wait a few minutes before trying to connect "
-- "again. Logging into the Yahoo! website may help."));
-- error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
-- break;
-- case 100:
-- /* username or password missing */
-- error_reason = g_strdup(_("Username or password missing"));
-- error = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
-- break;
-- default:
-- /* Unknown error! */
-- error_reason = g_strdup_printf(_("Unknown error (%d)"), response_no);
-- error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
-- break;
-- }
-- purple_debug_error("yahoo", "Authentication error: %s. Code %d\n",
-- error_reason, response_no);
-- purple_connection_error_reason(gc, error, error_reason);
-- g_free(error_reason);
-- g_free(auth_data->seed);
-- g_free(auth_data);
-- g_free(token);
-- }
-- else {
-- /* OK to login, correct information provided */
-- PurpleUtilFetchUrlData *url_data = NULL;
-- char *url = NULL;
-- gboolean yahoojp = yahoo_is_japan(account);
-- gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE);
--
-- url = g_strdup_printf(yahoojp ? YAHOOJP_LOGIN_URL : YAHOO_LOGIN_URL, token);
-- url_data = purple_util_fetch_url_request_len_with_account(
-- proxy_ssl ? account : NULL, url, TRUE, YAHOO_CLIENT_USERAGENT,
-- TRUE, NULL, TRUE, -1, yahoo_auth16_stage2, auth_data);
-- if (url_data)
-- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-- g_free(url);
-- g_free(token);
-- }
-- }
--}
--
--static void yahoo_auth16_stage1(PurpleConnection *gc, const char *seed)
--{
-- YahooData *yd = purple_connection_get_protocol_data(gc);
-- PurpleAccount *account = purple_connection_get_account(gc);
-- PurpleUtilFetchUrlData *url_data = NULL;
-- struct yahoo_auth_data *auth_data = NULL;
-- char *url = NULL;
-- char *encoded_username;
-- char *encoded_password;
-- gboolean yahoojp = yahoo_is_japan(account);
-- gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE);
--
-- purple_debug_info("yahoo", "Authentication: In yahoo_auth16_stage1\n");
--
-- if(!purple_ssl_is_supported()) {
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("SSL support unavailable"));
-- return;
-- }
--
-- auth_data = g_new0(struct yahoo_auth_data, 1);
-- auth_data->gc = gc;
-- auth_data->seed = g_strdup(seed);
--
-- encoded_username = g_strdup(purple_url_encode(purple_account_get_username(purple_connection_get_account(gc))));
-- encoded_password = g_strdup(purple_url_encode(purple_connection_get_password(gc)));
-- url = g_strdup_printf(yahoojp ? YAHOOJP_TOKEN_URL : YAHOO_TOKEN_URL,
-- encoded_username, encoded_password, purple_url_encode(seed));
-- g_free(encoded_password);
-- g_free(encoded_username);
--
-- url_data = purple_util_fetch_url_request_len_with_account(
-- proxy_ssl ? account : NULL, url, TRUE,
-- YAHOO_CLIENT_USERAGENT, TRUE, NULL, FALSE, -1,
-- yahoo_auth16_stage1_cb, auth_data);
-- if (url_data)
-- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
--
-- g_free(url);
--}
--
--static void yahoo_process_auth(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- char *seed = NULL;
-- char *sn = NULL;
-- GSList *l = pkt->hash;
-- int m = 0;
-- gchar *buf;
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
-- if (pair->key == 94)
-- seed = pair->value;
-- if (pair->key == 1)
-- sn = pair->value;
-- if (pair->key == 13)
-- m = atoi(pair->value);
-- l = l->next;
-- }
--
-- if (seed) {
-- switch (m) {
-- case 0:
-- /* used to be for really old auth routine, dont support now */
-- case 1:
-- case 2: /* Yahoo ver 16 authentication */
-- yahoo_auth16_stage1(gc, seed);
-- break;
-- default:
-- {
-- GHashTable *ui_info = purple_core_get_ui_info();
--
-- buf = g_strdup_printf(_("The Yahoo server has requested the use of an unrecognized "
-- "authentication method. You will probably not be able "
-- "to successfully sign on to Yahoo. Check %s for updates."),
-- ((ui_info && g_hash_table_lookup(ui_info, "website")) ? (char *)g_hash_table_lookup(ui_info, "website") : PURPLE_WEBSITE));
-- purple_notify_error(gc, "", _("Failed Yahoo! Authentication"),
-- buf);
-- g_free(buf);
-- yahoo_auth16_stage1(gc, seed); /* Can't hurt to try it anyway. */
-- break;
-- }
-- }
-- }
--}
--
--static void ignore_buddy(PurpleBuddy *buddy) {
-- PurpleGroup *group;
-- PurpleAccount *account;
-- gchar *name;
--
-- if (!buddy)
-- return;
--
-- group = purple_buddy_get_group(buddy);
-- name = g_strdup(purple_buddy_get_name(buddy));
-- account = purple_buddy_get_account(buddy);
--
-- purple_debug_info("yahoo", "blist: Removing '%s' from buddy list.\n", name);
-- purple_account_remove_buddy(account, buddy, group);
-- purple_blist_remove_buddy(buddy);
--
-- serv_add_deny(purple_account_get_connection(account), name);
--
-- g_free(name);
--}
--
--static void keep_buddy(PurpleBuddy *b)
--{
-- purple_privacy_deny_remove(purple_buddy_get_account(b),
-- purple_buddy_get_name(b), 1);
--}
--
--static void yahoo_process_ignore(PurpleConnection *gc, struct yahoo_packet *pkt) {
-- PurpleBuddy *b;
-- GSList *l;
-- gchar *who = NULL;
-- gchar *me = NULL;
-- gchar buf[BUF_LONG];
-- gboolean ignore = TRUE;
-- gint status = 0;
--
-- for (l = pkt->hash; l; l = l->next) {
-- struct yahoo_pair *pair = l->data;
-- switch (pair->key) {
-- case 0:
-- who = pair->value;
-- break;
-- case 1:
-- me = pair->value;
-- break;
-- case 13:
-- /* 1 == ignore, 2 == unignore */
-- ignore = (strtol(pair->value, NULL, 10) == 1);
-- break;
-- case 66:
-- status = strtol(pair->value, NULL, 10);
-- break;
-- default:
-- break;
-- }
-- }
--
-- /*
-- * status
-- * 0 - ok
-- * 2 - already in ignore list, could not add
-- * 3 - not in ignore list, could not delete
-- * 12 - is a buddy, could not add (and possibly also a not-in-ignore list condition?)
-- */
-- switch (status) {
-- case 12:
-- purple_debug_info("yahoo", "Server reported \"is a buddy\" for %s while %s",
-- who, (ignore ? "ignoring" : "unignoring"));
--
-- if (ignore) {
-- b = purple_find_buddy(gc->account, who);
-- g_snprintf(buf, sizeof(buf), _("You have tried to ignore %s, but the "
-- "user is on your buddy list. Clicking \"Yes\" "
-- "will remove and ignore the buddy."), who);
-- purple_request_yes_no(gc, NULL, _("Ignore buddy?"), buf, 0,
-- gc->account, who, NULL,
-- b,
-- G_CALLBACK(ignore_buddy),
-- G_CALLBACK(keep_buddy));
-- break;
-- }
-- case 2:
-- purple_debug_info("yahoo", "Server reported that %s is already in the ignore list.\n",
-- who);
-- break;
-- case 3:
-- purple_debug_info("yahoo", "Server reported that %s is not in the ignore list; could not delete\n",
-- who);
-- case 0:
-- default:
-- break;
-- }
--}
--
--static void yahoo_process_authresp(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
--#ifdef TRY_WEBMESSENGER_LOGIN
-- YahooData *yd = gc->proto_data;
--#endif /* TRY_WEBMESSENGER_LOGIN */
-- GSList *l = pkt->hash;
-- int err = 0;
-- char *msg;
-- char *url = NULL;
-- char *fullmsg;
-- PurpleAccount *account = gc->account;
-- PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
--
-- if (pair->key == 66)
-- err = strtol(pair->value, NULL, 10);
-- else if (pair->key == 20)
-- url = pair->value;
--
-- l = l->next;
-- }
--
-- switch (err) {
-- case 0:
-- msg = g_strdup(_("Unknown error"));
-- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-- break;
-- case 3:
-- msg = g_strdup(_("Username does not exist"));
-- reason = PURPLE_CONNECTION_ERROR_INVALID_USERNAME;
-- break;
-- case 13:
--#ifdef TRY_WEBMESSENGER_LOGIN
-- if (!yd->wm) {
-- PurpleUtilFetchUrlData *url_data;
-- yd->wm = TRUE;
-- if (yd->fd >= 0)
-- close(yd->fd);
-- if (gc->inpa)
-- purple_input_remove(gc->inpa);
-- url_data = purple_util_fetch_url(WEBMESSENGER_URL, TRUE,
-- "Purple/" VERSION, FALSE, yahoo_login_page_cb, gc);
-- if (url_data != NULL)
-- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-- return;
-- }
--#endif /* TRY_WEBMESSENGER_LOGIN */
-- if (!purple_account_get_remember_password(account))
-- purple_account_set_password(account, NULL);
--
-- msg = g_strdup(_("Invalid username or password"));
-- reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
-- break;
-- case 14:
-- msg = g_strdup(_("Your account has been locked due to too many failed login attempts."
-- " Please try logging into the Yahoo! website."));
-- reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
-- break;
-- case 52:
-- /* See #9660. As much as we know, reconnecting shouldn't hurt */
-- purple_debug_info("yahoo", "Got error 52, Set to autoreconnect\n");
-- msg = g_strdup_printf(_("Unknown error 52. Reconnecting should fix this."));
-- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-- break;
-- case 1013:
-- msg = g_strdup(_("Error 1013: The username you have entered is invalid."
-- " The most common cause of this error is entering your email"
-- " address instead of your Yahoo! ID."));
-- reason = PURPLE_CONNECTION_ERROR_INVALID_USERNAME;
-- break;
-- default:
-- msg = g_strdup_printf(_("Unknown error number %d. Logging into the Yahoo! website may fix this."), err);
-- }
--
-- if (url)
-- fullmsg = g_strdup_printf("%s\n%s", msg, url);
-- else
-- fullmsg = g_strdup(msg);
--
-- purple_connection_error_reason(gc, reason, fullmsg);
-- g_free(msg);
-- g_free(fullmsg);
--}
--
--static void yahoo_process_addbuddy(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- int err = 0;
-- char *who = NULL;
-- char *temp = NULL;
-- char *group = NULL;
-- char *decoded_group;
-- char *buf;
-- YahooFriend *f;
-- GSList *l = pkt->hash;
-- YahooData *yd = gc->proto_data;
-- YahooFederation fed = YAHOO_FEDERATION_NONE;
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 66:
-- err = strtol(pair->value, NULL, 10);
-- break;
-- case 7:
-- temp = pair->value;
-- break;
-- case 65:
-- group = pair->value;
-- break;
-- case 241:
-- fed = strtol(pair->value, NULL, 10);
-- break;
-- }
--
-- l = l->next;
-- }
--
-- if (!temp)
-- return;
-- if (!group)
-- group = "";
--
-- switch (fed) {
-- case YAHOO_FEDERATION_MSN:
-- who = g_strconcat("msn/", temp, NULL);
-- break;
-- case YAHOO_FEDERATION_OCS:
-- who = g_strconcat("ocs/", temp, NULL);
-- break;
-- case YAHOO_FEDERATION_IBM:
-- who = g_strconcat("ibm/", temp, NULL);
-- break;
-- case YAHOO_FEDERATION_NONE:
-- default:
-- who = g_strdup(temp);
-- break;
-- }
--
-- if (!err || (err == 2)) { /* 0 = ok, 2 = already on serv list */
-- f = yahoo_friend_find_or_new(gc, who);
-- yahoo_update_status(gc, who, f);
-- f->fed = fed;
--
-- if( !g_hash_table_lookup(yd->peers, who) ) {
-- /* we are not connected as client, so set friend to not connected */
-- if(fed)
-- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_DO_NOT_CONNECT);
-- else {
-- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED);
-- f->p2p_packet_sent = 0;
-- }
-- }
-- else /* we are already connected. set friend to YAHOO_P2PSTATUS_WE_ARE_CLIENT */
-- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_CLIENT);
-- g_free(who);
-- return;
-- }
--
-- decoded_group = yahoo_string_decode(gc, group, FALSE);
-- buf = g_strdup_printf(_("Unable to add buddy %s to group %s to the server list on account %s."),
-- who, decoded_group, purple_connection_get_display_name(gc));
-- if (!purple_conv_present_error(who, purple_connection_get_account(gc), buf))
-- purple_notify_error(gc, NULL, _("Unable to add buddy to server list"), buf);
-- g_free(buf);
-- g_free(decoded_group);
-- g_free(who);
--}
--
--/* write pkt to the source */
--static void yahoo_p2p_write_pkt(gint source, struct yahoo_packet *pkt)
--{
-- size_t pkt_len;
-- guchar *raw_packet;
--
-- /*build the raw packet and send it to the host*/
-- pkt_len = yahoo_packet_build(pkt, 0, 0, 0, &raw_packet);
-- if(write(source, raw_packet, pkt_len) != pkt_len)
-- purple_debug_warning("yahoo","p2p: couldn't write to the source\n");
-- g_free(raw_packet);
--}
--
--static void yahoo_p2p_keepalive_cb(gpointer key, gpointer value, gpointer user_data)
--{
-- struct yahoo_p2p_data *p2p_data = value;
-- PurpleConnection *gc = user_data;
-- struct yahoo_packet *pkt_to_send;
-- PurpleAccount *account;
-- YahooData *yd = gc->proto_data;
--
-- account = purple_connection_get_account(gc);
--
-- pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash(pkt_to_send, "ssisi",
-- 4, purple_normalize(account, purple_account_get_username(account)),
-- 5, p2p_data->host_username,
-- 241, 0, /* Protocol identifier */
-- 49, "PEERTOPEER",
-- 13, 7);
-- yahoo_p2p_write_pkt(p2p_data->source, pkt_to_send);
--
-- yahoo_packet_free(pkt_to_send);
--}
--
--static gboolean yahoo_p2p_keepalive(gpointer data)
--{
-- PurpleConnection *gc = data;
-- YahooData *yd = gc->proto_data;
--
-- g_hash_table_foreach(yd->peers, yahoo_p2p_keepalive_cb, gc);
--
-- return TRUE;
--}
--
--/* destroy p2p_data associated with a peer and close p2p connection.
-- * g_hash_table_remove() calls this function to destroy p2p_data associated with the peer,
-- * call g_hash_table_remove() instead of this fucntion if peer has an entry in the table */
--static void yahoo_p2p_disconnect_destroy_data(gpointer data)
--{
-- struct yahoo_p2p_data *p2p_data;
-- YahooFriend *f;
--
-- if(!(p2p_data = data))
-- return ;
--
-- /* If friend, set him not connected */
-- f = yahoo_friend_find(p2p_data->gc, p2p_data->host_username);
-- if (f)
-- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED);
--
-- if(p2p_data->source >= 0)
-- close(p2p_data->source);
-- if (p2p_data->input_event > 0)
-- purple_input_remove(p2p_data->input_event);
-- g_free(p2p_data->host_ip);
-- g_free(p2p_data->host_username);
-- g_free(p2p_data);
--}
--
--/* exchange of initial p2pfilexfer packets, service type YAHOO_SERVICE_P2PFILEXFER */
--static void yahoo_p2p_process_p2pfilexfer(gpointer data, gint source, struct yahoo_packet *pkt)
--{
-- struct yahoo_p2p_data *p2p_data;
-- char *who = NULL;
-- GSList *l = pkt->hash;
-- struct yahoo_packet *pkt_to_send;
-- PurpleAccount *account;
-- int val_13_to_send = 0;
-- YahooData *yd;
-- YahooFriend *f;
--
-- if(!(p2p_data = data))
-- return ;
--
-- yd = p2p_data->gc->proto_data;
--
-- /* lets see whats in the packet */
-- while (l) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 4:
-- who = pair->value;
-- if(strncmp(who, p2p_data->host_username, strlen(p2p_data->host_username)) != 0) {
-- /* from whom are we receiving the packets ?? */
-- purple_debug_warning("yahoo","p2p: received data from wrong user\n");
-- return;
-- }
-- break;
-- case 13:
-- p2p_data->val_13 = strtol(pair->value, NULL, 10); /* Value should be 5-7 */
-- break;
-- /* case 5, 49 look laters, no use right now */
-- }
-- l = l->next;
-- }
--
-- account = purple_connection_get_account(p2p_data->gc);
--
-- /* key_13: sort of a counter.
-- * WHEN WE ARE CLIENT: yahoo server sends val_13 = 0, we send to peer val_13 = 1, receive back val_13 = 5,
-- * we send val_13=6, receive val_13=7, we send val_13=7, HALT. Keep sending val_13 = 7 as keep alive.
-- * WHEN WE ARE SERVER: we send val_13 = 0 to yahoo server, peer sends us val_13 = 1, we send val_13 = 5,
-- * receive val_13 = 6, send val_13 = 7, receive val_13 = 7. HALT. Keep sending val_13 = 7 as keep alive. */
--
-- switch(p2p_data->val_13) {
-- case 1 : val_13_to_send = 5; break;
-- case 5 : val_13_to_send = 6; break;
-- case 6 : val_13_to_send = 7; break;
-- case 7 : if( g_hash_table_lookup(yd->peers, p2p_data->host_username) )
-- return;
-- val_13_to_send = 7; break;
-- default: purple_debug_warning("yahoo","p2p:Unknown value for key 13\n");
-- return;
-- }
--
-- /* Build the yahoo packet */
-- pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash(pkt_to_send, "ssisi",
-- 4, purple_normalize(account, purple_account_get_username(account)),
-- 5, p2p_data->host_username,
-- 241, 0, /* Protocol identifier */
-- 49, "PEERTOPEER",
-- 13, val_13_to_send);
--
-- /* build the raw packet and send it to the host */
-- yahoo_p2p_write_pkt(source, pkt_to_send);
-- yahoo_packet_free(pkt_to_send);
--
-- if( val_13_to_send == 7 )
-- if( !g_hash_table_lookup(yd->peers, p2p_data->host_username) ) {
-- g_hash_table_insert(yd->peers, g_strdup(p2p_data->host_username), p2p_data);
-- /* If the peer is a friend, set him connected */
-- f = yahoo_friend_find(p2p_data->gc, p2p_data->host_username);
-- if (f) {
-- if(p2p_data->connection_type == YAHOO_P2P_WE_ARE_SERVER) {
-- p2p_data->session_id = f->session_id;
-- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_SERVER);
-- }
-- else
-- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_CLIENT);
-- }
-- }
--}
--
--/* callback function associated with receiving of data, not considering receipt of multiple YMSG packets in a single TCP packet */
--static void yahoo_p2p_read_pkt_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- guchar buf[1024]; /* is it safe to assume a fixed array length of 1024 ?? */
-- int len;
-- int pos = 0;
-- int pktlen;
-- struct yahoo_packet *pkt;
-- guchar *start = NULL;
-- struct yahoo_p2p_data *p2p_data;
-- YahooData *yd;
--
-- if(!(p2p_data = data))
-- return ;
-- yd = p2p_data->gc->proto_data;
--
-- len = read(source, buf, sizeof(buf));
-- if ((len < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
-- return ; /* No Worries*/
-- else if (len <= 0)
-- {
-- purple_debug_warning("yahoo","p2p: Error in connection, or host disconnected\n");
-- /* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */
-- if( g_hash_table_lookup(yd->peers, p2p_data->host_username) )
-- g_hash_table_remove(yd->peers,p2p_data->host_username);
-- else
-- yahoo_p2p_disconnect_destroy_data(data);
-- return;
-- }
--
-- if(len < YAHOO_PACKET_HDRLEN)
-- return;
--
-- if(strncmp((char *)buf, "YMSG", MIN(4, len)) != 0) {
-- /* Not a YMSG packet */
-- purple_debug_warning("yahoo","p2p: Got something other than YMSG packet\n");
--
-- start = memchr(buf + 1, 'Y', len - 1);
-- if (start == NULL)
-- return;
--
-- g_memmove(buf, start, len - (start - buf));
-- len -= start - buf;
-- }
--
-- pos += 4; /* YMSG */
-- pos += 2;
-- pos += 2;
--
-- pktlen = yahoo_get16(buf + pos); pos += 2;
-- purple_debug_misc("yahoo", "p2p: %d bytes to read\n", len);
--
-- pkt = yahoo_packet_new(0, 0, 0);
-- pkt->service = yahoo_get16(buf + pos); pos += 2;
-- pkt->status = yahoo_get32(buf + pos); pos += 4;
-- pkt->id = yahoo_get32(buf + pos); pos += 4;
--
-- purple_debug_misc("yahoo", "p2p: Yahoo Service: 0x%02x Status: %d\n",pkt->service, pkt->status);
-- yahoo_packet_read(pkt, buf + pos, pktlen);
--
-- /* packet processing */
-- switch(pkt->service) {
-- case YAHOO_SERVICE_P2PFILEXFER:
-- yahoo_p2p_process_p2pfilexfer(data, source, pkt);
-- break;
-- case YAHOO_SERVICE_MESSAGE:
-- yahoo_process_message(p2p_data->gc, pkt, YAHOO_PKT_TYPE_P2P);
-- break;
-- case YAHOO_SERVICE_NOTIFY:
-- yahoo_process_notify(p2p_data->gc, pkt, YAHOO_PKT_TYPE_P2P);
-- break;
-- default:
-- purple_debug_warning("yahoo","p2p: p2p service %d Unhandled\n",pkt->service);
-- }
--
-- yahoo_packet_free(pkt);
--}
--
--static void yahoo_p2p_server_send_connected_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- int acceptfd;
-- struct yahoo_p2p_data *p2p_data;
-- YahooData *yd;
--
-- if(!(p2p_data = data))
-- return ;
-- yd = p2p_data->gc->proto_data;
--
-- acceptfd = accept(source, NULL, 0);
-- if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
-- return;
-- else if(acceptfd == -1) {
-- purple_debug_warning("yahoo","yahoo_p2p_server_send_connected_cb: accept: %s\n", g_strerror(errno));
-- yahoo_p2p_disconnect_destroy_data(data);
-- return;
-- }
--
-- /* remove timeout */
-- if (yd->yahoo_p2p_server_timeout_handle) {
-- purple_timeout_remove(yd->yahoo_p2p_server_timeout_handle);
-- yd->yahoo_p2p_server_timeout_handle = 0;
-- }
--
-- /* remove watcher and close p2p server */
-- if (yd->yahoo_p2p_server_watcher) {
-- purple_input_remove(yd->yahoo_p2p_server_watcher);
-- yd->yahoo_p2p_server_watcher = 0;
-- }
-- if (yd->yahoo_local_p2p_server_fd >= 0) {
-- close(yd->yahoo_local_p2p_server_fd);
-- yd->yahoo_local_p2p_server_fd = -1;
-- }
--
-- /* Add an Input Read event to the file descriptor */
-- p2p_data->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_read_pkt_cb, data);
-- p2p_data->source = acceptfd;
--}
--
--static gboolean yahoo_cancel_p2p_server_listen_cb(gpointer data)
--{
-- struct yahoo_p2p_data *p2p_data;
-- YahooData *yd;
--
-- if(!(p2p_data = data))
-- return FALSE;
--
-- yd = p2p_data->gc->proto_data;
--
-- purple_debug_warning("yahoo","yahoo p2p server timeout, peer failed to connect\n");
-- yahoo_p2p_disconnect_destroy_data(data);
-- purple_input_remove(yd->yahoo_p2p_server_watcher);
-- yd->yahoo_p2p_server_watcher = 0;
-- close(yd->yahoo_local_p2p_server_fd);
-- yd->yahoo_local_p2p_server_fd = -1;
-- yd->yahoo_p2p_server_timeout_handle = 0;
--
-- return FALSE;
--}
--
--static void yahoo_p2p_server_listen_cb(int listenfd, gpointer data)
--{
-- struct yahoo_p2p_data *p2p_data;
-- YahooData *yd;
--
-- if(!(p2p_data = data))
-- return ;
--
-- yd = p2p_data->gc->proto_data;
-- yd->listen_data = NULL;
--
-- if(listenfd == -1) {
-- purple_debug_warning("yahoo","p2p: error starting p2p server\n");
-- yahoo_p2p_disconnect_destroy_data(data);
-- return;
-- }
--
-- /* Add an Input Read event to the file descriptor */
-- yd->yahoo_local_p2p_server_fd = listenfd;
-- yd->yahoo_p2p_server_watcher = purple_input_add(listenfd, PURPLE_INPUT_READ, yahoo_p2p_server_send_connected_cb,data);
--
-- /* add timeout */
-- yd->yahoo_p2p_server_timeout_handle = purple_timeout_add_seconds(YAHOO_P2P_SERVER_TIMEOUT, yahoo_cancel_p2p_server_listen_cb, data);
--}
--
--/* send p2p pkt containing our encoded ip, asking peer to connect to us */
--void yahoo_send_p2p_pkt(PurpleConnection *gc, const char *who, int val_13)
--{
-- const char *public_ip;
-- guint32 temp[4];
-- guint32 ip;
-- char temp_str[100];
-- gchar *base64_ip = NULL;
-- YahooFriend *f;
-- struct yahoo_packet *pkt;
-- PurpleAccount *account;
-- YahooData *yd = gc->proto_data;
-- struct yahoo_p2p_data *p2p_data;
-- const char *norm_username;
--
-- f = yahoo_friend_find(gc, who);
-- account = purple_connection_get_account(gc);
--
-- /* Do not send invitation if already listening for other connection */
-- if(yd->yahoo_local_p2p_server_fd >= 0)
-- return;
--
-- /* One shouldn't try to connect to self */
-- if( strcmp(purple_normalize(account, purple_account_get_username(account)), who) == 0)
-- return;
--
-- /* send packet to only those friends who arent p2p connected and to whom we havent already sent. Do not send if this condition doesn't hold good */
-- if( !( f && (yahoo_friend_get_p2p_status(f) == YAHOO_P2PSTATUS_NOT_CONNECTED) && (f->p2p_packet_sent == 0)) )
-- return;
--
-- /* Dont send p2p packet to buddies of other protocols */
-- if(f->fed)
-- return;
--
-- /* Finally, don't try to connect to buddies not online or on sms */
-- if( (f->status == YAHOO_STATUS_OFFLINE) || f->sms )
-- return;
--
-- public_ip = purple_network_get_public_ip();
-- if( (sscanf(public_ip, "%u.%u.%u.%u", &temp[0], &temp[1], &temp[2], &temp[3])) !=4 )
-- return ;
--
-- ip = (temp[3] << 24) | (temp[2] <<16) | (temp[1] << 8) | temp[0];
-- sprintf(temp_str, "%d", ip);
-- base64_ip = purple_base64_encode( (guchar *)temp_str, strlen(temp_str) );
--
-- norm_username = purple_normalize(account, purple_account_get_username(account));
-- pkt = yahoo_packet_new(YAHOO_SERVICE_PEERTOPEER, YAHOO_STATUS_AVAILABLE, 0);
-- yahoo_packet_hash(pkt, "sssissis",
-- 1, norm_username,
-- 4, norm_username,
-- 12, base64_ip, /* base64 encode ip */
-- 61, 0, /* To-do : figure out what is 61 for?? */
-- 2, "",
-- 5, who,
-- 13, val_13,
-- 49, "PEERTOPEER");
-- yahoo_packet_send_and_free(pkt, yd);
--
-- f->p2p_packet_sent = 1; /* set p2p_packet_sent to sent */
--
-- p2p_data = g_new0(struct yahoo_p2p_data, 1);
--
-- p2p_data->gc = gc;
-- p2p_data->host_ip = NULL;
-- p2p_data->host_username = g_strdup(who);
-- p2p_data->val_13 = val_13;
-- p2p_data->connection_type = YAHOO_P2P_WE_ARE_SERVER;
-- p2p_data->source = -1;
--
-- /* FIXME: If the port is already used, purple_network_listener returns NULL and old listener won't be canceled
-- * in yahoo_close function. */
-- if (yd->listen_data)
-- purple_debug_warning("yahoo","p2p: Failed to create p2p server - server already exists\n");
-- else {
-- yd->listen_data = purple_network_listen(YAHOO_PAGER_PORT_P2P, SOCK_STREAM, yahoo_p2p_server_listen_cb, p2p_data);
-- if (yd->listen_data == NULL)
-- purple_debug_warning("yahoo","p2p: Failed to created p2p server\n");
-- }
--
-- g_free(base64_ip);
--}
--
--/* function called when connection to p2p host is setup */
--static void yahoo_p2p_init_cb(gpointer data, gint source, const gchar *error_message)
--{
-- struct yahoo_p2p_data *p2p_data;
-- struct yahoo_packet *pkt_to_send;
-- PurpleAccount *account;
-- YahooData *yd;
--
-- p2p_data = data;
-- yd = p2p_data->gc->proto_data;
--
-- if(error_message != NULL) {
-- purple_debug_warning("yahoo","p2p: %s\n",error_message);
-- yahoo_send_p2p_pkt(p2p_data->gc, p2p_data->host_username, 2);/* send p2p init packet with val_13=2 */
--
-- yahoo_p2p_disconnect_destroy_data(p2p_data);
-- return;
-- }
--
-- /* Add an Input Read event to the file descriptor */
-- p2p_data->input_event = purple_input_add(source, PURPLE_INPUT_READ, yahoo_p2p_read_pkt_cb, data);
-- p2p_data->source = source;
--
-- account = purple_connection_get_account(p2p_data->gc);
--
-- /* Build the yahoo packet */
-- pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash(pkt_to_send, "ssisi",
-- 4, purple_normalize(account, purple_account_get_username(account)),
-- 5, p2p_data->host_username,
-- 241, 0, /* Protocol identifier */
-- 49, "PEERTOPEER",
-- 13, 1); /* we receive key13= 0 or 2, we send key13=1 */
--
-- yahoo_p2p_write_pkt(source, pkt_to_send); /* build raw packet and send */
-- yahoo_packet_free(pkt_to_send);
--}
--
--static void yahoo_process_p2p(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- GSList *l = pkt->hash;
-- char *who = NULL;
-- char *base64 = NULL;
-- guchar *decoded;
-- gsize len;
-- gint val_13 = 0;
-- gint val_11 = 0;
-- PurpleAccount *account;
-- YahooFriend *f;
--
-- /* if status is not YAHOO_STATUS_BRB or YAHOO_STATUS_P2P, the packet bounced back,
-- * so it contains our own ip */
-- if(pkt->status != YAHOO_STATUS_BRB && pkt->status != YAHOO_STATUS_P2P)
-- return ;
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 5:
-- /* our identity */
-- break;
-- case 4:
-- who = pair->value;
-- break;
-- case 1:
-- /* who again, the master identity this time? */
-- break;
-- case 12:
-- base64 = pair->value;
-- /* so, this is an ip address. in base64. decoded it's in ascii.
-- after strtol, it's in reversed byte order. Who thought this up?*/
-- break;
-- case 13:
-- val_13 = strtol(pair->value, NULL, 10);
-- break;
-- case 11:
-- val_11 = strtol(pair->value, NULL, 10); /* session id of peer */
-- if( (f = yahoo_friend_find(gc, who)) )
-- f->session_id = val_11;
-- break;
-- /*
-- TODO: figure these out
-- yahoo: Key: 61 Value: 0
-- yahoo: Key: 2 Value:
-- yahoo: Key: 13 Value: 0 packet count ??
-- yahoo: Key: 49 Value: PEERTOPEER
-- yahoo: Key: 140 Value: 1
-- */
--
-- }
--
-- l = l->next;
-- }
--
-- if (base64) {
-- guint32 ip;
-- YahooFriend *f;
-- char *host_ip, *tmp;
-- struct yahoo_p2p_data *p2p_data;
--
-- decoded = purple_base64_decode(base64, &len);
-- if (decoded == NULL) {
-- purple_debug_info("yahoo","p2p: Unable to decode base64 IP (%s) \n", base64);
-- return;
-- }
-- tmp = purple_str_binary_to_ascii(decoded, len);
-- purple_debug_info("yahoo", "Got P2P service packet (from server): who = %s, ip = %s\n", who, tmp);
-- g_free(tmp);
--
-- ip = strtol((gchar *)decoded, NULL, 10);
-- g_free(decoded);
-- host_ip = g_strdup_printf("%u.%u.%u.%u", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff,
-- (ip >> 24) & 0xff);
-- f = yahoo_friend_find(gc, who);
-- if (f)
-- yahoo_friend_set_ip(f, host_ip);
-- purple_debug_info("yahoo", "IP : %s\n", host_ip);
--
-- account = purple_connection_get_account(gc);
--
-- if(val_11==0) {
-- if(!f)
-- return;
-- else
-- val_11 = f->session_id;
-- }
--
-- p2p_data = g_new0(struct yahoo_p2p_data, 1);
-- p2p_data->host_username = g_strdup(who);
-- p2p_data->val_13 = val_13;
-- p2p_data->session_id = val_11;
-- p2p_data->host_ip = host_ip;
-- p2p_data->gc = gc;
-- p2p_data->connection_type = YAHOO_P2P_WE_ARE_CLIENT;
-- p2p_data->source = -1;
--
-- /* connect to host */
-- if((purple_proxy_connect(gc, account, host_ip, YAHOO_PAGER_PORT_P2P, yahoo_p2p_init_cb, p2p_data))==NULL) {
-- purple_debug_info("yahoo","p2p: Connection to %s failed\n", host_ip);
-- g_free(p2p_data->host_ip);
-- g_free(p2p_data->host_username);
-- g_free(p2p_data);
-- }
-- }
--}
--
--static void yahoo_process_audible(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- PurpleAccount *account;
-- char *who = NULL, *msg = NULL, *id = NULL;
-- GSList *l = pkt->hash;
--
-- account = purple_connection_get_account(gc);
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 4:
-- who = pair->value;
-- break;
-- case 5:
-- /* us */
-- break;
-- case 230:
-- /* the audible, in foo.locale.bar.baz format
-- eg: base.tw.smiley.smiley43 */
-- id = pair->value;
-- break;
-- case 231:
-- /* the text of the audible */
-- msg = pair->value;
-- break;
-- case 232:
-- /* SHA-1 hash of audible SWF file (eg: 4e8691499d9c0fb8374478ff9720f4a9ea4a4915) */
-- break;
-- }
--
-- l = l->next;
-- }
--
-- if (!msg)
-- msg = id;
-- if (!who || !msg)
-- return;
-- if (!g_utf8_validate(msg, -1, NULL)) {
-- purple_debug_misc("yahoo", "Warning, nonutf8 audible, ignoring!\n");
-- return;
-- }
-- if (!purple_privacy_check(account, who)) {
-- purple_debug_misc("yahoo", "Audible message from %s for %s dropped!\n",
-- purple_account_get_username(account), who);
-- return;
-- }
-- if (id) {
-- /* "http://l.yimg.com/pu/dl/aud/"+locale+"/"+id+".swf" */
-- char **audible_locale = g_strsplit(id, ".", 0);
-- char *buf = g_strdup_printf(_("[ Audible %s/%s/%s.swf ] %s"), YAHOO_AUDIBLE_URL, audible_locale[1], id, msg);
-- g_strfreev(audible_locale);
--
-- serv_got_im(gc, who, buf, 0, time(NULL));
-- g_free(buf);
-- } else
-- serv_got_im(gc, who, msg, 0, time(NULL));
--}
--
--static void yahoo_packet_process(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- switch (pkt->service) {
-- case YAHOO_SERVICE_LOGON:
-- case YAHOO_SERVICE_LOGOFF:
-- case YAHOO_SERVICE_ISAWAY:
-- case YAHOO_SERVICE_ISBACK:
-- case YAHOO_SERVICE_GAMELOGON:
-- case YAHOO_SERVICE_GAMELOGOFF:
-- case YAHOO_SERVICE_CHATLOGON:
-- case YAHOO_SERVICE_CHATLOGOFF:
-- case YAHOO_SERVICE_Y6_STATUS_UPDATE:
-- case YAHOO_SERVICE_STATUS_15:
-- yahoo_process_status(gc, pkt);
-- break;
-- case YAHOO_SERVICE_NOTIFY:
-- yahoo_process_notify(gc, pkt, YAHOO_PKT_TYPE_SERVER);
-- break;
-- case YAHOO_SERVICE_MESSAGE:
-- case YAHOO_SERVICE_GAMEMSG:
-- case YAHOO_SERVICE_CHATMSG:
-- yahoo_process_message(gc, pkt, YAHOO_PKT_TYPE_SERVER);
-- break;
-- case YAHOO_SERVICE_SYSMESSAGE:
-- yahoo_process_sysmessage(gc, pkt);
-- break;
-- case YAHOO_SERVICE_NEWMAIL:
-- yahoo_process_mail(gc, pkt);
-- break;
-- case YAHOO_SERVICE_NEWCONTACT:
-- yahoo_process_contact(gc, pkt);
-- break;
-- case YAHOO_SERVICE_AUTHRESP:
-- yahoo_process_authresp(gc, pkt);
-- break;
-- case YAHOO_SERVICE_LIST:
-- yahoo_process_list(gc, pkt);
-- break;
-- case YAHOO_SERVICE_LIST_15:
-- yahoo_process_list_15(gc, pkt);
-- break;
-- case YAHOO_SERVICE_AUTH:
-- yahoo_process_auth(gc, pkt);
-- break;
-- case YAHOO_SERVICE_AUTH_REQ_15:
-- yahoo_buddy_auth_req_15(gc, pkt);
-- break;
-- case YAHOO_SERVICE_ADDBUDDY:
-- yahoo_process_addbuddy(gc, pkt);
-- break;
-- case YAHOO_SERVICE_IGNORECONTACT:
-- yahoo_process_ignore(gc, pkt);
-- break;
-- case YAHOO_SERVICE_CONFINVITE:
-- case YAHOO_SERVICE_CONFADDINVITE:
-- yahoo_process_conference_invite(gc, pkt);
-- break;
-- case YAHOO_SERVICE_CONFDECLINE:
-- yahoo_process_conference_decline(gc, pkt);
-- break;
-- case YAHOO_SERVICE_CONFLOGON:
-- yahoo_process_conference_logon(gc, pkt);
-- break;
-- case YAHOO_SERVICE_CONFLOGOFF:
-- yahoo_process_conference_logoff(gc, pkt);
-- break;
-- case YAHOO_SERVICE_CONFMSG:
-- yahoo_process_conference_message(gc, pkt);
-- break;
-- case YAHOO_SERVICE_CHATONLINE:
-- yahoo_process_chat_online(gc, pkt);
-- break;
-- case YAHOO_SERVICE_CHATLOGOUT:
-- yahoo_process_chat_logout(gc, pkt);
-- break;
-- case YAHOO_SERVICE_CHATGOTO:
-- yahoo_process_chat_goto(gc, pkt);
-- break;
-- case YAHOO_SERVICE_CHATJOIN:
-- yahoo_process_chat_join(gc, pkt);
-- break;
-- case YAHOO_SERVICE_CHATLEAVE: /* XXX is this right? */
-- case YAHOO_SERVICE_CHATEXIT:
-- yahoo_process_chat_exit(gc, pkt);
-- break;
-- case YAHOO_SERVICE_CHATINVITE: /* XXX never seen this one, might not do it right */
-- case YAHOO_SERVICE_CHATADDINVITE:
-- yahoo_process_chat_addinvite(gc, pkt);
-- break;
-- case YAHOO_SERVICE_COMMENT:
-- yahoo_process_chat_message(gc, pkt);
-- break;
-- case YAHOO_SERVICE_PRESENCE_PERM:
-- case YAHOO_SERVICE_PRESENCE_SESSION:
-- yahoo_process_presence(gc, pkt);
-- break;
-- case YAHOO_SERVICE_P2PFILEXFER:
-- /* This case had no break and continued; thus keeping it this way.*/
-- yahoo_process_p2p(gc, pkt); /* P2PFILEXFER handled the same way as process_p2p */
-- yahoo_process_p2pfilexfer(gc, pkt); /* redundant ??, need to have a break now */
-- case YAHOO_SERVICE_FILETRANSFER:
-- yahoo_process_filetransfer(gc, pkt);
-- break;
-- case YAHOO_SERVICE_PEERTOPEER:
-- yahoo_process_p2p(gc, pkt);
-- break;
-- case YAHOO_SERVICE_PICTURE:
-- yahoo_process_picture(gc, pkt);
-- break;
-- case YAHOO_SERVICE_PICTURE_CHECKSUM:
-- yahoo_process_picture_checksum(gc, pkt);
-- break;
-- case YAHOO_SERVICE_PICTURE_UPLOAD:
-- yahoo_process_picture_upload(gc, pkt);
-- break;
-- case YAHOO_SERVICE_PICTURE_UPDATE:
-- case YAHOO_SERVICE_AVATAR_UPDATE:
-- yahoo_process_avatar_update(gc, pkt);
-- break;
-- case YAHOO_SERVICE_AUDIBLE:
-- yahoo_process_audible(gc, pkt);
-- break;
-- case YAHOO_SERVICE_CONTACT_DETAILS:
-- yahoo_process_contact_details(gc, pkt);
-- break;
-- case YAHOO_SERVICE_FILETRANS_15:
-- yahoo_process_filetrans_15(gc, pkt);
-- break;
-- case YAHOO_SERVICE_FILETRANS_INFO_15:
-- yahoo_process_filetrans_info_15(gc, pkt);
-- break;
-- case YAHOO_SERVICE_FILETRANS_ACC_15:
-- yahoo_process_filetrans_acc_15(gc, pkt);
-- break;
-- case YAHOO_SERVICE_SMS_MSG:
-- yahoo_process_sms_message(gc, pkt);
-- break;
--
-- default:
-- purple_debug_error("yahoo", "Unhandled service 0x%02x\n", pkt->service);
-- break;
-- }
--}
--
--static void yahoo_pending(gpointer data, gint source, PurpleInputCondition cond)
--{
-- PurpleConnection *gc = data;
-- YahooData *yd = gc->proto_data;
-- char buf[1024];
-- int len;
--
-- len = read(yd->fd, buf, sizeof(buf));
--
-- if (len < 0) {
-- gchar *tmp;
--
-- if (errno == EAGAIN)
-- /* No worries */
-- return;
--
-- tmp = g_strdup_printf(_("Lost connection with server: %s"),
-- g_strerror(errno));
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-- g_free(tmp);
-- return;
-- } else if (len == 0) {
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Server closed the connection"));
-- return;
-- }
-- gc->last_received = time(NULL);
-- yd->rxqueue = g_realloc(yd->rxqueue, len + yd->rxlen);
-- memcpy(yd->rxqueue + yd->rxlen, buf, len);
-- yd->rxlen += len;
--
-- while (1) {
-- struct yahoo_packet *pkt;
-- int pos = 0;
-- int pktlen;
--
-- if (yd->rxlen < YAHOO_PACKET_HDRLEN)
-- return;
--
-- if (strncmp((char *)yd->rxqueue, "YMSG", MIN(4, yd->rxlen)) != 0) {
-- /* HEY! This isn't even a YMSG packet. What
-- * are you trying to pull? */
-- guchar *start;
--
-- purple_debug_warning("yahoo", "Error in YMSG stream, got something not a YMSG packet!\n");
--
-- start = memchr(yd->rxqueue + 1, 'Y', yd->rxlen - 1);
-- if (start) {
-- g_memmove(yd->rxqueue, start, yd->rxlen - (start - yd->rxqueue));
-- yd->rxlen -= start - yd->rxqueue;
-- continue;
-- } else {
-- g_free(yd->rxqueue);
-- yd->rxqueue = NULL;
-- yd->rxlen = 0;
-- return;
-- }
-- }
--
-- pos += 4; /* YMSG */
-- pos += 2;
-- pos += 2;
--
-- pktlen = yahoo_get16(yd->rxqueue + pos); pos += 2;
-- purple_debug_misc("yahoo", "%d bytes to read, rxlen is %d\n", pktlen, yd->rxlen);
--
-- if (yd->rxlen < (YAHOO_PACKET_HDRLEN + pktlen))
-- return;
--
-- yahoo_packet_dump(yd->rxqueue, YAHOO_PACKET_HDRLEN + pktlen);
--
-- pkt = yahoo_packet_new(0, 0, 0);
--
-- pkt->service = yahoo_get16(yd->rxqueue + pos); pos += 2;
-- pkt->status = yahoo_get32(yd->rxqueue + pos); pos += 4;
-- purple_debug_misc("yahoo", "Yahoo Service: 0x%02x Status: %d\n",
-- pkt->service, pkt->status);
-- pkt->id = yahoo_get32(yd->rxqueue + pos); pos += 4;
--
-- yahoo_packet_read(pkt, yd->rxqueue + pos, pktlen);
--
-- yd->rxlen -= YAHOO_PACKET_HDRLEN + pktlen;
-- if (yd->rxlen) {
-- guchar *tmp = g_memdup(yd->rxqueue + YAHOO_PACKET_HDRLEN + pktlen, yd->rxlen);
-- g_free(yd->rxqueue);
-- yd->rxqueue = tmp;
-- } else {
-- g_free(yd->rxqueue);
-- yd->rxqueue = NULL;
-- }
--
-- yahoo_packet_process(gc, pkt);
--
-- yahoo_packet_free(pkt);
-- }
--}
--
--static void yahoo_got_connected(gpointer data, gint source, const gchar *error_message)
--{
-- PurpleConnection *gc = data;
-- YahooData *yd;
-- struct yahoo_packet *pkt;
--
-- if (source < 0) {
-- gchar *tmp;
-- tmp = g_strdup_printf(_("Unable to connect: %s"), error_message);
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-- g_free(tmp);
-- return;
-- }
--
-- yd = gc->proto_data;
-- yd->fd = source;
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, yd->current_status, yd->session_id);
--
-- yahoo_packet_hash_str(pkt, 1, purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc))));
-- yahoo_packet_send_and_free(pkt, yd);
--
-- gc->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc);
--}
--
--#ifdef TRY_WEBMESSENGER_LOGIN
--static void yahoo_got_web_connected(gpointer data, gint source, const gchar *error_message)
--{
-- PurpleConnection *gc = data;
-- YahooData *yd;
-- struct yahoo_packet *pkt;
--
-- if (source < 0) {
-- gchar *tmp;
-- tmp = g_strdup_printf(_("Unable to connect: %s"), error_message);
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-- g_free(tmp);
-- return;
-- }
--
-- yd = gc->proto_data;
-- yd->fd = source;
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_WEBLOGIN, YAHOO_STATUS_WEBLOGIN, yd->session_id);
--
-- yahoo_packet_hash(pkt, "sss", 0,
-- purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc))),
-- 1, purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc))),
-- 6, yd->auth);
-- yahoo_packet_send_and_free(pkt, yd);
--
-- g_free(yd->auth);
-- gc->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc);
--}
--
--static void yahoo_web_pending(gpointer data, gint source, PurpleInputCondition cond)
--{
-- PurpleConnection *gc = data;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- YahooData *yd = gc->proto_data;
-- char bufread[2048], *i = bufread, *buf = bufread;
-- int len;
-- GString *s;
--
-- len = read(source, bufread, sizeof(bufread) - 1);
--
-- if (len < 0) {
-- gchar *tmp;
--
-- if (errno == EAGAIN)
-- /* No worries */
-- return;
--
-- tmp = g_strdup_printf(_("Lost connection with server: %s"),
-- g_strerror(errno));
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-- g_free(tmp);
-- return;
-- } else if (len == 0) {
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Server closed the connection"));
-- return;
-- }
--
-- if (yd->rxlen > 0 || !g_strstr_len(buf, len, "\r\n\r\n")) {
-- yd->rxqueue = g_realloc(yd->rxqueue, yd->rxlen + len + 1);
-- memcpy(yd->rxqueue + yd->rxlen, buf, len);
-- yd->rxlen += len;
-- i = buf = (char *)yd->rxqueue;
-- len = yd->rxlen;
-- }
-- buf[len] = '\0';
--
-- if ((strncmp(buf, "HTTP/1.0 302", strlen("HTTP/1.0 302")) &&
-- strncmp(buf, "HTTP/1.1 302", strlen("HTTP/1.1 302")))) {
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Received unexpected HTTP response from server"));
-- purple_debug_misc("yahoo", "Unexpected HTTP response: %s\n", buf);
-- return;
-- }
--
-- s = g_string_sized_new(len);
--
-- while ((i = strstr(i, "Set-Cookie: "))) {
--
-- i += strlen("Set-Cookie: ");
-- for (;*i != ';' && *i != '\0'; i++)
-- g_string_append_c(s, *i);
--
-- g_string_append(s, "; ");
-- /* Should these cookies be included too when trying for xfer?
-- * It seems to work without these
-- */
-- }
--
-- yd->auth = g_string_free(s, FALSE);
-- purple_input_remove(gc->inpa);
-- close(source);
-- g_free(yd->rxqueue);
-- yd->rxqueue = NULL;
-- yd->rxlen = 0;
-- /* Now we have our cookies to login with. I'll go get the milk. */
-- if (purple_proxy_connect(gc, account, "wcs2.msg.dcn.yahoo.com",
-- purple_account_get_int(account, "port", YAHOO_PAGER_PORT),
-- yahoo_got_web_connected, gc) == NULL) {
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Unable to connect"));
-- return;
-- }
--}
--
--static void yahoo_got_cookies_send_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- PurpleConnection *gc;
-- YahooData *yd;
-- int written, remaining;
--
-- gc = data;
-- yd = gc->proto_data;
--
-- remaining = strlen(yd->auth) - yd->auth_written;
-- written = write(source, yd->auth + yd->auth_written, remaining);
--
-- if (written < 0 && errno == EAGAIN)
-- written = 0;
-- else if (written <= 0) {
-- gchar *tmp;
-- g_free(yd->auth);
-- yd->auth = NULL;
-- if (gc->inpa)
-- purple_input_remove(gc->inpa);
-- gc->inpa = 0;
-- tmp = g_strdup_printf(_("Lost connection with %s: %s"),
-- "login.yahoo.com:80", g_strerror(errno));
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-- g_free(tmp);
-- return;
-- }
--
-- if (written < remaining) {
-- yd->auth_written += written;
-- return;
-- }
--
-- g_free(yd->auth);
-- yd->auth = NULL;
-- yd->auth_written = 0;
-- purple_input_remove(gc->inpa);
-- gc->inpa = purple_input_add(source, PURPLE_INPUT_READ, yahoo_web_pending, gc);
--}
--
--static void yahoo_got_cookies(gpointer data, gint source, const gchar *error_message)
--{
-- PurpleConnection *gc = data;
--
-- if (source < 0) {
-- gchar *tmp;
-- tmp = g_strdup_printf(_("Unable to establish a connection with %s: %s"),
-- "login.yahoo.com:80", error_message);
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-- g_free(tmp);
-- return;
-- }
--
-- if (gc->inpa == 0)
-- {
-- gc->inpa = purple_input_add(source, PURPLE_INPUT_WRITE,
-- yahoo_got_cookies_send_cb, gc);
-- yahoo_got_cookies_send_cb(gc, source, PURPLE_INPUT_WRITE);
-- }
--}
--
--static void yahoo_login_page_hash_iter(const char *key, const char *val, GString *url)
--{
-- if (!strcmp(key, "passwd") || !strcmp(key, "login"))
-- return;
-- g_string_append_c(url, '&');
-- g_string_append(url, key);
-- g_string_append_c(url, '=');
-- if (!strcmp(key, ".save") || !strcmp(key, ".js"))
-- g_string_append_c(url, '1');
-- else if (!strcmp(key, ".challenge"))
-- g_string_append(url, val);
-- else
-- g_string_append(url, purple_url_encode(val));
--}
--
--static GHashTable *yahoo_login_page_hash(const char *buf, size_t len)
--{
-- GHashTable *hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-- const char *c = buf;
-- char *d;
-- char name[64], value[64];
-- int count;
-- int input_len = strlen("<input ");
-- int name_len = strlen("name=\"");
-- int value_len = strlen("value=\"");
-- while ((len > ((c - buf) + input_len))
-- && (c = strstr(c, "<input "))) {
-- if (!(c = g_strstr_len(c, len - (c - buf), "name=\"")))
-- continue;
-- c += name_len;
-- count = sizeof(name)-1;
-- for (d = name; (len > ((c - buf) + 1)) && *c!='"'
-- && count; c++, d++, count--)
-- *d = *c;
-- *d = '\0';
-- count = sizeof(value)-1;
-- if (!(d = g_strstr_len(c, len - (c - buf), "value=\"")))
-- continue;
-- d += value_len;
-- if (strchr(c, '>') < d)
-- break;
-- for (c = d, d = value; (len > ((c - buf) + 1))
-- && *c!='"' && count; c++, d++, count--)
-- *d = *c;
-- *d = '\0';
-- g_hash_table_insert(hash, g_strdup(name), g_strdup(value));
-- }
-- return hash;
--}
--
--static void
--yahoo_login_page_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
-- const gchar *url_text, size_t len, const gchar *error_message)
--{
-- PurpleConnection *gc = (PurpleConnection *)user_data;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- YahooData *yd = gc->proto_data;
-- const char *sn = purple_account_get_username(account);
-- const char *pass = purple_connection_get_password(gc);
-- GHashTable *hash = yahoo_login_page_hash(url_text, len);
-- GString *url = g_string_new("GET http://login.yahoo.com/config/login?login=");
-- char md5[33], *hashp = md5, *chal;
-- int i;
-- PurpleCipher *cipher;
-- PurpleCipherContext *context;
-- guchar digest[16];
--
-- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
--
-- if (error_message != NULL)
-- {
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- error_message);
-- return;
-- }
--
-- url = g_string_append(url, sn);
-- url = g_string_append(url, "&passwd=");
--
-- cipher = purple_ciphers_find_cipher("md5");
-- context = purple_cipher_context_new(cipher, NULL);
--
-- purple_cipher_context_append(context, (const guchar *)pass, strlen(pass));
-- purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
-- for (i = 0; i < 16; ++i) {
-- g_snprintf(hashp, 3, "%02x", digest[i]);
-- hashp += 2;
-- }
--
-- chal = g_strconcat(md5, g_hash_table_lookup(hash, ".challenge"), NULL);
-- purple_cipher_context_reset(context, NULL);
-- purple_cipher_context_append(context, (const guchar *)chal, strlen(chal));
-- purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
-- hashp = md5;
-- for (i = 0; i < 16; ++i) {
-- g_snprintf(hashp, 3, "%02x", digest[i]);
-- hashp += 2;
-- }
-- /*
-- * I dunno why this is here and commented out.. but in case it's needed
-- * I updated it..
--
-- purple_cipher_context_reset(context, NULL);
-- purple_cipher_context_append(context, md5, strlen(md5));
-- purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
-- hashp = md5;
-- for (i = 0; i < 16; ++i) {
-- g_snprintf(hashp, 3, "%02x", digest[i]);
-- hashp += 2;
-- }
-- */
-- g_free(chal);
--
-- url = g_string_append(url, md5);
-- g_hash_table_foreach(hash, (GHFunc)yahoo_login_page_hash_iter, url);
--
-- url = g_string_append(url, "&.hash=1&.md5=1 HTTP/1.1\r\n"
-- "Host: login.yahoo.com\r\n\r\n");
-- g_hash_table_destroy(hash);
-- yd->auth = g_string_free(url, FALSE);
-- if (purple_proxy_connect(gc, account, "login.yahoo.com", 80, yahoo_got_cookies, gc) == NULL) {
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Unable to connect"));
-- return;
-- }
--
-- purple_cipher_context_destroy(context);
--}
--#endif /* TRY_WEBMESSENGER_LOGIN */
--
--static void yahoo_picture_check(PurpleAccount *account)
--{
-- PurpleConnection *gc = purple_account_get_connection(account);
-- PurpleStoredImage *img = purple_buddy_icons_find_account_icon(account);
--
-- yahoo_set_buddy_icon(gc, img);
-- purple_imgstore_unref(img);
--}
--
--static int get_yahoo_status_from_purple_status(PurpleStatus *status)
--{
-- PurplePresence *presence;
-- const char *status_id;
-- const char *msg;
--
-- presence = purple_status_get_presence(status);
-- status_id = purple_status_get_id(status);
-- msg = purple_status_get_attr_string(status, "message");
--
-- if ((msg != NULL) && (*msg != '\0')) {
-- return YAHOO_STATUS_CUSTOM;
-- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_AVAILABLE)) {
-- return YAHOO_STATUS_AVAILABLE;
-- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_BRB)) {
-- return YAHOO_STATUS_BRB;
-- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_BUSY)) {
-- return YAHOO_STATUS_BUSY;
-- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_NOTATHOME)) {
-- return YAHOO_STATUS_NOTATHOME;
-- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_NOTATDESK)) {
-- return YAHOO_STATUS_NOTATDESK;
-- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_NOTINOFFICE)) {
-- return YAHOO_STATUS_NOTINOFFICE;
-- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_ONPHONE)) {
-- return YAHOO_STATUS_ONPHONE;
-- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_ONVACATION)) {
-- return YAHOO_STATUS_ONVACATION;
-- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_OUTTOLUNCH)) {
-- return YAHOO_STATUS_OUTTOLUNCH;
-- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_STEPPEDOUT)) {
-- return YAHOO_STATUS_STEPPEDOUT;
-- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_INVISIBLE)) {
-- return YAHOO_STATUS_INVISIBLE;
-- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_AWAY)) {
-- return YAHOO_STATUS_CUSTOM;
-- } else if (purple_presence_is_idle(presence)) {
-- return YAHOO_STATUS_IDLE;
-- } else {
-- purple_debug_error("yahoo", "Unexpected PurpleStatus!\n");
-- return YAHOO_STATUS_AVAILABLE;
-- }
--}
--
--static void yahoo_got_pager_server(PurpleUtilFetchUrlData *url_data,
-- gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message)
--{
-- YahooData *yd = user_data;
-- PurpleConnection *gc = yd->gc;
-- PurpleAccount *a = purple_connection_get_account(gc);
-- gchar **strings = NULL, *cs_server = NULL;
-- int port = purple_account_get_int(a, "port", YAHOO_PAGER_PORT);
-- int stringslen = 0;
--
-- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
--
-- if(error_message != NULL || len == 0) {
-- purple_debug_error("yahoo", "Unable to retrieve server info. %"
-- G_GSIZE_FORMAT " bytes retrieved with error message: %s\n", len,
-- error_message ? error_message : "(null)");
--
-- if(yahoo_is_japan(a)) { /* We don't know fallback hosts for Yahoo Japan :( */
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Unable to connect: The server returned an empty response."));
-- } else {
-- if(purple_proxy_connect(gc, a, YAHOO_PAGER_HOST_FALLBACK, port,
-- yahoo_got_connected, gc) == NULL) {
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Unable to connect"));
-- }
-- }
-- } else {
-- strings = g_strsplit(url_text, "\r\n", -1);
--
-- if((stringslen = g_strv_length(strings)) > 1) {
-- int i;
--
-- for(i = 0; i < stringslen; i++) {
-- if(g_ascii_strncasecmp(strings[i], "COLO_CAPACITY=", 14) == 0) {
-- purple_debug_info("yahoo", "Got COLO Capacity: %s\n", &(strings[i][14]));
-- } else if(g_ascii_strncasecmp(strings[i], "CS_IP_ADDRESS=", 14) == 0) {
-- cs_server = g_strdup(&strings[i][14]);
-- purple_debug_info("yahoo", "Got CS IP address: %s\n", cs_server);
-- }
-- }
-- }
--
-- if(cs_server) { /* got an address; get on with connecting */
-- if(purple_proxy_connect(gc, a, cs_server, port, yahoo_got_connected, gc) == NULL)
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Unable to connect"));
-- } else {
-- purple_debug_error("yahoo", "No CS address retrieved! Server "
-- "response:\n%s\n", url_text ? url_text : "(null)");
--
-- if(yahoo_is_japan(a)) { /* We don't know fallback hosts for Yahoo Japan :( */
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Unable to connect: The server's response did not contain "
-- "the necessary information"));
-- } else
-- if(purple_proxy_connect(gc, a, YAHOO_PAGER_HOST_FALLBACK, port,
-- yahoo_got_connected, gc) == NULL) {
-- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Unable to connect"));
-- }
-- }
-- }
--
-- g_strfreev(strings);
-- g_free(cs_server);
--}
--
--void yahoo_login(PurpleAccount *account) {
-- PurpleConnection *gc = purple_account_get_connection(account);
-- YahooData *yd = gc->proto_data = g_new0(YahooData, 1);
-- PurpleStatus *status = purple_account_get_active_status(account);
-- gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
-- gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE);
-- PurpleUtilFetchUrlData *url_data;
--
-- gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC;
--
-- purple_connection_update_progress(gc, _("Connecting"), 1, 2);
--
-- purple_connection_set_display_name(gc, purple_account_get_username(account));
--
-- yd->gc = gc;
-- yd->jp = yahoo_is_japan(account);
-- yd->yahoo_local_p2p_server_fd = -1;
-- yd->fd = -1;
-- yd->txhandler = 0;
-- /* TODO: Is there a good grow size for the buffer? */
-- yd->txbuf = purple_circ_buffer_new(0);
-- yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free);
-- yd->imvironments = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-- yd->xfer_peer_idstring_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
-- yd->peers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
-- yahoo_p2p_disconnect_destroy_data);
-- yd->sms_carrier = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-- yd->yahoo_p2p_timer = purple_timeout_add_seconds(YAHOO_P2P_KEEPALIVE_SECS,
-- yahoo_p2p_keepalive, gc);
-- yd->confs = NULL;
-- yd->conf_id = 2;
-- yd->last_keepalive = yd->last_ping = time(NULL);
--
-- yd->current_status = get_yahoo_status_from_purple_status(status);
--
-- yahoo_picture_check(account);
--
-- /* Get the pager server. Actually start connecting in the callback since we
-- * must have the contents of the HTTP response to proceed. */
-- url_data = purple_util_fetch_url_request_len_with_account(
-- proxy_ssl ? purple_connection_get_account(gc) : NULL,
-- yd->jp ? YAHOOJP_PAGER_HOST_REQ_URL : YAHOO_PAGER_HOST_REQ_URL,
-- use_whole_url ? TRUE : FALSE,
-- YAHOO_CLIENT_USERAGENT, FALSE, NULL, FALSE, -1,
-- yahoo_got_pager_server, yd);
-- if (url_data)
-- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
--
-- return;
--}
--
--void yahoo_close(PurpleConnection *gc) {
-- YahooData *yd = (YahooData *)gc->proto_data;
-- GSList *l;
--
-- if (gc->inpa)
-- purple_input_remove(gc->inpa);
--
-- while (yd->url_datas) {
-- purple_util_fetch_url_cancel(yd->url_datas->data);
-- yd->url_datas = g_slist_delete_link(yd->url_datas, yd->url_datas);
-- }
--
-- for (l = yd->confs; l; l = l->next) {
-- PurpleConversation *conv = l->data;
--
-- yahoo_conf_leave(yd, purple_conversation_get_name(conv),
-- purple_connection_get_display_name(gc),
-- purple_conv_chat_get_users(PURPLE_CONV_CHAT(conv)));
-- }
-- g_slist_free(yd->confs);
--
-- for (l = yd->cookies; l; l = l->next) {
-- g_free(l->data);
-- l->data=NULL;
-- }
-- g_slist_free(yd->cookies);
--
-- yd->chat_online = FALSE;
-- if (yd->in_chat)
-- yahoo_c_leave(gc, 1); /* 1 = YAHOO_CHAT_ID */
--
-- purple_timeout_remove(yd->yahoo_p2p_timer);
-- if(yd->yahoo_p2p_server_timeout_handle != 0) {
-- purple_timeout_remove(yd->yahoo_p2p_server_timeout_handle);
-- yd->yahoo_p2p_server_timeout_handle = 0;
-- }
--
-- /* close p2p server if it is waiting for a peer to connect */
-- if (yd->yahoo_p2p_server_watcher) {
-- purple_input_remove(yd->yahoo_p2p_server_watcher);
-- yd->yahoo_p2p_server_watcher = 0;
-- }
-- if (yd->yahoo_local_p2p_server_fd >= 0) {
-- close(yd->yahoo_local_p2p_server_fd);
-- yd->yahoo_local_p2p_server_fd = -1;
-- }
--
-- g_hash_table_destroy(yd->sms_carrier);
-- g_hash_table_destroy(yd->peers);
-- g_hash_table_destroy(yd->friends);
-- g_hash_table_destroy(yd->imvironments);
-- g_hash_table_destroy(yd->xfer_peer_idstring_map);
-- g_free(yd->chat_name);
--
-- g_free(yd->cookie_y);
-- g_free(yd->cookie_t);
-- g_free(yd->cookie_b);
--
-- if (yd->txhandler)
-- purple_input_remove(yd->txhandler);
--
-- purple_circ_buffer_destroy(yd->txbuf);
--
-- if (yd->fd >= 0)
-- close(yd->fd);
--
-- g_free(yd->rxqueue);
-- yd->rxlen = 0;
-- g_free(yd->picture_url);
--
-- if (yd->buddy_icon_connect_data)
-- purple_proxy_connect_cancel(yd->buddy_icon_connect_data);
-- if (yd->picture_upload_todo)
-- yahoo_buddy_icon_upload_data_free(yd->picture_upload_todo);
-- if (yd->ycht)
-- ycht_connection_close(yd->ycht);
-- if (yd->listen_data != NULL)
-- purple_network_listen_cancel(yd->listen_data);
--
-- g_free(yd->pending_chat_room);
-- g_free(yd->pending_chat_id);
-- g_free(yd->pending_chat_topic);
-- g_free(yd->pending_chat_goto);
-- g_strfreev(yd->profiles);
--
-- yahoo_personal_details_reset(&yd->ypd, TRUE);
--
-- g_free(yd->current_list15_grp);
--
-- g_free(yd);
-- gc->proto_data = NULL;
--}
--
--const char *yahoo_list_icon(PurpleAccount *a, PurpleBuddy *b)
--{
-- return "yahoo";
--}
--
--const char *yahoo_list_emblem(PurpleBuddy *b)
--{
-- PurpleAccount *account;
-- PurpleConnection *gc;
-- YahooFriend *f;
-- PurplePresence *presence;
--
-- if (!b || !(account = purple_buddy_get_account(b)) ||
-- !(gc = purple_account_get_connection(account)) ||
-- !gc->proto_data)
-- return NULL;
--
-- f = yahoo_friend_find(gc, purple_buddy_get_name(b));
-- if (!f) {
-- return "not-authorized";
-- }
--
-- presence = purple_buddy_get_presence(b);
--
-- if (purple_presence_is_online(presence)) {
-- if (yahoo_friend_get_game(f))
-- return "game";
--
-- if (f->fed)
-- return "external";
-- }
-- return NULL;
--}
--
--static const char *yahoo_get_status_string(enum yahoo_status a)
--{
-- switch (a) {
-- case YAHOO_STATUS_BRB:
-- return _("Be Right Back");
-- case YAHOO_STATUS_BUSY:
-- return _("Busy");
-- case YAHOO_STATUS_NOTATHOME:
-- return _("Not at Home");
-- case YAHOO_STATUS_NOTATDESK:
-- return _("Not at Desk");
-- case YAHOO_STATUS_NOTINOFFICE:
-- return _("Not in Office");
-- case YAHOO_STATUS_ONPHONE:
-- return _("On the Phone");
-- case YAHOO_STATUS_ONVACATION:
-- return _("On Vacation");
-- case YAHOO_STATUS_OUTTOLUNCH:
-- return _("Out to Lunch");
-- case YAHOO_STATUS_STEPPEDOUT:
-- return _("Stepped Out");
-- case YAHOO_STATUS_INVISIBLE:
-- return _("Invisible");
-- case YAHOO_STATUS_IDLE:
-- return _("Idle");
-- case YAHOO_STATUS_OFFLINE:
-- return _("Offline");
-- default:
-- return _("Available");
-- }
--}
--
--static void yahoo_initiate_conference(PurpleBlistNode *node, gpointer data) {
--
-- PurpleBuddy *buddy;
-- PurpleConnection *gc;
--
-- GHashTable *components;
-- YahooData *yd;
-- int id;
--
-- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
--
-- buddy = (PurpleBuddy *) node;
-- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-- yd = gc->proto_data;
-- id = yd->conf_id;
--
-- components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-- g_hash_table_replace(components, g_strdup("room"),
-- g_strdup_printf("%s-%d", purple_connection_get_display_name(gc), id));
-- g_hash_table_replace(components, g_strdup("topic"), g_strdup("Join my conference..."));
-- g_hash_table_replace(components, g_strdup("type"), g_strdup("Conference"));
-- yahoo_c_join(gc, components);
-- g_hash_table_destroy(components);
--
-- yahoo_c_invite(gc, id, "Join my conference...", purple_buddy_get_name(buddy));
--}
--
--static void yahoo_presence_settings(PurpleBlistNode *node, gpointer data) {
-- PurpleBuddy *buddy;
-- PurpleConnection *gc;
-- int presence_val = GPOINTER_TO_INT(data);
--
-- buddy = (PurpleBuddy *) node;
-- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
--
-- yahoo_friend_update_presence(gc, purple_buddy_get_name(buddy), presence_val);
--}
--
--static void yahoo_game(PurpleBlistNode *node, gpointer data) {
--
-- PurpleBuddy *buddy;
-- PurpleConnection *gc;
--
-- const char *game;
-- char *game2;
-- char *t;
-- char url[256];
-- YahooFriend *f;
--
-- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
--
-- buddy = (PurpleBuddy *) node;
-- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
--
-- f = yahoo_friend_find(gc, purple_buddy_get_name(buddy));
-- if (!f)
-- return;
--
-- game = yahoo_friend_get_game(f);
-- if (!game)
-- return;
--
-- t = game2 = g_strdup(strstr(game, "ante?room="));
-- while (*t && *t != '\t')
-- t++;
-- *t = 0;
-- g_snprintf(url, sizeof url, "http://games.yahoo.com/games/%s", game2);
-- purple_notify_uri(gc, url);
-- g_free(game2);
--}
--
--char *yahoo_status_text(PurpleBuddy *b)
--{
-- YahooFriend *f = NULL;
-- const char *msg;
-- char *msg2;
-- PurpleAccount *account;
-- PurpleConnection *gc;
--
-- account = purple_buddy_get_account(b);
-- gc = purple_account_get_connection(account);
-- if (!gc || !purple_connection_get_protocol_data(gc))
-- return NULL;
--
-- f = yahoo_friend_find(gc, purple_buddy_get_name(b));
-- if (!f)
-- return g_strdup(_("Not on server list"));
--
-- switch (f->status) {
-- case YAHOO_STATUS_AVAILABLE:
-- return NULL;
-- case YAHOO_STATUS_IDLE:
-- if (f->idle == -1)
-- return g_strdup(yahoo_get_status_string(f->status));
-- return NULL;
-- case YAHOO_STATUS_CUSTOM:
-- if (!(msg = yahoo_friend_get_status_message(f)))
-- return NULL;
-- msg2 = g_markup_escape_text(msg, strlen(msg));
-- purple_util_chrreplace(msg2, '\n', ' ');
-- return msg2;
--
-- default:
-- return g_strdup(yahoo_get_status_string(f->status));
-- }
--}
--
--void yahoo_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
--{
-- YahooFriend *f;
-- char *status = NULL;
-- const char *presence = NULL;
-- PurpleAccount *account;
--
-- account = purple_buddy_get_account(b);
-- f = yahoo_friend_find(purple_account_get_connection(account), purple_buddy_get_name(b));
-- if (!f)
-- status = g_strdup_printf("\n%s", _("Not on server list"));
-- else {
-- switch (f->status) {
-- case YAHOO_STATUS_CUSTOM:
-- if (!yahoo_friend_get_status_message(f))
-- return;
-- status = g_strdup(yahoo_friend_get_status_message(f));
-- break;
-- case YAHOO_STATUS_OFFLINE:
-- break;
-- default:
-- status = g_strdup(yahoo_get_status_string(f->status));
-- break;
-- }
--
-- switch (f->presence) {
-- case YAHOO_PRESENCE_ONLINE:
-- presence = _("Appear Online");
-- break;
-- case YAHOO_PRESENCE_PERM_OFFLINE:
-- presence = _("Appear Permanently Offline");
-- break;
-- case YAHOO_PRESENCE_DEFAULT:
-- break;
-- default:
-- purple_debug_error("yahoo", "Unknown presence in yahoo_tooltip_text\n");
-- break;
-- }
-- }
--
-- if (status != NULL) {
-- purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), status);
-- g_free(status);
-- }
--
-- if (presence != NULL)
-- purple_notify_user_info_add_pair_plaintext(user_info, _("Presence"), presence);
--
-- if (f && full) {
-- YahooPersonalDetails *ypd = &f->ypd;
-- int i;
-- struct {
-- char *id;
-- char *text;
-- char *value;
-- } yfields[] = {
-- {"hp", N_("Home Phone Number"), ypd->phone.home},
-- {"wp", N_("Work Phone Number"), ypd->phone.work},
-- {"mo", N_("Mobile Phone Number"), ypd->phone.mobile},
-- {NULL, NULL, NULL}
-- };
-- for (i = 0; yfields[i].id; i++) {
-- if (!yfields[i].value || !*yfields[i].value)
-- continue;
-- purple_notify_user_info_add_pair(user_info, _(yfields[i].text), yfields[i].value);
-- }
-- }
--}
--
--static void yahoo_addbuddyfrommenu_cb(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(purple_buddy_get_account(buddy));
--
-- yahoo_add_buddy(gc, buddy, NULL);
--}
--
--
--static void yahoo_chat_goto_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(purple_buddy_get_account(buddy));
--
-- yahoo_chat_goto(gc, purple_buddy_get_name(buddy));
--}
--
--static GList *build_presence_submenu(YahooFriend *f, PurpleConnection *gc) {
-- GList *m = NULL;
-- PurpleMenuAction *act;
-- YahooData *yd = (YahooData *) gc->proto_data;
--
-- if (yd->current_status == YAHOO_STATUS_INVISIBLE) {
-- if (f->presence != YAHOO_PRESENCE_ONLINE) {
-- act = purple_menu_action_new(_("Appear Online"),
-- PURPLE_CALLBACK(yahoo_presence_settings),
-- GINT_TO_POINTER(YAHOO_PRESENCE_ONLINE),
-- NULL);
-- m = g_list_append(m, act);
-- } else if (f->presence != YAHOO_PRESENCE_DEFAULT) {
-- act = purple_menu_action_new(_("Appear Offline"),
-- PURPLE_CALLBACK(yahoo_presence_settings),
-- GINT_TO_POINTER(YAHOO_PRESENCE_DEFAULT),
-- NULL);
-- m = g_list_append(m, act);
-- }
-- }
--
-- if (f->presence == YAHOO_PRESENCE_PERM_OFFLINE) {
-- act = purple_menu_action_new(_("Don't Appear Permanently Offline"),
-- PURPLE_CALLBACK(yahoo_presence_settings),
-- GINT_TO_POINTER(YAHOO_PRESENCE_DEFAULT),
-- NULL);
-- m = g_list_append(m, act);
-- } else {
-- act = purple_menu_action_new(_("Appear Permanently Offline"),
-- PURPLE_CALLBACK(yahoo_presence_settings),
-- GINT_TO_POINTER(YAHOO_PRESENCE_PERM_OFFLINE),
-- NULL);
-- m = g_list_append(m, act);
-- }
--
-- return m;
--}
--
--static void yahoo_doodle_blist_node(PurpleBlistNode *node, gpointer data)
--{
-- PurpleBuddy *b = (PurpleBuddy *)node;
-- PurpleAccount *account = purple_buddy_get_account(b);
-- PurpleConnection *gc = purple_account_get_connection(account);
--
-- yahoo_doodle_initiate(gc, purple_buddy_get_name(b));
--}
--
--static void
--yahoo_userinfo_blist_node(PurpleBlistNode *node, gpointer data)
--{
-- PurpleBuddy *b = (PurpleBuddy *)node;
-- PurpleAccount *account = purple_buddy_get_account(b);
-- PurpleConnection *gc = purple_account_get_connection(account);
--
-- yahoo_set_userinfo_for_buddy(gc, b);
--}
--
--static GList *yahoo_buddy_menu(PurpleBuddy *buddy)
--{
-- GList *m = NULL;
-- PurpleMenuAction *act;
--
-- PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-- YahooData *yd = gc->proto_data;
-- static char buf2[1024];
-- YahooFriend *f;
--
-- f = yahoo_friend_find(gc, purple_buddy_get_name(buddy));
--
-- if (!f && !yd->wm) {
-- act = purple_menu_action_new(_("Add Buddy"),
-- PURPLE_CALLBACK(yahoo_addbuddyfrommenu_cb),
-- NULL, NULL);
-- m = g_list_append(m, act);
--
-- return m;
--
-- }
--
-- if (f && f->status != YAHOO_STATUS_OFFLINE && f->fed == YAHOO_FEDERATION_NONE) {
-- if (!yd->wm) {
-- act = purple_menu_action_new(_("Join in Chat"),
-- PURPLE_CALLBACK(yahoo_chat_goto_menu),
-- NULL, NULL);
-- m = g_list_append(m, act);
-- }
--
-- act = purple_menu_action_new(_("Initiate Conference"),
-- PURPLE_CALLBACK(yahoo_initiate_conference),
-- NULL, NULL);
-- m = g_list_append(m, act);
--
-- if (yahoo_friend_get_game(f)) {
-- const char *game = yahoo_friend_get_game(f);
-- char *room;
-- char *t;
--
-- if ((room = strstr(game, "&follow="))) {/* skip ahead to the url */
-- while (*room && *room != '\t') /* skip to the tab */
-- room++;
-- t = room++; /* room as now at the name */
-- while (*t != '\n')
-- t++; /* replace the \n with a space */
-- *t = ' ';
-- g_snprintf(buf2, sizeof buf2, "%s", room);
--
-- act = purple_menu_action_new(buf2,
-- PURPLE_CALLBACK(yahoo_game),
-- NULL, NULL);
-- m = g_list_append(m, act);
-- }
-- }
-- }
--
-- if (f) {
-- act = purple_menu_action_new(_("Presence Settings"), NULL, NULL,
-- build_presence_submenu(f, gc));
-- m = g_list_append(m, act);
--
-- if (f->fed == YAHOO_FEDERATION_NONE) {
-- act = purple_menu_action_new(_("Start Doodling"),
-- PURPLE_CALLBACK(yahoo_doodle_blist_node),
-- NULL, NULL);
-- m = g_list_append(m, act);
-- }
--
-- act = purple_menu_action_new(_("Set User Info..."),
-- PURPLE_CALLBACK(yahoo_userinfo_blist_node),
-- NULL, NULL);
-- m = g_list_append(m, act);
-- }
--
-- return m;
--}
--
--GList *yahoo_blist_node_menu(PurpleBlistNode *node)
--{
-- if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
-- return yahoo_buddy_menu((PurpleBuddy *) node);
-- } else {
-- return NULL;
-- }
--}
--
--static void yahoo_act_id(PurpleConnection *gc, PurpleRequestFields *fields)
--{
-- YahooData *yd = gc->proto_data;
-- const char *name = yd->profiles[purple_request_fields_get_choice(fields, "id")];
--
-- struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_IDACT, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash_str(pkt, 3, name);
-- yahoo_packet_send_and_free(pkt, yd);
--
-- purple_connection_set_display_name(gc, name);
--}
--
--static void
--yahoo_get_inbox_token_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
-- const gchar *token, size_t len, const gchar *error_message)
--{
-- PurpleConnection *gc = user_data;
-- gboolean set_cookie = FALSE;
-- gchar *url;
-- YahooData *yd = gc->proto_data;
--
-- g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
--
-- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
--
-- if (error_message != NULL)
-- purple_debug_error("yahoo", "Requesting mail login token failed: %s\n", error_message);
-- else if (len > 0 && token && *token) {
-- /* Should we not be hardcoding the rd url? */
-- url = g_strdup_printf(
-- "http://login.yahoo.com/config/reset_cookies_token?"
-- ".token=%s"
-- "&.done=http://us.rd.yahoo.com/messenger/client/%%3fhttp://mail.yahoo.com/",
-- token);
-- set_cookie = TRUE;
-- }
--
-- if (!set_cookie) {
-- purple_debug_error("yahoo", "No mail login token; forwarding to login screen.\n");
-- url = g_strdup(yd->jp ? YAHOOJP_MAIL_URL : YAHOO_MAIL_URL);
-- }
--
-- /* Open the mailbox with the parsed url data */
-- purple_notify_uri(gc, url);
--
-- g_free(url);
--}
--
--
--static void yahoo_show_inbox(PurplePluginAction *action)
--{
-- /* Setup a cookie that can be used by the browser */
-- /* XXX I have no idea how this will work with Yahoo! Japan. */
--
-- PurpleConnection *gc = action->context;
-- YahooData *yd = gc->proto_data;
--
-- PurpleUtilFetchUrlData *url_data;
-- const char* base_url = "http://login.yahoo.com";
-- /* use whole URL if using HTTP Proxy */
-- gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
-- gchar *request = g_strdup_printf(
-- "POST %s/config/cookie_token HTTP/1.0\r\n"
-- "Cookie: T=%s; path=/; domain=.yahoo.com; Y=%s;\r\n"
-- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-- "Host: login.yahoo.com\r\n"
-- "Content-Length: 0\r\n\r\n",
-- use_whole_url ? base_url : "",
-- yd->cookie_t, yd->cookie_y);
--
-- url_data = purple_util_fetch_url_request_len_with_account(
-- purple_connection_get_account(gc), base_url, use_whole_url,
-- YAHOO_CLIENT_USERAGENT, TRUE, request, FALSE, -1,
-- yahoo_get_inbox_token_cb, gc);
--
-- g_free(request);
--
-- if (url_data != NULL)
-- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-- else {
-- const char *yahoo_mail_url = (yd->jp ? YAHOOJP_MAIL_URL : YAHOO_MAIL_URL);
-- purple_debug_error("yahoo",
-- "Unable to request mail login token; forwarding to login screen.");
-- purple_notify_uri(gc, yahoo_mail_url);
-- }
--}
--
--static void
--yahoo_set_userinfo_fn(PurplePluginAction *action)
--{
-- yahoo_set_userinfo(action->context);
--}
--
--static void yahoo_show_act_id(PurplePluginAction *action)
--{
-- PurpleRequestFields *fields;
-- PurpleRequestFieldGroup *group;
-- PurpleRequestField *field;
-- PurpleConnection *gc = (PurpleConnection *) action->context;
-- YahooData *yd = purple_connection_get_protocol_data(gc);
-- const char *name = purple_connection_get_display_name(gc);
-- int iter;
--
-- fields = purple_request_fields_new();
-- group = purple_request_field_group_new(NULL);
-- purple_request_fields_add_group(fields, group);
-- field = purple_request_field_choice_new("id", "Activate which ID?", 0);
-- purple_request_field_group_add_field(group, field);
--
-- for (iter = 0; yd->profiles[iter]; iter++) {
-- purple_request_field_choice_add(field, yd->profiles[iter]);
-- if (purple_strequal(yd->profiles[iter], name))
-- purple_request_field_choice_set_default_value(field, iter);
-- }
--
-- purple_request_fields(gc, NULL, _("Select the ID you want to activate"), NULL,
-- fields,
-- _("OK"), G_CALLBACK(yahoo_act_id),
-- _("Cancel"), NULL,
-- purple_connection_get_account(gc), NULL, NULL,
-- gc);
--}
--
--static void yahoo_show_chat_goto(PurplePluginAction *action)
--{
-- PurpleConnection *gc = (PurpleConnection *) action->context;
-- purple_request_input(gc, NULL, _("Join whom in chat?"), NULL,
-- "", FALSE, FALSE, NULL,
-- _("OK"), G_CALLBACK(yahoo_chat_goto),
-- _("Cancel"), NULL,
-- purple_connection_get_account(gc), NULL, NULL,
-- gc);
--}
--
--GList *yahoo_actions(PurplePlugin *plugin, gpointer context) {
-- GList *m = NULL;
-- PurplePluginAction *act;
--
-- act = purple_plugin_action_new(_("Set User Info..."),
-- yahoo_set_userinfo_fn);
-- m = g_list_append(m, act);
--
-- act = purple_plugin_action_new(_("Activate ID..."),
-- yahoo_show_act_id);
-- m = g_list_append(m, act);
--
-- act = purple_plugin_action_new(_("Join User in Chat..."),
-- yahoo_show_chat_goto);
-- m = g_list_append(m, act);
--
-- m = g_list_append(m, NULL);
-- act = purple_plugin_action_new(_("Open Inbox"),
-- yahoo_show_inbox);
-- m = g_list_append(m, act);
--
-- return m;
--}
--
--struct yahoo_sms_carrier_cb_data {
-- PurpleConnection *gc;
-- char *who;
-- char *what;
--};
--
--static void yahoo_get_sms_carrier_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
-- const gchar *webdata, size_t len, const gchar *error_message)
--{
-- struct yahoo_sms_carrier_cb_data *sms_cb_data = user_data;
-- PurpleConnection *gc = sms_cb_data->gc;
-- YahooData *yd = gc->proto_data;
-- char *status = NULL;
-- char *carrier = NULL;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms_cb_data->who, account);
--
-- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
--
-- if (error_message != NULL) {
-- purple_conversation_write(conv, NULL, _("Can't send SMS. Unable to obtain mobile carrier."), PURPLE_MESSAGE_SYSTEM, time(NULL));
--
-- g_free(sms_cb_data->who);
-- g_free(sms_cb_data->what);
-- g_free(sms_cb_data);
-- return ;
-- }
-- else if (len > 0 && webdata && *webdata) {
-- xmlnode *validate_data_root = xmlnode_from_str(webdata, -1);
-- xmlnode *validate_data_child = xmlnode_get_child(validate_data_root, "mobile_no");
-- const char *mobile_no = xmlnode_get_attrib(validate_data_child, "msisdn");
--
-- validate_data_root = xmlnode_copy(validate_data_child);
-- validate_data_child = xmlnode_get_child(validate_data_root, "status");
-- status = xmlnode_get_data(validate_data_child);
--
-- validate_data_child = xmlnode_get_child(validate_data_root, "carrier");
-- carrier = xmlnode_get_data(validate_data_child);
--
-- purple_debug_info("yahoo", "SMS validate data: %s\n", webdata);
--
-- if (status && g_str_equal(status, "Valid")) {
-- g_hash_table_insert(yd->sms_carrier,
-- g_strdup_printf("+%s", mobile_no), g_strdup(carrier));
-- yahoo_send_im(sms_cb_data->gc, sms_cb_data->who,
-- sms_cb_data->what, PURPLE_MESSAGE_SEND);
-- } else {
-- g_hash_table_insert(yd->sms_carrier,
-- g_strdup_printf("+%s", mobile_no), g_strdup("Unknown"));
-- purple_conversation_write(conv, NULL,
-- _("Can't send SMS. Unknown mobile carrier."),
-- PURPLE_MESSAGE_SYSTEM, time(NULL));
-- }
--
-- xmlnode_free(validate_data_child);
-- xmlnode_free(validate_data_root);
-- g_free(sms_cb_data->who);
-- g_free(sms_cb_data->what);
-- g_free(sms_cb_data);
-- g_free(status);
-- g_free(carrier);
-- }
--}
--
--static void yahoo_get_sms_carrier(PurpleConnection *gc, gpointer data)
--{
-- YahooData *yd = gc->proto_data;
-- PurpleUtilFetchUrlData *url_data;
-- struct yahoo_sms_carrier_cb_data *sms_cb_data;
-- char *validate_request_str = NULL;
-- char *request = NULL;
-- gboolean use_whole_url = FALSE;
-- xmlnode *validate_request_root = NULL;
-- xmlnode *validate_request_child = NULL;
--
-- if(!(sms_cb_data = data))
-- return;
--
-- validate_request_root = xmlnode_new("validate");
-- xmlnode_set_attrib(validate_request_root, "intl", "us");
-- xmlnode_set_attrib(validate_request_root, "version", YAHOO_CLIENT_VERSION);
-- xmlnode_set_attrib(validate_request_root, "qos", "0");
--
-- validate_request_child = xmlnode_new_child(validate_request_root, "mobile_no");
-- xmlnode_set_attrib(validate_request_child, "msisdn", sms_cb_data->who + 1);
--
-- validate_request_str = xmlnode_to_str(validate_request_root, NULL);
--
-- xmlnode_free(validate_request_child);
-- xmlnode_free(validate_request_root);
--
-- request = g_strdup_printf(
-- "POST /mobileno?intl=us&version=%s HTTP/1.1\r\n"
-- "Cookie: T=%s; path=/; domain=.yahoo.com; Y=%s; path=/; domain=.yahoo.com;\r\n"
-- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-- "Host: validate.msg.yahoo.com\r\n"
-- "Content-Length: %" G_GSIZE_FORMAT "\r\n"
-- "Cache-Control: no-cache\r\n\r\n%s",
-- YAHOO_CLIENT_VERSION, yd->cookie_t, yd->cookie_y, strlen(validate_request_str), validate_request_str);
--
-- /* use whole URL if using HTTP Proxy */
-- if ((gc->account->proxy_info) && (gc->account->proxy_info->type == PURPLE_PROXY_HTTP))
-- use_whole_url = TRUE;
--
-- url_data = purple_util_fetch_url_request_len_with_account(
-- purple_connection_get_account(gc), YAHOO_SMS_CARRIER_URL, use_whole_url,
-- YAHOO_CLIENT_USERAGENT, TRUE, request, FALSE, -1,
-- yahoo_get_sms_carrier_cb, data);
--
-- g_free(request);
-- g_free(validate_request_str);
--
-- if (url_data)
-- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-- else {
-- PurpleAccount *account = purple_connection_get_account(gc);
-- PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms_cb_data->who, account);
-- purple_conversation_write(conv, NULL, _("Can't send SMS. Unable to obtain mobile carrier."), PURPLE_MESSAGE_SYSTEM, time(NULL));
-- g_free(sms_cb_data->who);
-- g_free(sms_cb_data->what);
-- g_free(sms_cb_data);
-- }
--}
--
--int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags)
--{
-- YahooData *yd = gc->proto_data;
-- struct yahoo_packet *pkt = NULL;
-- char *msg = yahoo_html_to_codes(what);
-- char *msg2;
-- gboolean utf8 = TRUE;
-- PurpleWhiteboard *wb;
-- int ret = 1;
-- const char *fed_who;
-- gsize lenb = 0;
-- glong lenc = 0;
-- struct yahoo_p2p_data *p2p_data;
-- YahooFederation fed = YAHOO_FEDERATION_NONE;
-- msg2 = yahoo_string_encode(gc, msg, &utf8);
--
-- if(msg2) {
-- lenb = strlen(msg2);
-- lenc = g_utf8_strlen(msg2, -1);
--
-- if(lenb > YAHOO_MAX_MESSAGE_LENGTH_BYTES || lenc > YAHOO_MAX_MESSAGE_LENGTH_CHARS) {
-- purple_debug_info("yahoo", "Message too big. Length is %" G_GSIZE_FORMAT
-- " bytes, %ld characters. Max is %d bytes, %d chars."
-- " Message is '%s'.\n", lenb, lenc, YAHOO_MAX_MESSAGE_LENGTH_BYTES,
-- YAHOO_MAX_MESSAGE_LENGTH_CHARS, msg2);
-- g_free(msg);
-- g_free(msg2);
-- return -E2BIG;
-- }
-- }
--
-- fed = yahoo_get_federation_from_name(who);
--
-- if (who[0] == '+') {
-- /* we have an sms to be sent */
-- gchar *carrier = NULL;
-- const char *alias = NULL;
-- PurpleAccount *account = purple_connection_get_account(gc);
-- PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, account);
--
-- carrier = g_hash_table_lookup(yd->sms_carrier, who);
-- if (!carrier) {
-- struct yahoo_sms_carrier_cb_data *sms_cb_data;
-- sms_cb_data = g_malloc(sizeof(struct yahoo_sms_carrier_cb_data));
-- sms_cb_data->gc = gc;
-- sms_cb_data->who = g_strdup(who);
-- sms_cb_data->what = g_strdup(what);
--
-- purple_conversation_write(conv, NULL, _("Getting mobile carrier to send the SMS."), PURPLE_MESSAGE_SYSTEM, time(NULL));
--
-- yahoo_get_sms_carrier(gc, sms_cb_data);
--
-- g_free(msg);
-- g_free(msg2);
-- return ret;
-- }
-- else if( strcmp(carrier,"Unknown") == 0 ) {
-- purple_conversation_write(conv, NULL, _("Can't send SMS. Unknown mobile carrier."), PURPLE_MESSAGE_SYSTEM, time(NULL));
--
-- g_free(msg);
-- g_free(msg2);
-- return -1;
-- }
--
-- alias = purple_account_get_alias(account);
-- pkt = yahoo_packet_new(YAHOO_SERVICE_SMS_MSG, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash(pkt, "sssss",
-- 1, purple_connection_get_display_name(gc),
-- 69, alias,
-- 5, who + 1,
-- 68, carrier,
-- 14, msg2);
-- yahoo_packet_send_and_free(pkt, yd);
--
-- g_free(msg);
-- g_free(msg2);
--
-- return ret;
-- }
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, yd->session_id);
-- fed_who = who;
-- switch (fed) {
-- case YAHOO_FEDERATION_MSN:
-- case YAHOO_FEDERATION_OCS:
-- case YAHOO_FEDERATION_IBM:
-- case YAHOO_FEDERATION_PBX:
-- fed_who += 4;
-- break;
-- case YAHOO_FEDERATION_NONE:
-- default:
-- break;
-- }
-- yahoo_packet_hash(pkt, "ss", 1, purple_connection_get_display_name(gc), 5, fed_who);
-- if (fed)
-- yahoo_packet_hash_int(pkt, 241, fed);
--
-- if (utf8)
-- yahoo_packet_hash_str(pkt, 97, "1");
-- yahoo_packet_hash_str(pkt, 14, msg2);
--
-- /*
-- * IMVironment.
-- *
-- * If this message is to a user who is also Doodling with the local user,
-- * format the chat packet with the correct IMV information (thanks Yahoo!)
-- *
-- * Otherwise attempt to use the same IMVironment as the remote user,
-- * just so that we don't inadvertantly reset their IMVironment back
-- * to nothing.
-- *
-- * If they have not set an IMVironment, then use the default.
-- */
-- wb = purple_whiteboard_get_session(gc->account, who);
-- if (wb)
-- yahoo_packet_hash_str(pkt, 63, DOODLE_IMV_KEY);
-- else
-- {
-- const char *imv;
-- imv = g_hash_table_lookup(yd->imvironments, who);
-- if (imv != NULL)
-- yahoo_packet_hash_str(pkt, 63, imv);
-- else
-- yahoo_packet_hash_str(pkt, 63, ";0");
-- }
--
-- yahoo_packet_hash_str(pkt, 64, "0"); /* no idea */
-- yahoo_packet_hash_str(pkt, 1002, "1"); /* no idea, Yahoo 6 or later only it seems */
-- if (!yd->picture_url)
-- yahoo_packet_hash_str(pkt, 206, "0"); /* 0 = no picture, 2 = picture, maybe 1 = avatar? */
-- else
-- yahoo_packet_hash_str(pkt, 206, "2");
--
-- /* We may need to not send any packets over 2000 bytes, but I'm not sure yet. */
-- if ((YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt)) <= 2000) {
-- /* if p2p link exists, send through it. To-do: key 15, time value to be sent in case of p2p */
-- if( (p2p_data = g_hash_table_lookup(yd->peers, who)) && !fed) {
-- yahoo_packet_hash_int(pkt, 11, p2p_data->session_id);
-- yahoo_p2p_write_pkt(p2p_data->source, pkt);
-- }
-- else {
-- yahoo_packet_send(pkt, yd);
-- if(!fed)
-- yahoo_send_p2p_pkt(gc, who, 0); /* send p2p packet, with val_13=0 */
-- }
-- }
-- else
-- ret = -E2BIG;
--
-- yahoo_packet_free(pkt);
--
-- g_free(msg);
-- g_free(msg2);
--
-- return ret;
--}
--
--unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state)
--{
-- YahooData *yd = gc->proto_data;
-- struct yahoo_p2p_data *p2p_data;
-- YahooFederation fed = YAHOO_FEDERATION_NONE;
-- struct yahoo_packet *pkt = NULL;
--
-- fed = yahoo_get_federation_from_name(who);
--
-- /* Don't do anything if sms is being typed */
-- if( strncmp(who, "+", 1) == 0 )
-- return 0;
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YAHOO_STATUS_TYPING, yd->session_id);
--
-- /* check to see if p2p link exists, send through it */
-- if( (p2p_data = g_hash_table_lookup(yd->peers, who)) && !fed) {
-- yahoo_packet_hash(pkt, "sssssis", 49, "TYPING", 1, purple_connection_get_display_name(gc),
-- 14, " ", 13, state == PURPLE_TYPING ? "1" : "0",
-- 5, who, 11, p2p_data->session_id, 1002, "1"); /* To-do: key 15 to be sent in case of p2p */
-- yahoo_p2p_write_pkt(p2p_data->source, pkt);
-- yahoo_packet_free(pkt);
-- }
-- else { /* send through yahoo server */
--
-- const char *fed_who = who;
-- switch (fed) {
-- case YAHOO_FEDERATION_MSN:
-- case YAHOO_FEDERATION_OCS:
-- case YAHOO_FEDERATION_IBM:
-- case YAHOO_FEDERATION_PBX:
-- fed_who += 4;
-- break;
-- case YAHOO_FEDERATION_NONE:
-- default:
-- break;
-- }
--
-- yahoo_packet_hash(pkt, "ssssss", 49, "TYPING", 1, purple_connection_get_display_name(gc),
-- 14, " ", 13, state == PURPLE_TYPING ? "1" : "0",
-- 5, fed_who, 1002, "1");
-- if (fed)
-- yahoo_packet_hash_int(pkt, 241, fed);
-- yahoo_packet_send_and_free(pkt, yd);
-- }
--
-- return 0;
--}
--
--static void yahoo_session_presence_remove(gpointer key, gpointer value, gpointer data)
--{
-- YahooFriend *f = value;
-- if (f && f->presence == YAHOO_PRESENCE_ONLINE)
-- f->presence = YAHOO_PRESENCE_DEFAULT;
--}
--
--void yahoo_set_status(PurpleAccount *account, PurpleStatus *status)
--{
-- PurpleConnection *gc;
-- PurplePresence *presence;
-- YahooData *yd;
-- struct yahoo_packet *pkt;
-- int old_status;
-- const char *msg = NULL;
-- char *tmp = NULL;
-- char *conv_msg = NULL;
-- gboolean utf8 = TRUE;
--
-- if (!purple_status_is_active(status))
-- return;
--
-- gc = purple_account_get_connection(account);
-- presence = purple_status_get_presence(status);
-- yd = (YahooData *)gc->proto_data;
-- old_status = yd->current_status;
--
-- yd->current_status = get_yahoo_status_from_purple_status(status);
--
-- if (yd->current_status == YAHOO_STATUS_CUSTOM)
-- {
-- msg = purple_status_get_attr_string(status, "message");
--
-- if (purple_status_is_available(status)) {
-- tmp = yahoo_string_encode(gc, msg, &utf8);
-- conv_msg = purple_markup_strip_html(tmp);
-- g_free(tmp);
-- } else {
-- if ((msg == NULL) || (*msg == '\0'))
-- msg = _("Away");
-- tmp = yahoo_string_encode(gc, msg, &utf8);
-- conv_msg = purple_markup_strip_html(tmp);
-- g_free(tmp);
-- }
-- }
--
-- if (yd->current_status == YAHOO_STATUS_INVISIBLE) {
-- pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash_str(pkt, 13, "2");
-- yahoo_packet_send_and_free(pkt, yd);
--
-- return;
-- }
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash_int(pkt, 10, yd->current_status);
--
-- if (yd->current_status == YAHOO_STATUS_CUSTOM) {
-- yahoo_packet_hash_str(pkt, 97, utf8 ? "1" : 0);
-- yahoo_packet_hash_str(pkt, 19, conv_msg);
-- } else {
-- yahoo_packet_hash_str(pkt, 19, "");
-- }
--
-- g_free(conv_msg);
--
-- if (purple_presence_is_idle(presence))
-- yahoo_packet_hash_str(pkt, 47, "2");
-- else {
-- if (!purple_status_is_available(status))
-- yahoo_packet_hash_str(pkt, 47, "1");
-- else
-- yahoo_packet_hash_str(pkt, 47, "0");
-- }
--
-- yahoo_packet_send_and_free(pkt, yd);
--
-- if (old_status == YAHOO_STATUS_INVISIBLE) {
-- pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash_str(pkt, 13, "1");
-- yahoo_packet_send_and_free(pkt, yd);
--
-- /* Any per-session presence settings are removed */
-- g_hash_table_foreach(yd->friends, yahoo_session_presence_remove, NULL);
--
-- }
--}
--
--void yahoo_set_idle(PurpleConnection *gc, int idle)
--{
-- YahooData *yd = gc->proto_data;
-- struct yahoo_packet *pkt = NULL;
-- char *msg = NULL, *msg2 = NULL;
-- PurpleStatus *status = NULL;
-- gboolean invisible = FALSE;
--
-- if (idle && yd->current_status != YAHOO_STATUS_CUSTOM)
-- yd->current_status = YAHOO_STATUS_IDLE;
-- else if (!idle && yd->current_status == YAHOO_STATUS_IDLE) {
-- status = purple_presence_get_active_status(purple_account_get_presence(purple_connection_get_account(gc)));
-- yd->current_status = get_yahoo_status_from_purple_status(status);
-- }
--
-- invisible = (yd->current_status == YAHOO_STATUS_INVISIBLE);
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE, YAHOO_STATUS_AVAILABLE, yd->session_id);
--
-- if (!idle && invisible)
-- yahoo_packet_hash_int(pkt, 10, YAHOO_STATUS_AVAILABLE);
-- else
-- yahoo_packet_hash_int(pkt, 10, yd->current_status);
--
-- if (yd->current_status == YAHOO_STATUS_CUSTOM) {
-- const char *tmp;
-- if (status == NULL)
-- status = purple_presence_get_active_status(purple_account_get_presence(purple_connection_get_account(gc)));
-- tmp = purple_status_get_attr_string(status, "message");
-- if (tmp != NULL) {
-- gboolean utf8 = TRUE;
-- msg = yahoo_string_encode(gc, tmp, &utf8);
-- msg2 = purple_markup_strip_html(msg);
-- yahoo_packet_hash_str(pkt, 97, utf8 ? "1" : 0);
-- yahoo_packet_hash_str(pkt, 19, msg2);
-- } else {
-- /* get_yahoo_status_from_purple_status() returns YAHOO_STATUS_CUSTOM for
-- * the generic away state (YAHOO_STATUS_TYPE_AWAY) with no message */
-- yahoo_packet_hash_str(pkt, 19, _("Away"));
-- }
-- } else {
-- yahoo_packet_hash_str(pkt, 19, "");
-- }
--
-- if (idle)
-- yahoo_packet_hash_str(pkt, 47, "2");
-- else if (yd->current_status == YAHOO_STATUS_CUSTOM &&
-- !purple_status_is_available(status))
-- /* We are still unavailable in this case.
-- * Make sure Yahoo knows that */
-- yahoo_packet_hash_str(pkt, 47, "1");
--
-- yahoo_packet_send_and_free(pkt, yd);
--
-- g_free(msg);
-- g_free(msg2);
--}
--
--GList *yahoo_status_types(PurpleAccount *account)
--{
-- PurpleStatusType *type;
-- GList *types = NULL;
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, YAHOO_STATUS_TYPE_AVAILABLE,
-- NULL, TRUE, TRUE, FALSE,
-- "message", _("Message"),
-- purple_value_new(PURPLE_TYPE_STRING), NULL);
-- types = g_list_append(types, type);
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_AWAY,
-- NULL, TRUE, TRUE, FALSE,
-- "message", _("Message"),
-- purple_value_new(PURPLE_TYPE_STRING), NULL);
-- types = g_list_append(types, type);
--
-- type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_BRB, _("Be Right Back"), TRUE);
-- types = g_list_append(types, type);
--
-- type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE, YAHOO_STATUS_TYPE_BUSY,
-- _("Busy"), TRUE, TRUE, FALSE,
-- "message", _("Message"),
-- purple_value_new(PURPLE_TYPE_STRING), NULL);
-- types = g_list_append(types, type);
--
-- type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_NOTATHOME, _("Not at Home"), TRUE);
-- types = g_list_append(types, type);
--
-- type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_NOTATDESK, _("Not at Desk"), TRUE);
-- types = g_list_append(types, type);
--
-- type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_NOTINOFFICE, _("Not in Office"), TRUE);
-- types = g_list_append(types, type);
--
-- type = purple_status_type_new(PURPLE_STATUS_UNAVAILABLE, YAHOO_STATUS_TYPE_ONPHONE, _("On the Phone"), TRUE);
-- types = g_list_append(types, type);
--
-- type = purple_status_type_new(PURPLE_STATUS_EXTENDED_AWAY, YAHOO_STATUS_TYPE_ONVACATION, _("On Vacation"), TRUE);
-- types = g_list_append(types, type);
--
-- type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_OUTTOLUNCH, _("Out to Lunch"), TRUE);
-- types = g_list_append(types, type);
--
-- type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_STEPPEDOUT, _("Stepped Out"), TRUE);
-- types = g_list_append(types, type);
--
--
-- type = purple_status_type_new(PURPLE_STATUS_INVISIBLE, YAHOO_STATUS_TYPE_INVISIBLE, NULL, TRUE);
-- types = g_list_append(types, type);
--
-- type = purple_status_type_new(PURPLE_STATUS_OFFLINE, YAHOO_STATUS_TYPE_OFFLINE, NULL, TRUE);
-- types = g_list_append(types, type);
--
-- type = purple_status_type_new_full(PURPLE_STATUS_MOBILE, YAHOO_STATUS_TYPE_MOBILE, NULL, FALSE, FALSE, TRUE);
-- types = g_list_append(types, type);
--
-- return types;
--}
--
--void yahoo_keepalive(PurpleConnection *gc)
--{
-- struct yahoo_packet *pkt;
-- YahooData *yd = gc->proto_data;
-- time_t now = time(NULL);
--
-- /* We're only allowed to send a ping once an hour or the servers will boot us */
-- if ((now - yd->last_ping) >= PING_TIMEOUT) {
-- yd->last_ping = now;
--
-- /* The native client will only send PING or CHATPING */
-- if (yd->chat_online) {
-- if (yd->wm) {
-- ycht_chat_send_keepalive(yd->ycht);
-- } else {
-- pkt = yahoo_packet_new(YAHOO_SERVICE_CHATPING, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash_str(pkt, 109, purple_connection_get_display_name(gc));
-- yahoo_packet_send_and_free(pkt, yd);
-- }
-- } else {
-- pkt = yahoo_packet_new(YAHOO_SERVICE_PING, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_send_and_free(pkt, yd);
-- }
-- }
--
-- if ((now - yd->last_keepalive) >= KEEPALIVE_TIMEOUT) {
-- yd->last_keepalive = now;
-- pkt = yahoo_packet_new(YAHOO_SERVICE_KEEPALIVE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash_str(pkt, 0, purple_connection_get_display_name(gc));
-- yahoo_packet_send_and_free(pkt, yd);
-- }
--
--}
--
--void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g)
--{
-- YahooData *yd = (YahooData *)gc->proto_data;
-- struct yahoo_packet *pkt;
-- const char *group = NULL;
-- char *group2;
-- const char *bname;
-- const char *fed_bname;
-- YahooFederation fed = YAHOO_FEDERATION_NONE;
--
-- if (!yd->logged_in)
-- return;
--
-- fed_bname = bname = purple_buddy_get_name(buddy);
-- if (!purple_privacy_check(purple_connection_get_account(gc), bname))
-- return;
--
-- fed = yahoo_get_federation_from_name(bname);
-- if (fed != YAHOO_FEDERATION_NONE)
-- fed_bname += 4;
--
-- g = purple_buddy_get_group(buddy);
-- if (g)
-- group = purple_group_get_name(g);
-- else
-- group = "Buddies";
--
-- group2 = yahoo_string_encode(gc, group, NULL);
-- pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- if (fed) {
-- yahoo_packet_hash(pkt, "sssssssisss",
-- 14, "",
-- 65, group2,
-- 97, "1",
-- 1, purple_connection_get_display_name(gc),
-- 302, "319",
-- 300, "319",
-- 7, fed_bname,
-- 241, fed,
-- 334, "0",
-- 301, "319",
-- 303, "319"
-- );
-- }
-- else {
-- yahoo_packet_hash(pkt, "ssssssssss",
-- 14, "",
-- 65, group2,
-- 97, "1",
-- 1, purple_connection_get_display_name(gc),
-- 302, "319",
-- 300, "319",
-- 7, fed_bname,
-- 334, "0",
-- 301, "319",
-- 303, "319"
-- );
-- }
--
-- yahoo_packet_send_and_free(pkt, yd);
-- g_free(group2);
--}
--
--void yahoo_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
--{
-- YahooData *yd = (YahooData *)gc->proto_data;
-- struct yahoo_packet *pkt;
-- GSList *buddies, *l;
-- PurpleGroup *g;
-- gboolean remove = TRUE;
-- char *cg;
-- const char *bname, *gname;
-- YahooFriend *f = NULL;
-- YahooFederation fed = YAHOO_FEDERATION_NONE;
--
-- bname = purple_buddy_get_name(buddy);
-- f = yahoo_friend_find(gc, bname);
-- if (!f)
-- return;
-- fed = f->fed;
--
-- gname = purple_group_get_name(group);
-- buddies = purple_find_buddies(purple_connection_get_account(gc), bname);
-- for (l = buddies; l; l = l->next) {
-- g = purple_buddy_get_group(l->data);
-- if (purple_utf8_strcasecmp(gname, purple_group_get_name(g))) {
-- remove = FALSE;
-- break;
-- }
-- }
--
-- g_slist_free(buddies);
--
-- if (remove) {
-- g_hash_table_remove(yd->friends, bname);
-- f = NULL; /* f no longer valid - Just making it clear */
-- }
--
-- cg = yahoo_string_encode(gc, gname, NULL);
-- pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id);
--
-- switch (fed) {
-- case YAHOO_FEDERATION_MSN:
-- case YAHOO_FEDERATION_OCS:
-- case YAHOO_FEDERATION_IBM:
-- bname += 4;
-- break;
-- case YAHOO_FEDERATION_NONE:
-- default:
-- break;
-- }
--
-- yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc),
-- 7, bname, 65, cg);
-- if (fed)
-- yahoo_packet_hash_int(pkt, 241, fed);
-- yahoo_packet_send_and_free(pkt, yd);
-- g_free(cg);
--}
--
--void yahoo_add_deny(PurpleConnection *gc, const char *who) {
-- YahooData *yd = (YahooData *)gc->proto_data;
-- struct yahoo_packet *pkt;
-- YahooFederation fed = YAHOO_FEDERATION_NONE;
--
-- if (!yd->logged_in)
-- return;
--
-- if (!who || who[0] == '\0')
-- return;
--
-- fed = yahoo_get_federation_from_name(who);
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id);
--
-- if(fed)
-- yahoo_packet_hash(pkt, "ssis", 1, purple_connection_get_display_name(gc), 7, who+4, 241, fed, 13, "1");
-- else
-- yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), 7, who, 13, "1");
--
-- yahoo_packet_send_and_free(pkt, yd);
--}
--
--void yahoo_rem_deny(PurpleConnection *gc, const char *who) {
-- YahooData *yd = (YahooData *)gc->proto_data;
-- struct yahoo_packet *pkt;
-- YahooFederation fed = YAHOO_FEDERATION_NONE;
--
-- if (!yd->logged_in)
-- return;
--
-- if (!who || who[0] == '\0')
-- return;
-- fed = yahoo_get_federation_from_name(who);
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id);
--
-- if(fed)
-- yahoo_packet_hash(pkt, "ssis", 1, purple_connection_get_display_name(gc), 7, who+4, 241, fed, 13, "2");
-- else
-- yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), 7, who, 13, "2");
--
-- yahoo_packet_send_and_free(pkt, yd);
--}
--
--void yahoo_set_permit_deny(PurpleConnection *gc)
--{
-- PurpleAccount *account;
-- GSList *deny;
--
-- account = purple_connection_get_account(gc);
--
-- switch (account->perm_deny)
-- {
-- case PURPLE_PRIVACY_ALLOW_ALL:
-- for (deny = account->deny; deny; deny = deny->next)
-- yahoo_rem_deny(gc, deny->data);
-- break;
--
-- case PURPLE_PRIVACY_ALLOW_BUDDYLIST:
-- case PURPLE_PRIVACY_ALLOW_USERS:
-- case PURPLE_PRIVACY_DENY_USERS:
-- case PURPLE_PRIVACY_DENY_ALL:
-- for (deny = account->deny; deny; deny = deny->next)
-- yahoo_add_deny(gc, deny->data);
-- break;
-- }
--}
--
--void yahoo_change_buddys_group(PurpleConnection *gc, const char *who,
-- const char *old_group, const char *new_group)
--{
-- YahooData *yd = gc->proto_data;
-- struct yahoo_packet *pkt;
-- char *gpn, *gpo;
-- YahooFriend *f = yahoo_friend_find(gc, who);
-- const char *temp = NULL;
--
-- /* Step 0: If they aren't on the server list anyway,
-- * don't bother letting the server know.
-- */
-- if (!f)
-- return;
--
-- if(f->fed) {
-- temp = who+4;
-- } else
-- temp = who;
--
-- /* If old and new are the same, we would probably
-- * end up deleting the buddy, which would be bad.
-- * This might happen because of the charset conversation.
-- */
-- gpn = yahoo_string_encode(gc, new_group, NULL);
-- gpo = yahoo_string_encode(gc, old_group, NULL);
-- if (!strcmp(gpn, gpo)) {
-- g_free(gpn);
-- g_free(gpo);
-- return;
-- }
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_CHGRP_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- if(f->fed)
-- yahoo_packet_hash(pkt, "ssssissss", 1, purple_connection_get_display_name(gc),
-- 302, "240", 300, "240", 7, temp, 241, f->fed, 224, gpo, 264, gpn, 301,
-- "240", 303, "240");
-- else
-- yahoo_packet_hash(pkt, "ssssssss", 1, purple_connection_get_display_name(gc),
-- 302, "240", 300, "240", 7, temp, 224, gpo, 264, gpn, 301,
-- "240", 303, "240");
-- yahoo_packet_send_and_free(pkt, yd);
--
-- g_free(gpn);
-- g_free(gpo);
--}
--
--void yahoo_rename_group(PurpleConnection *gc, const char *old_name,
-- PurpleGroup *group, GList *moved_buddies)
--{
-- YahooData *yd = gc->proto_data;
-- struct yahoo_packet *pkt;
-- char *gpn, *gpo;
--
-- gpn = yahoo_string_encode(gc, purple_group_get_name(group), NULL);
-- gpo = yahoo_string_encode(gc, old_name, NULL);
-- if (!strcmp(gpn, gpo)) {
-- g_free(gpn);
-- g_free(gpo);
-- return;
-- }
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_GROUPRENAME, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc),
-- 65, gpo, 67, gpn);
-- yahoo_packet_send_and_free(pkt, yd);
-- g_free(gpn);
-- g_free(gpo);
--}
--
--/********************************* Commands **********************************/
--
--PurpleCmdRet
--yahoopurple_cmd_buzz(PurpleConversation *c, const gchar *cmd, gchar **args, gchar **error, void *data) {
-- PurpleAccount *account = purple_conversation_get_account(c);
--
-- if (*args && args[0])
-- return PURPLE_CMD_RET_FAILED;
--
-- purple_prpl_send_attention(account->gc, c->name, YAHOO_BUZZ);
--
-- return PURPLE_CMD_RET_OK;
--}
--
--PurpleCmdRet
--yahoopurple_cmd_chat_join(PurpleConversation *conv, const char *cmd,
-- char **args, char **error, void *data)
--{
-- GHashTable *comp;
-- PurpleConnection *gc;
--
-- if (!args || !args[0])
-- return PURPLE_CMD_RET_FAILED;
--
-- gc = purple_conversation_get_gc(conv);
-- purple_debug_info("yahoo", "Trying to join %s \n", args[0]);
--
-- comp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-- g_hash_table_replace(comp, g_strdup("room"), g_ascii_strdown(args[0], -1));
-- g_hash_table_replace(comp, g_strdup("type"), g_strdup("Chat"));
--
-- yahoo_c_join(gc, comp);
--
-- g_hash_table_destroy(comp);
-- return PURPLE_CMD_RET_OK;
--}
--
--PurpleCmdRet
--yahoopurple_cmd_chat_list(PurpleConversation *conv, const char *cmd,
-- char **args, char **error, void *data)
--{
-- PurpleAccount *account = purple_conversation_get_account(conv);
-- if (*args && args[0])
-- return PURPLE_CMD_RET_FAILED;
-- purple_roomlist_show_with_account(account);
-- return PURPLE_CMD_RET_OK;
--}
--
--gboolean yahoo_offline_message(const PurpleBuddy *buddy)
--{
-- return TRUE;
--}
--
--gboolean yahoo_send_attention(PurpleConnection *gc, const char *username, guint type)
--{
-- PurpleConversation *c;
--
-- c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-- username, gc->account);
--
-- g_return_val_if_fail(c != NULL, FALSE);
--
-- purple_debug_info("yahoo", "Sending <ding> on account %s to buddy %s.\n",
-- username, c->name);
-- purple_conv_im_send_with_flags(PURPLE_CONV_IM(c), "<ding>", PURPLE_MESSAGE_INVISIBLE);
--
-- return TRUE;
--}
--
--GList *yahoo_attention_types(PurpleAccount *account)
--{
-- static GList *list = NULL;
--
-- if (!list) {
-- /* Yahoo only supports one attention command: the 'buzz'. */
-- /* This is index number YAHOO_BUZZ. */
-- list = g_list_append(list, purple_attention_type_new("Buzz", _("Buzz"),
-- _("%s has buzzed you!"), _("Buzzing %s...")));
-- }
--
-- return list;
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/libymsg.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/libymsg.h
---- pidgin-2.10.7/libpurple/protocols/yahoo/libymsg.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/libymsg.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,402 +0,0 @@
--/**
-- * @file libymsg.h The Yahoo! and Yahoo! JAPAN Protocol Plugins
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _LIBYMSG_H_
--#define _LIBYMSG_H_
--
--#include "circbuffer.h"
--#include "cmds.h"
--#include "prpl.h"
--#include "network.h"
--
--#define YAHOO_PAGER_HOST_REQ_URL "http://vcs1.msg.yahoo.com/capacity"
--#define YAHOO_PAGER_HOST_FALLBACK "scsa.msg.yahoo.com"
--#define YAHOO_PAGER_PORT 5050
--#define YAHOO_PAGER_PORT_P2P 5101
--#define YAHOO_LOGIN_URL "https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts=&token=%s"
--#define YAHOO_TOKEN_URL "https://login.yahoo.com/config/pwtoken_get?src=ymsgr&ts=&login=%s&passwd=%s&chal=%s"
--#define YAHOO_P2P_KEEPALIVE_SECS 300
--#define YAHOO_P2P_SERVER_TIMEOUT 10
--#define YAHOO_PROFILE_URL "http://profiles.yahoo.com/"
--#define YAHOO_MAIL_URL "http://rd.yahoo.com/messenger/client/?http://mail.yahoo.com/"
--#define YAHOO_XFER_HOST "filetransfer.msg.yahoo.com"
--#define YAHOO_XFER_PORT 80
--#define YAHOO_XFER_RELAY_HOST "relay.msg.yahoo.com"
--#define YAHOO_XFER_RELAY_PORT 80
--#define YAHOO_ROOMLIST_URL "http://insider.msg.yahoo.com/ycontent/"
--#define YAHOO_ROOMLIST_LOCALE "us"
--
--/* Yahoo! JAPAN stuff */
--#define YAHOOJP_PAGER_HOST_REQ_URL "http://cs1.yahoo.co.jp/capacity"
--#define YAHOOJP_TOKEN_URL "https://login.yahoo.co.jp/config/pwtoken_get?src=ymsgr&ts=&login=%s&passwd=%s&chal=%s"
--#define YAHOOJP_LOGIN_URL "https://login.yahoo.co.jp/config/pwtoken_login?src=ymsgr&ts=&token=%s"
--#define YAHOOJP_PROFILE_URL "http://profiles.yahoo.co.jp/"
--#define YAHOOJP_MAIL_URL "http://mail.yahoo.co.jp/"
--#define YAHOOJP_XFER_HOST "filetransfer.msg.yahoo.co.jp"
--#define YAHOOJP_WEBCAM_HOST "wc.yahoo.co.jp"
--/* not sure, must test: */
--#define YAHOOJP_XFER_RELAY_HOST "relay.msg.yahoo.co.jp"
--#define YAHOOJP_XFER_RELAY_PORT 80
--#define YAHOOJP_ROOMLIST_URL "http://insider.msg.yahoo.co.jp/ycontent/"
--#define YAHOOJP_ROOMLIST_LOCALE "ja"
--
--#define YAHOO_AUDIBLE_URL "http://l.yimg.com/pu/dl/aud"
--
--#define WEBMESSENGER_URL "http://login.yahoo.com/config/login?.src=pg"
--
--#define YAHOO_SMS_CARRIER_URL "http://validate.msg.yahoo.com"
--
--#define YAHOO_USERINFO_URL "http://address.yahoo.com/yab/us?v=XM&sync=1&tags=short&useutf8=1&noclear=1&legenc=codepage-1252"
--#define YAHOOJP_USERINFO_URL "http://address.yahoo.co.jp/yab/jp?v=XM&sync=1&tags=short&useutf8=1&noclear=1&legenc=codepage-1252"
--
--#define YAHOO_PICURL_SETTING "picture_url"
--#define YAHOO_PICCKSUM_SETTING "picture_checksum"
--#define YAHOO_PICEXPIRE_SETTING "picture_expire"
--
--#define YAHOO_STATUS_TYPE_OFFLINE "offline"
--#define YAHOO_STATUS_TYPE_AVAILABLE "available"
--#define YAHOO_STATUS_TYPE_BRB "brb"
--#define YAHOO_STATUS_TYPE_BUSY "busy"
--#define YAHOO_STATUS_TYPE_NOTATHOME "notathome"
--#define YAHOO_STATUS_TYPE_NOTATDESK "notatdesk"
--#define YAHOO_STATUS_TYPE_NOTINOFFICE "notinoffice"
--#define YAHOO_STATUS_TYPE_ONPHONE "onphone"
--#define YAHOO_STATUS_TYPE_ONVACATION "onvacation"
--#define YAHOO_STATUS_TYPE_OUTTOLUNCH "outtolunch"
--#define YAHOO_STATUS_TYPE_STEPPEDOUT "steppedout"
--#define YAHOO_STATUS_TYPE_AWAY "away"
--#define YAHOO_STATUS_TYPE_INVISIBLE "invisible"
--#define YAHOO_STATUS_TYPE_MOBILE "mobile"
--
--#define YAHOO_CLIENT_VERSION_ID "4194239"
--#define YAHOO_CLIENT_VERSION "9.0.0.2162"
--
--#define YAHOOJP_CLIENT_VERSION_ID "4186047"
--#define YAHOOJP_CLIENT_VERSION "9.0.0.1727"
--
--#define YAHOO_CLIENT_USERAGENT "Mozilla/5.0"
--#define YAHOO_CLIENT_USERAGENT_ALIAS "Mozilla/4.0 (compatible; MSIE 5.5)"
--
--/* Index into attention types list. */
--#define YAHOO_BUZZ 0
--
--typedef enum {
-- YAHOO_PKT_TYPE_SERVER = 0,
-- YAHOO_PKT_TYPE_P2P
--} yahoo_pkt_type;
--
--typedef enum {
-- YAHOO_P2P_WE_ARE_CLIENT =0,
-- YAHOO_P2P_WE_ARE_SERVER
--} yahoo_p2p_connection_type;
--
--enum yahoo_status {
-- YAHOO_STATUS_AVAILABLE = 0,
-- YAHOO_STATUS_BRB,
-- YAHOO_STATUS_BUSY,
-- YAHOO_STATUS_NOTATHOME,
-- YAHOO_STATUS_NOTATDESK,
-- YAHOO_STATUS_NOTINOFFICE,
-- YAHOO_STATUS_ONPHONE,
-- YAHOO_STATUS_ONVACATION,
-- YAHOO_STATUS_OUTTOLUNCH,
-- YAHOO_STATUS_STEPPEDOUT,
-- YAHOO_STATUS_P2P = 11,
-- YAHOO_STATUS_INVISIBLE = 12,
-- YAHOO_STATUS_CUSTOM = 99,
-- YAHOO_STATUS_IDLE = 999,
-- YAHOO_STATUS_WEBLOGIN = 0x5a55aa55,
-- YAHOO_STATUS_OFFLINE = 0x5a55aa56, /* don't ask */
-- YAHOO_STATUS_TYPING = 0x16,
-- YAHOO_STATUS_DISCONNECTED = 0xffffffff /* in ymsg 15. doesnt mean the normal sense of 'disconnected' */
--};
--
--/*
-- * Yahoo federated networks. Key 241 in ymsg.
-- * If it doesn't exist, it is on Yahoo's netowrk.
-- * It if does exist, send to another IM network.
-- */
--
--typedef enum {
-- YAHOO_FEDERATION_NONE = 0, /* No federation - Yahoo! network */
-- YAHOO_FEDERATION_OCS = 1, /* LCS or OCS private networks */
-- YAHOO_FEDERATION_MSN = 2, /* MSN or Windows Live network */
-- YAHOO_FEDERATION_IBM = 9, /* IBM/Sametime network */
-- YAHOO_FEDERATION_PBX = 100 /* Yahoo! Pingbox service */
--} YahooFederation;
--
--
--struct yahoo_buddy_icon_upload_data {
-- PurpleConnection *gc;
-- GString *str;
-- char *filename;
-- int pos;
-- int fd;
-- guint watcher;
--};
--
--struct yahoo_p2p_data {
-- PurpleConnection *gc;
-- char *host_ip;
-- char *host_username;
-- int val_13;
-- guint input_event;
-- gint source;
-- int session_id;
-- yahoo_p2p_connection_type connection_type;
--};
--
--struct _YchtConn;
--
--typedef struct _YahooPersonalDetails {
-- char *id;
--
-- struct {
-- char *first;
-- char *last;
-- char *middle;
-- char *nick;
-- } names;
--
-- struct {
-- char *work;
-- char *home;
-- char *mobile;
-- } phone;
--} YahooPersonalDetails;
--
--typedef struct {
-- PurpleConnection *gc;
-- int fd;
-- guchar *rxqueue;
-- int rxlen;
-- PurpleCircBuffer *txbuf;
-- guint txhandler;
-- GHashTable *friends;
--
-- char **profiles; /* Multiple profiles can be associated with an account */
-- YahooPersonalDetails ypd;
--
-- /**
-- * This is used to keep track of the IMVironment chosen
-- * by people you talk to. We don't do very much with
-- * this right now... but at least now if the remote user
-- * selects an IMVironment we won't reset it back to the
-- * default of nothing.
-- */
-- GHashTable *imvironments;
--
-- int current_status;
-- gboolean logged_in;
-- GString *tmp_serv_blist, *tmp_serv_ilist, *tmp_serv_plist;
-- GSList *confs;
-- unsigned int conf_id; /* just a counter */
-- gboolean chat_online;
-- gboolean in_chat;
-- char *chat_name;
-- char *pending_chat_room;
-- char *pending_chat_id;
-- char *pending_chat_topic;
-- char *pending_chat_goto;
-- char *auth;
-- gsize auth_written;
-- char *cookie_y;
-- char *cookie_t;
-- char *cookie_b;
-- int session_id;
-- gboolean jp;
-- gboolean wm; /* connected w/ web messenger method */
-- /* picture aka buddy icon stuff */
-- char *picture_url;
-- int picture_checksum;
--
-- /* ew. we have to check the icon before we connect,
-- * but can't upload it til we're connected. */
-- struct yahoo_buddy_icon_upload_data *picture_upload_todo;
-- PurpleProxyConnectData *buddy_icon_connect_data;
--
-- struct _YchtConn *ycht;
--
-- /**
-- * This linked list contains PurpleUtilFetchUrlData structs
-- * for when we lookup people profile or photo information.
-- */
-- GSList *url_datas;
-- GHashTable *xfer_peer_idstring_map;/* Hey, i dont know, but putting this HashTable next to friends gives a run time fault... */
-- GSList *cookies;/* contains all cookies, including _y and _t */
-- PurpleNetworkListenData *listen_data;
--
-- /**
-- * We may receive a list15 in multiple packets with no prior warning as to how many we'll be getting;
-- * the server expects us to keep track of the group for which it is sending us contact names.
-- */
-- char *current_list15_grp;
-- time_t last_ping;
-- time_t last_keepalive;
-- GHashTable *peers; /* information about p2p data */
-- int yahoo_p2p_timer;
-- int yahoo_local_p2p_server_fd;
-- int yahoo_p2p_server_watcher;
-- GHashTable *sms_carrier; /* sms carrier data */
-- guint yahoo_p2p_server_timeout_handle;
--} YahooData;
--
--#define YAHOO_MAX_STATUS_MESSAGE_LENGTH (255)
--
--/*
-- * Current Maximum Length for Instant Messages
-- *
-- * This was found by experiment.
-- *
-- * The YMSG protocol allows a message of up to 948 bytes, but the official client
-- * limits to 800 characters. According to experiments I conducted, it seems that
-- * the discrepancy is to allow some leeway for messages with mixed single- and
-- * multi-byte characters, as I was able to send messages of 840 and 932 bytes
-- * by using some multibyte characters (some random Chinese or Japanese characters,
-- * to be precise). - rekkanoryo
-- */
--#define YAHOO_MAX_MESSAGE_LENGTH_BYTES 948
--#define YAHOO_MAX_MESSAGE_LENGTH_CHARS 800
--
--/* sometimes i wish prpls could #include things from other prpls. then i could just
-- * use the routines from libfaim and not have to admit to knowing how they work. */
--#define yahoo_put16(buf, data) ( \
-- (*(buf) = (unsigned char)((data)>>8)&0xff), \
-- (*((buf)+1) = (unsigned char)(data)&0xff), \
-- 2)
--#define yahoo_get16(buf) ((((*(buf))<<8)&0xff00) + ((*((buf)+1)) & 0xff))
--#define yahoo_put32(buf, data) ( \
-- (*((buf)) = (unsigned char)((data)>>24)&0xff), \
-- (*((buf)+1) = (unsigned char)((data)>>16)&0xff), \
-- (*((buf)+2) = (unsigned char)((data)>>8)&0xff), \
-- (*((buf)+3) = (unsigned char)(data)&0xff), \
-- 4)
--#define yahoo_get32(buf) ((((*(buf))<<24)&0xff000000) + \
-- (((*((buf)+1))<<16)&0x00ff0000) + \
-- (((*((buf)+2))<< 8)&0x0000ff00) + \
-- (((*((buf)+3) )&0x000000ff)))
--
--/* util.c */
--void yahoo_init_colorht(void);
--void yahoo_dest_colorht(void);
--char *yahoo_codes_to_html(const char *x);
--
--/**
-- * This function takes a normal HTML message and converts it to the message
-- * format used by Yahoo, which uses a frankensteinish combination of ANSI
-- * escape codes and broken HTML.
-- *
-- * It results in slightly different output than would be sent by official
-- * Yahoo clients. The two main differences are:
-- *
-- * 1. We always close all tags, whereas official Yahoo clients leave tags
-- * dangling open at the end of each message (and the client treats them
-- * as closed).
-- * 2. We always close inner tags first before closing outter tags.
-- *
-- * For example, if you want to send this message:
-- * <b> bold <i> bolditalic </i></b><i> italic </i>
-- * Official Yahoo clients would send:
-- * ESC[1m bold ESC[2m bolditalic ESC[x1m italic
-- * But we will send:
-- * ESC[1m bold ESC[2m bolditalic ESC[x2mESC[x1mESC[2m italic ESC[x2m
-- */
--char *yahoo_html_to_codes(const char *src);
--
--gboolean
--yahoo_account_use_http_proxy(PurpleConnection *conn);
--
--/**
-- * Encode some text to send to the yahoo server.
-- *
-- * @param gc The connection handle.
-- * @param str The null terminated utf8 string to encode.
-- * @param utf8 If not @c NULL, whether utf8 is okay or not.
-- * Even if it is okay, we may not use it. If we
-- * used it, we set this to @c TRUE, else to
-- * @c FALSE. If @c NULL, false is assumed, and
-- * it is not dereferenced.
-- * @return The g_malloced string in the appropriate encoding.
-- */
--char *yahoo_string_encode(PurpleConnection *gc, const char *str, gboolean *utf8);
--
--/**
-- * Decode some text received from the server.
-- *
-- * @param gc The gc handle.
-- * @param str The null terminated string to decode.
-- * @param utf8 Did the server tell us it was supposed to be utf8?
-- * @return The decoded, utf-8 string, which must be g_free()'d.
-- */
--char *yahoo_string_decode(PurpleConnection *gc, const char *str, gboolean utf8);
--
--char *yahoo_convert_to_numeric(const char *str);
--
--YahooFederation yahoo_get_federation_from_name(const char *who);
--
--/* yahoo_profile.c */
--void yahoo_get_info(PurpleConnection *gc, const char *name);
--
--/* libymsg.h - these functions were formerly static but need not to be for the
-- * new two-prpl model. */
--const char *yahoo_list_icon(PurpleAccount *a, PurpleBuddy *b);
--const char *yahoo_list_emblem(PurpleBuddy *b);
--char *yahoo_status_text(PurpleBuddy *b);
--void yahoo_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full);
--GList *yahoo_status_types(PurpleAccount *account);
--GList *yahoo_blist_node_menu(PurpleBlistNode *node);
--void yahoo_login(PurpleAccount *account);
--void yahoo_close(PurpleConnection *gc);
--int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags);
--unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state);
--void yahoo_set_status(PurpleAccount *account, PurpleStatus *status);
--void yahoo_set_idle(PurpleConnection *gc, int idle);
--void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g);
--void yahoo_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
--void yahoo_add_deny(PurpleConnection *gc, const char *who);
--void yahoo_rem_deny(PurpleConnection *gc, const char *who);
--void yahoo_set_permit_deny(PurpleConnection *gc);
--void yahoo_keepalive(PurpleConnection *gc);
--void yahoo_change_buddys_group(PurpleConnection *gc, const char *who, const char *old_group, const char *new_group);
--void yahoo_rename_group(PurpleConnection *gc, const char *old_name, PurpleGroup *group, GList *moved_buddies);
--gboolean yahoo_offline_message(const PurpleBuddy *buddy);
--gboolean yahoo_send_attention(PurpleConnection *gc, const char *username, guint type);
--GList *yahoo_attention_types(PurpleAccount *account);
--
--GList *yahoo_actions(PurplePlugin *plugin, gpointer context);
--void yahoopurple_register_commands(void);
--
--PurpleCmdRet yahoopurple_cmd_buzz(PurpleConversation *c, const gchar *cmd, gchar **args, gchar **error, void *data);
--PurpleCmdRet yahoopurple_cmd_chat_join(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data);
--PurpleCmdRet yahoopurple_cmd_chat_list(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data);
--/* needed for xfer, thought theyd be useful for other enhancements later on
-- Returns list of cookies stored in yahoo_data formatted as a single null terminated string
-- returned value must be g_freed
--*/
--gchar* yahoo_get_cookies(PurpleConnection *gc);
--
--/* send p2p pkt containing our encoded ip, asking peer to connect to us */
--void yahoo_send_p2p_pkt(PurpleConnection *gc, const char *who, int val_13);
--
--#endif /* _LIBYMSG_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/Makefile.am
---- pidgin-2.10.7/libpurple/protocols/yahoo/Makefile.am 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/Makefile.am 1969-12-31 21:00:00.000000000 -0300
-@@ -1,60 +0,0 @@
--EXTRA_DIST = \
-- Makefile.mingw
--
--pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
--
--YAHOOSOURCES = \
-- libymsg.c \
-- libymsg.h \
-- util.c \
-- yahoochat.h \
-- yahoochat.c \
-- yahoo_aliases.c \
-- yahoo_aliases.h \
-- yahoo_doodle.h \
-- yahoo_doodle.c \
-- yahoo_filexfer.h \
-- yahoo_filexfer.c \
-- yahoo_friend.h \
-- yahoo_friend.c \
-- yahoo_packet.h \
-- yahoo_packet.c \
-- yahoo_picture.c \
-- yahoo_picture.h \
-- yahoo_profile.c \
-- ycht.c \
-- ycht.h
--
--AM_CFLAGS = $(st)
--
--libyahoo_la_LDFLAGS = -module -avoid-version
--libyahoojp_la_LDFLAGS = -module -avoid-version
--
--if STATIC_YAHOO
--
--st = -DPURPLE_STATIC_PRPL
--noinst_LTLIBRARIES = libymsg.la
--libymsg_la_SOURCES = $(YAHOOSOURCES) libyahoo.c libyahoojp.c
--libymsg_la_CFLAGS = $(AM_CFLAGS)
--
--else
--
--st =
--pkg_LTLIBRARIES = libymsg.la libyahoo.la libyahoojp.la
--
--libymsg_la_SOURCES = $(YAHOOSOURCES)
--libymsg_la_LIBADD = $(GLIB_LIBS)
--
--libyahoo_la_SOURCES = libyahoo.c
--libyahoo_la_LIBADD = libymsg.la
--
--libyahoojp_la_SOURCES = libyahoojp.c
--libyahoojp_la_LIBADD = libymsg.la
--
--endif
--
--AM_CPPFLAGS = \
-- -I$(top_srcdir)/libpurple \
-- -I$(top_builddir)/libpurple \
-- $(GLIB_CFLAGS) \
-- $(DEBUG_CFLAGS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/Makefile.in
---- pidgin-2.10.7/libpurple/protocols/yahoo/Makefile.in 2013-02-11 07:17:22.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/Makefile.in 1969-12-31 21:00:00.000000000 -0300
-@@ -1,904 +0,0 @@
--# Makefile.in generated by automake 1.11.6 from Makefile.am.
--# @configure_input@
--
--# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
--# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
--# Foundation, Inc.
--# This Makefile.in is free software; the Free Software Foundation
--# gives unlimited permission to copy and/or distribute it,
--# with or without modifications, as long as this notice is preserved.
--
--# This program is distributed in the hope that it will be useful,
--# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
--# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
--# PARTICULAR PURPOSE.
--
--@SET_MAKE@
--
--VPATH = @srcdir@
--am__make_dryrun = \
-- { \
-- am__dry=no; \
-- case $$MAKEFLAGS in \
-- *\\[\ \ ]*) \
-- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
-- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
-- *) \
-- for am__flg in $$MAKEFLAGS; do \
-- case $$am__flg in \
-- *=*|--*) ;; \
-- *n*) am__dry=yes; break;; \
-- esac; \
-- done;; \
-- esac; \
-- test $$am__dry = yes; \
-- }
--pkgdatadir = $(datadir)/@PACKAGE@
--pkgincludedir = $(includedir)/@PACKAGE@
--pkglibdir = $(libdir)/@PACKAGE@
--pkglibexecdir = $(libexecdir)/@PACKAGE@
--am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
--install_sh_DATA = $(install_sh) -c -m 644
--install_sh_PROGRAM = $(install_sh) -c
--install_sh_SCRIPT = $(install_sh) -c
--INSTALL_HEADER = $(INSTALL_DATA)
--transform = $(program_transform_name)
--NORMAL_INSTALL = :
--PRE_INSTALL = :
--POST_INSTALL = :
--NORMAL_UNINSTALL = :
--PRE_UNINSTALL = :
--POST_UNINSTALL = :
--build_triplet = @build@
--host_triplet = @host@
--subdir = libpurple/protocols/yahoo
--DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
--ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
--am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
-- $(top_srcdir)/configure.ac
--am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-- $(ACLOCAL_M4)
--mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
--CONFIG_HEADER = $(top_builddir)/config.h
--CONFIG_CLEAN_FILES =
--CONFIG_CLEAN_VPATH_FILES =
--am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
--am__vpath_adj = case $$p in \
-- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
-- *) f=$$p;; \
-- esac;
--am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
--am__install_max = 40
--am__nobase_strip_setup = \
-- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
--am__nobase_strip = \
-- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
--am__nobase_list = $(am__nobase_strip_setup); \
-- for p in $$list; do echo "$$p $$p"; done | \
-- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
-- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
-- if (++n[$$2] == $(am__install_max)) \
-- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
-- END { for (dir in files) print dir, files[dir] }'
--am__base_list = \
-- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
-- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
--am__uninstall_files_from_dir = { \
-- test -z "$$files" \
-- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
-- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
-- $(am__cd) "$$dir" && rm -f $$files; }; \
-- }
--am__installdirs = "$(DESTDIR)$(pkgdir)"
--LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkg_LTLIBRARIES)
--@STATIC_YAHOO_FALSE@libyahoo_la_DEPENDENCIES = libymsg.la
--am__libyahoo_la_SOURCES_DIST = libyahoo.c
--@STATIC_YAHOO_FALSE@am_libyahoo_la_OBJECTS = libyahoo.lo
--libyahoo_la_OBJECTS = $(am_libyahoo_la_OBJECTS)
--AM_V_lt = $(am__v_lt_@AM_V@)
--am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
--am__v_lt_0 = --silent
--libyahoo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-- $(libyahoo_la_LDFLAGS) $(LDFLAGS) -o $@
--@STATIC_YAHOO_FALSE@am_libyahoo_la_rpath = -rpath $(pkgdir)
--@STATIC_YAHOO_FALSE@libyahoojp_la_DEPENDENCIES = libymsg.la
--am__libyahoojp_la_SOURCES_DIST = libyahoojp.c
--@STATIC_YAHOO_FALSE@am_libyahoojp_la_OBJECTS = libyahoojp.lo
--libyahoojp_la_OBJECTS = $(am_libyahoojp_la_OBJECTS)
--libyahoojp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-- $(libyahoojp_la_LDFLAGS) $(LDFLAGS) -o $@
--@STATIC_YAHOO_FALSE@am_libyahoojp_la_rpath = -rpath $(pkgdir)
--am__DEPENDENCIES_1 =
--@STATIC_YAHOO_FALSE@libymsg_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
--am__libymsg_la_SOURCES_DIST = libymsg.c libymsg.h util.c yahoochat.h \
-- yahoochat.c yahoo_aliases.c yahoo_aliases.h yahoo_doodle.h \
-- yahoo_doodle.c yahoo_filexfer.h yahoo_filexfer.c \
-- yahoo_friend.h yahoo_friend.c yahoo_packet.h yahoo_packet.c \
-- yahoo_picture.c yahoo_picture.h yahoo_profile.c ycht.c ycht.h \
-- libyahoo.c libyahoojp.c
--am__objects_1 = libymsg_la-libymsg.lo libymsg_la-util.lo \
-- libymsg_la-yahoochat.lo libymsg_la-yahoo_aliases.lo \
-- libymsg_la-yahoo_doodle.lo libymsg_la-yahoo_filexfer.lo \
-- libymsg_la-yahoo_friend.lo libymsg_la-yahoo_packet.lo \
-- libymsg_la-yahoo_picture.lo libymsg_la-yahoo_profile.lo \
-- libymsg_la-ycht.lo
--@STATIC_YAHOO_FALSE@am_libymsg_la_OBJECTS = $(am__objects_1)
--@STATIC_YAHOO_TRUE@am_libymsg_la_OBJECTS = $(am__objects_1) \
--@STATIC_YAHOO_TRUE@ libymsg_la-libyahoo.lo \
--@STATIC_YAHOO_TRUE@ libymsg_la-libyahoojp.lo
--libymsg_la_OBJECTS = $(am_libymsg_la_OBJECTS)
--libymsg_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libymsg_la_CFLAGS) \
-- $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
--@STATIC_YAHOO_FALSE@am_libymsg_la_rpath = -rpath $(pkgdir)
--@STATIC_YAHOO_TRUE@am_libymsg_la_rpath =
--DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
--depcomp = $(SHELL) $(top_srcdir)/depcomp
--am__depfiles_maybe = depfiles
--am__mv = mv -f
--COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
--LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-- $(AM_CFLAGS) $(CFLAGS)
--AM_V_CC = $(am__v_CC_@AM_V@)
--am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
--am__v_CC_0 = @echo " CC " $@;
--AM_V_at = $(am__v_at_@AM_V@)
--am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
--am__v_at_0 = @
--CCLD = $(CC)
--LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-- $(AM_LDFLAGS) $(LDFLAGS) -o $@
--AM_V_CCLD = $(am__v_CCLD_@AM_V@)
--am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
--am__v_CCLD_0 = @echo " CCLD " $@;
--AM_V_GEN = $(am__v_GEN_@AM_V@)
--am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
--am__v_GEN_0 = @echo " GEN " $@;
--SOURCES = $(libyahoo_la_SOURCES) $(libyahoojp_la_SOURCES) \
-- $(libymsg_la_SOURCES)
--DIST_SOURCES = $(am__libyahoo_la_SOURCES_DIST) \
-- $(am__libyahoojp_la_SOURCES_DIST) \
-- $(am__libymsg_la_SOURCES_DIST)
--am__can_run_installinfo = \
-- case $$AM_UPDATE_INFO_DIR in \
-- n|no|NO) false;; \
-- *) (install-info --version) >/dev/null 2>&1;; \
-- esac
--ETAGS = etags
--CTAGS = ctags
--DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
--ACLOCAL = @ACLOCAL@
--ALLOCA = @ALLOCA@
--ALL_LINGUAS = @ALL_LINGUAS@
--AMTAR = @AMTAR@
--AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
--AR = @AR@
--AUTOCONF = @AUTOCONF@
--AUTOHEADER = @AUTOHEADER@
--AUTOMAKE = @AUTOMAKE@
--AVAHI_CFLAGS = @AVAHI_CFLAGS@
--AVAHI_LIBS = @AVAHI_LIBS@
--AWK = @AWK@
--CATALOGS = @CATALOGS@
--CATOBJEXT = @CATOBJEXT@
--CC = @CC@
--CCDEPMODE = @CCDEPMODE@
--CFLAGS = @CFLAGS@
--CHECK_CFLAGS = @CHECK_CFLAGS@
--CHECK_LIBS = @CHECK_LIBS@
--CPP = @CPP@
--CPPFLAGS = @CPPFLAGS@
--CYGPATH_W = @CYGPATH_W@
--DATADIRNAME = @DATADIRNAME@
--DBUS_CFLAGS = @DBUS_CFLAGS@
--DBUS_LIBS = @DBUS_LIBS@
--DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
--DEBUG_CFLAGS = @DEBUG_CFLAGS@
--DEFS = @DEFS@
--DEPDIR = @DEPDIR@
--DLLTOOL = @DLLTOOL@
--DOT = @DOT@
--DOXYGEN = @DOXYGEN@
--DSYMUTIL = @DSYMUTIL@
--DUMPBIN = @DUMPBIN@
--DYNALOADER_A = @DYNALOADER_A@
--DYNAMIC_PRPLS = @DYNAMIC_PRPLS@
--ECHO_C = @ECHO_C@
--ECHO_N = @ECHO_N@
--ECHO_T = @ECHO_T@
--EGREP = @EGREP@
--EVOLUTION_ADDRESSBOOK_CFLAGS = @EVOLUTION_ADDRESSBOOK_CFLAGS@
--EVOLUTION_ADDRESSBOOK_LIBS = @EVOLUTION_ADDRESSBOOK_LIBS@
--EXEEXT = @EXEEXT@
--FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
--FARSTREAM_LIBS = @FARSTREAM_LIBS@
--FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
--GCONFTOOL = @GCONFTOOL@
--GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
--GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
--GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
--GLIB_CFLAGS = @GLIB_CFLAGS@
--GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
--GLIB_LIBS = @GLIB_LIBS@
--GMOFILES = @GMOFILES@
--GMSGFMT = @GMSGFMT@
--GNT_CFLAGS = @GNT_CFLAGS@
--GNT_LIBS = @GNT_LIBS@
--GNT_LT_VERSION_INFO = @GNT_LT_VERSION_INFO@
--GNT_MAJOR_VERSION = @GNT_MAJOR_VERSION@
--GNT_MICRO_VERSION = @GNT_MICRO_VERSION@
--GNT_MINOR_VERSION = @GNT_MINOR_VERSION@
--GNT_VERSION = @GNT_VERSION@
--GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
--GNUTLS_LIBS = @GNUTLS_LIBS@
--GREP = @GREP@
--GSTINTERFACES_CFLAGS = @GSTINTERFACES_CFLAGS@
--GSTINTERFACES_LIBS = @GSTINTERFACES_LIBS@
--GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
--GSTREAMER_LIBS = @GSTREAMER_LIBS@
--GTKSPELL_CFLAGS = @GTKSPELL_CFLAGS@
--GTKSPELL_LIBS = @GTKSPELL_LIBS@
--GTK_CFLAGS = @GTK_CFLAGS@
--GTK_LIBS = @GTK_LIBS@
--IDN_CFLAGS = @IDN_CFLAGS@
--IDN_LIBS = @IDN_LIBS@
--INSTALL = @INSTALL@
--INSTALL_DATA = @INSTALL_DATA@
--INSTALL_PROGRAM = @INSTALL_PROGRAM@
--INSTALL_SCRIPT = @INSTALL_SCRIPT@
--INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
--INSTOBJEXT = @INSTOBJEXT@
--INTLLIBS = @INTLLIBS@
--INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
--INTLTOOL_MERGE = @INTLTOOL_MERGE@
--INTLTOOL_PERL = @INTLTOOL_PERL@
--INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
--INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
--INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
--INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
--INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
--KRB4_CFLAGS = @KRB4_CFLAGS@
--KRB4_LDFLAGS = @KRB4_LDFLAGS@
--KRB4_LIBS = @KRB4_LIBS@
--LD = @LD@
--LDADD = @LDADD@
--LDFLAGS = @LDFLAGS@
--LIBOBJS = @LIBOBJS@
--LIBPERL_A = @LIBPERL_A@
--LIBS = @LIBS@
--LIBTOOL = @LIBTOOL@
--LIBXML_CFLAGS = @LIBXML_CFLAGS@
--LIBXML_LIBS = @LIBXML_LIBS@
--LIPO = @LIPO@
--LN_S = @LN_S@
--LTLIBOBJS = @LTLIBOBJS@
--MAKEINFO = @MAKEINFO@
--MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
--MKDIR_P = @MKDIR_P@
--MKINSTALLDIRS = @MKINSTALLDIRS@
--MONO_CFLAGS = @MONO_CFLAGS@
--MONO_LIBS = @MONO_LIBS@
--MSGFMT = @MSGFMT@
--MSGFMT_OPTS = @MSGFMT_OPTS@
--MSGMERGE = @MSGMERGE@
--NETWORKMANAGER_CFLAGS = @NETWORKMANAGER_CFLAGS@
--NETWORKMANAGER_LIBS = @NETWORKMANAGER_LIBS@
--NM = @NM@
--NMEDIT = @NMEDIT@
--NSS_CFLAGS = @NSS_CFLAGS@
--NSS_LIBS = @NSS_LIBS@
--OBJDUMP = @OBJDUMP@
--OBJEXT = @OBJEXT@
--OTOOL = @OTOOL@
--OTOOL64 = @OTOOL64@
--PACKAGE = @PACKAGE@
--PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
--PACKAGE_NAME = @PACKAGE_NAME@
--PACKAGE_STRING = @PACKAGE_STRING@
--PACKAGE_TARNAME = @PACKAGE_TARNAME@
--PACKAGE_URL = @PACKAGE_URL@
--PACKAGE_VERSION = @PACKAGE_VERSION@
--PANGO_CFLAGS = @PANGO_CFLAGS@
--PANGO_LIBS = @PANGO_LIBS@
--PATH_SEPARATOR = @PATH_SEPARATOR@
--PERL = @PERL@
--PERL_CFLAGS = @PERL_CFLAGS@
--PERL_LIBS = @PERL_LIBS@
--PKG_CONFIG = @PKG_CONFIG@
--PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
--PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
--PLUGINS_DEFINE = @PLUGINS_DEFINE@
--POFILES = @POFILES@
--POSUB = @POSUB@
--PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
--PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
--PURPLE_LT_VERSION_INFO = @PURPLE_LT_VERSION_INFO@
--PURPLE_MAJOR_VERSION = @PURPLE_MAJOR_VERSION@
--PURPLE_MICRO_VERSION = @PURPLE_MICRO_VERSION@
--PURPLE_MINOR_VERSION = @PURPLE_MINOR_VERSION@
--PURPLE_VERSION = @PURPLE_VERSION@
--PYTHON = @PYTHON@
--PY_CFLAGS = @PY_CFLAGS@
--PY_LIBS = @PY_LIBS@
--RANLIB = @RANLIB@
--SASL_LIBS = @SASL_LIBS@
--SED = @SED@
--SET_MAKE = @SET_MAKE@
--SHELL = @SHELL@
--SILC_CFLAGS = @SILC_CFLAGS@
--SILC_LIBS = @SILC_LIBS@
--SM_LIBS = @SM_LIBS@
--SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
--SQLITE3_LIBS = @SQLITE3_LIBS@
--SSL_CERTIFICATES_DIR = @SSL_CERTIFICATES_DIR@
--STATIC_LINK_LIBS = @STATIC_LINK_LIBS@
--STATIC_PRPLS = @STATIC_PRPLS@
--STRIP = @STRIP@
--TCL_CFLAGS = @TCL_CFLAGS@
--TCL_LIBS = @TCL_LIBS@
--TK_LIBS = @TK_LIBS@
--USE_NLS = @USE_NLS@
--VERSION = @VERSION@
--X11_CFLAGS = @X11_CFLAGS@
--X11_LIBS = @X11_LIBS@
--XGETTEXT = @XGETTEXT@
--XMKMF = @XMKMF@
--XSLTPROC = @XSLTPROC@
--XSS_LIBS = @XSS_LIBS@
--X_CFLAGS = @X_CFLAGS@
--X_EXTRA_LIBS = @X_EXTRA_LIBS@
--X_LIBS = @X_LIBS@
--X_PRE_LIBS = @X_PRE_LIBS@
--ZEPHYR_CFLAGS = @ZEPHYR_CFLAGS@
--ZEPHYR_LDFLAGS = @ZEPHYR_LDFLAGS@
--ZEPHYR_LIBS = @ZEPHYR_LIBS@
--abs_builddir = @abs_builddir@
--abs_srcdir = @abs_srcdir@
--abs_top_builddir = @abs_top_builddir@
--abs_top_srcdir = @abs_top_srcdir@
--ac_ct_AR = @ac_ct_AR@
--ac_ct_CC = @ac_ct_CC@
--ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
--am__include = @am__include@
--am__leading_dot = @am__leading_dot@
--am__quote = @am__quote@
--am__tar = @am__tar@
--am__untar = @am__untar@
--bindir = @bindir@
--build = @build@
--build_alias = @build_alias@
--build_cpu = @build_cpu@
--build_os = @build_os@
--build_vendor = @build_vendor@
--builddir = @builddir@
--datadir = @datadir@
--datarootdir = @datarootdir@
--docdir = @docdir@
--dvidir = @dvidir@
--enable_dbus = @enable_dbus@
--enable_devhelp = @enable_devhelp@
--enable_dot = @enable_dot@
--enable_doxygen = @enable_doxygen@
--exec_prefix = @exec_prefix@
--host = @host@
--host_alias = @host_alias@
--host_cpu = @host_cpu@
--host_os = @host_os@
--host_vendor = @host_vendor@
--htmldir = @htmldir@
--includedir = @includedir@
--infodir = @infodir@
--install_sh = @install_sh@
--intltool__v_merge_options_ = @intltool__v_merge_options_@
--intltool__v_merge_options_0 = @intltool__v_merge_options_0@
--libdir = @libdir@
--libexecdir = @libexecdir@
--localedir = @localedir@
--localstatedir = @localstatedir@
--mandir = @mandir@
--mkdir_p = @mkdir_p@
--oldincludedir = @oldincludedir@
--pdfdir = @pdfdir@
--perlpath = @perlpath@
--pidginpath = @pidginpath@
--prefix = @prefix@
--program_transform_name = @program_transform_name@
--psdir = @psdir@
--sbindir = @sbindir@
--sedpath = @sedpath@
--sharedstatedir = @sharedstatedir@
--srcdir = @srcdir@
--sysconfdir = @sysconfdir@
--target_alias = @target_alias@
--top_build_prefix = @top_build_prefix@
--top_builddir = @top_builddir@
--top_srcdir = @top_srcdir@
--EXTRA_DIST = \
-- Makefile.mingw
--
--pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
--YAHOOSOURCES = \
-- libymsg.c \
-- libymsg.h \
-- util.c \
-- yahoochat.h \
-- yahoochat.c \
-- yahoo_aliases.c \
-- yahoo_aliases.h \
-- yahoo_doodle.h \
-- yahoo_doodle.c \
-- yahoo_filexfer.h \
-- yahoo_filexfer.c \
-- yahoo_friend.h \
-- yahoo_friend.c \
-- yahoo_packet.h \
-- yahoo_packet.c \
-- yahoo_picture.c \
-- yahoo_picture.h \
-- yahoo_profile.c \
-- ycht.c \
-- ycht.h
--
--AM_CFLAGS = $(st)
--libyahoo_la_LDFLAGS = -module -avoid-version
--libyahoojp_la_LDFLAGS = -module -avoid-version
--@STATIC_YAHOO_FALSE@st =
--@STATIC_YAHOO_TRUE@st = -DPURPLE_STATIC_PRPL
--@STATIC_YAHOO_TRUE@noinst_LTLIBRARIES = libymsg.la
--@STATIC_YAHOO_FALSE@libymsg_la_SOURCES = $(YAHOOSOURCES)
--@STATIC_YAHOO_TRUE@libymsg_la_SOURCES = $(YAHOOSOURCES) libyahoo.c libyahoojp.c
--@STATIC_YAHOO_TRUE@libymsg_la_CFLAGS = $(AM_CFLAGS)
--@STATIC_YAHOO_FALSE@pkg_LTLIBRARIES = libymsg.la libyahoo.la libyahoojp.la
--@STATIC_YAHOO_FALSE@libymsg_la_LIBADD = $(GLIB_LIBS)
--@STATIC_YAHOO_FALSE@libyahoo_la_SOURCES = libyahoo.c
--@STATIC_YAHOO_FALSE@libyahoo_la_LIBADD = libymsg.la
--@STATIC_YAHOO_FALSE@libyahoojp_la_SOURCES = libyahoojp.c
--@STATIC_YAHOO_FALSE@libyahoojp_la_LIBADD = libymsg.la
--AM_CPPFLAGS = \
-- -I$(top_srcdir)/libpurple \
-- -I$(top_builddir)/libpurple \
-- $(GLIB_CFLAGS) \
-- $(DEBUG_CFLAGS)
--
--all: all-am
--
--.SUFFIXES:
--.SUFFIXES: .c .lo .o .obj
--$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
-- @for dep in $?; do \
-- case '$(am__configure_deps)' in \
-- *$$dep*) \
-- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
-- && { if test -f $@; then exit 0; else break; fi; }; \
-- exit 1;; \
-- esac; \
-- done; \
-- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpurple/protocols/yahoo/Makefile'; \
-- $(am__cd) $(top_srcdir) && \
-- $(AUTOMAKE) --gnu libpurple/protocols/yahoo/Makefile
--.PRECIOUS: Makefile
--Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-- @case '$?' in \
-- *config.status*) \
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-- *) \
-- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-- esac;
--
--$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--
--$(top_srcdir)/configure: $(am__configure_deps)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--$(ACLOCAL_M4): $(am__aclocal_m4_deps)
-- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
--$(am__aclocal_m4_deps):
--
--clean-noinstLTLIBRARIES:
-- -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-- @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
-- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-- test "$$dir" != "$$p" || dir=.; \
-- echo "rm -f \"$${dir}/so_locations\""; \
-- rm -f "$${dir}/so_locations"; \
-- done
--install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES)
-- @$(NORMAL_INSTALL)
-- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
-- list2=; for p in $$list; do \
-- if test -f $$p; then \
-- list2="$$list2 $$p"; \
-- else :; fi; \
-- done; \
-- test -z "$$list2" || { \
-- echo " $(MKDIR_P) '$(DESTDIR)$(pkgdir)'"; \
-- $(MKDIR_P) "$(DESTDIR)$(pkgdir)" || exit 1; \
-- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgdir)'"; \
-- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgdir)"; \
-- }
--
--uninstall-pkgLTLIBRARIES:
-- @$(NORMAL_UNINSTALL)
-- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
-- for p in $$list; do \
-- $(am__strip_dir) \
-- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgdir)/$$f'"; \
-- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgdir)/$$f"; \
-- done
--
--clean-pkgLTLIBRARIES:
-- -test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES)
-- @list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
-- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
-- test "$$dir" != "$$p" || dir=.; \
-- echo "rm -f \"$${dir}/so_locations\""; \
-- rm -f "$${dir}/so_locations"; \
-- done
--libyahoo.la: $(libyahoo_la_OBJECTS) $(libyahoo_la_DEPENDENCIES) $(EXTRA_libyahoo_la_DEPENDENCIES)
-- $(AM_V_CCLD)$(libyahoo_la_LINK) $(am_libyahoo_la_rpath) $(libyahoo_la_OBJECTS) $(libyahoo_la_LIBADD) $(LIBS)
--libyahoojp.la: $(libyahoojp_la_OBJECTS) $(libyahoojp_la_DEPENDENCIES) $(EXTRA_libyahoojp_la_DEPENDENCIES)
-- $(AM_V_CCLD)$(libyahoojp_la_LINK) $(am_libyahoojp_la_rpath) $(libyahoojp_la_OBJECTS) $(libyahoojp_la_LIBADD) $(LIBS)
--libymsg.la: $(libymsg_la_OBJECTS) $(libymsg_la_DEPENDENCIES) $(EXTRA_libymsg_la_DEPENDENCIES)
-- $(AM_V_CCLD)$(libymsg_la_LINK) $(am_libymsg_la_rpath) $(libymsg_la_OBJECTS) $(libymsg_la_LIBADD) $(LIBS)
--
--mostlyclean-compile:
-- -rm -f *.$(OBJEXT)
--
--distclean-compile:
-- -rm -f *.tab.c
--
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libyahoo.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libyahoojp.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-libyahoo.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-libyahoojp.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-libymsg.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-util.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-yahoo_aliases.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-yahoo_doodle.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-yahoo_filexfer.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-yahoo_friend.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-yahoo_packet.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-yahoo_picture.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-yahoo_profile.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-yahoochat.Plo@am__quote@
--@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-ycht.Plo@am__quote@
--
--.c.o:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
--
--.c.obj:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
--
--.c.lo:
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
--
--libymsg_la-libymsg.lo: libymsg.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-libymsg.lo -MD -MP -MF $(DEPDIR)/libymsg_la-libymsg.Tpo -c -o libymsg_la-libymsg.lo `test -f 'libymsg.c' || echo '$(srcdir)/'`libymsg.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-libymsg.Tpo $(DEPDIR)/libymsg_la-libymsg.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libymsg.c' object='libymsg_la-libymsg.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-libymsg.lo `test -f 'libymsg.c' || echo '$(srcdir)/'`libymsg.c
--
--libymsg_la-util.lo: util.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-util.lo -MD -MP -MF $(DEPDIR)/libymsg_la-util.Tpo -c -o libymsg_la-util.lo `test -f 'util.c' || echo '$(srcdir)/'`util.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-util.Tpo $(DEPDIR)/libymsg_la-util.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='util.c' object='libymsg_la-util.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-util.lo `test -f 'util.c' || echo '$(srcdir)/'`util.c
--
--libymsg_la-yahoochat.lo: yahoochat.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-yahoochat.lo -MD -MP -MF $(DEPDIR)/libymsg_la-yahoochat.Tpo -c -o libymsg_la-yahoochat.lo `test -f 'yahoochat.c' || echo '$(srcdir)/'`yahoochat.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-yahoochat.Tpo $(DEPDIR)/libymsg_la-yahoochat.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='yahoochat.c' object='libymsg_la-yahoochat.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-yahoochat.lo `test -f 'yahoochat.c' || echo '$(srcdir)/'`yahoochat.c
--
--libymsg_la-yahoo_aliases.lo: yahoo_aliases.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-yahoo_aliases.lo -MD -MP -MF $(DEPDIR)/libymsg_la-yahoo_aliases.Tpo -c -o libymsg_la-yahoo_aliases.lo `test -f 'yahoo_aliases.c' || echo '$(srcdir)/'`yahoo_aliases.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-yahoo_aliases.Tpo $(DEPDIR)/libymsg_la-yahoo_aliases.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='yahoo_aliases.c' object='libymsg_la-yahoo_aliases.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-yahoo_aliases.lo `test -f 'yahoo_aliases.c' || echo '$(srcdir)/'`yahoo_aliases.c
--
--libymsg_la-yahoo_doodle.lo: yahoo_doodle.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-yahoo_doodle.lo -MD -MP -MF $(DEPDIR)/libymsg_la-yahoo_doodle.Tpo -c -o libymsg_la-yahoo_doodle.lo `test -f 'yahoo_doodle.c' || echo '$(srcdir)/'`yahoo_doodle.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-yahoo_doodle.Tpo $(DEPDIR)/libymsg_la-yahoo_doodle.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='yahoo_doodle.c' object='libymsg_la-yahoo_doodle.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-yahoo_doodle.lo `test -f 'yahoo_doodle.c' || echo '$(srcdir)/'`yahoo_doodle.c
--
--libymsg_la-yahoo_filexfer.lo: yahoo_filexfer.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-yahoo_filexfer.lo -MD -MP -MF $(DEPDIR)/libymsg_la-yahoo_filexfer.Tpo -c -o libymsg_la-yahoo_filexfer.lo `test -f 'yahoo_filexfer.c' || echo '$(srcdir)/'`yahoo_filexfer.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-yahoo_filexfer.Tpo $(DEPDIR)/libymsg_la-yahoo_filexfer.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='yahoo_filexfer.c' object='libymsg_la-yahoo_filexfer.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-yahoo_filexfer.lo `test -f 'yahoo_filexfer.c' || echo '$(srcdir)/'`yahoo_filexfer.c
--
--libymsg_la-yahoo_friend.lo: yahoo_friend.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-yahoo_friend.lo -MD -MP -MF $(DEPDIR)/libymsg_la-yahoo_friend.Tpo -c -o libymsg_la-yahoo_friend.lo `test -f 'yahoo_friend.c' || echo '$(srcdir)/'`yahoo_friend.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-yahoo_friend.Tpo $(DEPDIR)/libymsg_la-yahoo_friend.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='yahoo_friend.c' object='libymsg_la-yahoo_friend.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-yahoo_friend.lo `test -f 'yahoo_friend.c' || echo '$(srcdir)/'`yahoo_friend.c
--
--libymsg_la-yahoo_packet.lo: yahoo_packet.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-yahoo_packet.lo -MD -MP -MF $(DEPDIR)/libymsg_la-yahoo_packet.Tpo -c -o libymsg_la-yahoo_packet.lo `test -f 'yahoo_packet.c' || echo '$(srcdir)/'`yahoo_packet.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-yahoo_packet.Tpo $(DEPDIR)/libymsg_la-yahoo_packet.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='yahoo_packet.c' object='libymsg_la-yahoo_packet.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-yahoo_packet.lo `test -f 'yahoo_packet.c' || echo '$(srcdir)/'`yahoo_packet.c
--
--libymsg_la-yahoo_picture.lo: yahoo_picture.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-yahoo_picture.lo -MD -MP -MF $(DEPDIR)/libymsg_la-yahoo_picture.Tpo -c -o libymsg_la-yahoo_picture.lo `test -f 'yahoo_picture.c' || echo '$(srcdir)/'`yahoo_picture.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-yahoo_picture.Tpo $(DEPDIR)/libymsg_la-yahoo_picture.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='yahoo_picture.c' object='libymsg_la-yahoo_picture.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-yahoo_picture.lo `test -f 'yahoo_picture.c' || echo '$(srcdir)/'`yahoo_picture.c
--
--libymsg_la-yahoo_profile.lo: yahoo_profile.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-yahoo_profile.lo -MD -MP -MF $(DEPDIR)/libymsg_la-yahoo_profile.Tpo -c -o libymsg_la-yahoo_profile.lo `test -f 'yahoo_profile.c' || echo '$(srcdir)/'`yahoo_profile.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-yahoo_profile.Tpo $(DEPDIR)/libymsg_la-yahoo_profile.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='yahoo_profile.c' object='libymsg_la-yahoo_profile.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-yahoo_profile.lo `test -f 'yahoo_profile.c' || echo '$(srcdir)/'`yahoo_profile.c
--
--libymsg_la-ycht.lo: ycht.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-ycht.lo -MD -MP -MF $(DEPDIR)/libymsg_la-ycht.Tpo -c -o libymsg_la-ycht.lo `test -f 'ycht.c' || echo '$(srcdir)/'`ycht.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-ycht.Tpo $(DEPDIR)/libymsg_la-ycht.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ycht.c' object='libymsg_la-ycht.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-ycht.lo `test -f 'ycht.c' || echo '$(srcdir)/'`ycht.c
--
--libymsg_la-libyahoo.lo: libyahoo.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-libyahoo.lo -MD -MP -MF $(DEPDIR)/libymsg_la-libyahoo.Tpo -c -o libymsg_la-libyahoo.lo `test -f 'libyahoo.c' || echo '$(srcdir)/'`libyahoo.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-libyahoo.Tpo $(DEPDIR)/libymsg_la-libyahoo.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libyahoo.c' object='libymsg_la-libyahoo.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-libyahoo.lo `test -f 'libyahoo.c' || echo '$(srcdir)/'`libyahoo.c
--
--libymsg_la-libyahoojp.lo: libyahoojp.c
--@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-libyahoojp.lo -MD -MP -MF $(DEPDIR)/libymsg_la-libyahoojp.Tpo -c -o libymsg_la-libyahoojp.lo `test -f 'libyahoojp.c' || echo '$(srcdir)/'`libyahoojp.c
--@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-libyahoojp.Tpo $(DEPDIR)/libymsg_la-libyahoojp.Plo
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libyahoojp.c' object='libymsg_la-libyahoojp.lo' libtool=yes @AMDEPBACKSLASH@
--@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
--@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-libyahoojp.lo `test -f 'libyahoojp.c' || echo '$(srcdir)/'`libyahoojp.c
--
--mostlyclean-libtool:
-- -rm -f *.lo
--
--clean-libtool:
-- -rm -rf .libs _libs
--
--ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- mkid -fID $$unique
--tags: TAGS
--
--TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
-- $(TAGS_FILES) $(LISP)
-- set x; \
-- here=`pwd`; \
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- shift; \
-- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-- test -n "$$unique" || unique=$$empty_fix; \
-- if test $$# -gt 0; then \
-- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-- "$$@" $$unique; \
-- else \
-- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-- $$unique; \
-- fi; \
-- fi
--ctags: CTAGS
--CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
-- $(TAGS_FILES) $(LISP)
-- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
-- unique=`for i in $$list; do \
-- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-- done | \
-- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
-- END { if (nonempty) { for (i in files) print i; }; }'`; \
-- test -z "$(CTAGS_ARGS)$$unique" \
-- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-- $$unique
--
--GTAGS:
-- here=`$(am__cd) $(top_builddir) && pwd` \
-- && $(am__cd) $(top_srcdir) \
-- && gtags -i $(GTAGS_ARGS) "$$here"
--
--distclean-tags:
-- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
--
--distdir: $(DISTFILES)
-- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-- list='$(DISTFILES)'; \
-- dist_files=`for file in $$list; do echo $$file; done | \
-- sed -e "s|^$$srcdirstrip/||;t" \
-- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-- case $$dist_files in \
-- */*) $(MKDIR_P) `echo "$$dist_files" | \
-- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-- sort -u` ;; \
-- esac; \
-- for file in $$dist_files; do \
-- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-- if test -d $$d/$$file; then \
-- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-- if test -d "$(distdir)/$$file"; then \
-- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-- fi; \
-- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-- fi; \
-- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-- else \
-- test -f "$(distdir)/$$file" \
-- || cp -p $$d/$$file "$(distdir)/$$file" \
-- || exit 1; \
-- fi; \
-- done
--check-am: all-am
--check: check-am
--all-am: Makefile $(LTLIBRARIES)
--installdirs:
-- for dir in "$(DESTDIR)$(pkgdir)"; do \
-- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
-- done
--install: install-am
--install-exec: install-exec-am
--install-data: install-data-am
--uninstall: uninstall-am
--
--install-am: all-am
-- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
--
--installcheck: installcheck-am
--install-strip:
-- if test -z '$(STRIP)'; then \
-- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-- install; \
-- else \
-- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-- fi
--mostlyclean-generic:
--
--clean-generic:
--
--distclean-generic:
-- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
--
--maintainer-clean-generic:
-- @echo "This command is intended for maintainers to use"
-- @echo "it deletes files that may require special tools to rebuild."
--clean: clean-am
--
--clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
-- clean-pkgLTLIBRARIES mostlyclean-am
--
--distclean: distclean-am
-- -rm -rf ./$(DEPDIR)
-- -rm -f Makefile
--distclean-am: clean-am distclean-compile distclean-generic \
-- distclean-tags
--
--dvi: dvi-am
--
--dvi-am:
--
--html: html-am
--
--html-am:
--
--info: info-am
--
--info-am:
--
--install-data-am: install-pkgLTLIBRARIES
--
--install-dvi: install-dvi-am
--
--install-dvi-am:
--
--install-exec-am:
--
--install-html: install-html-am
--
--install-html-am:
--
--install-info: install-info-am
--
--install-info-am:
--
--install-man:
--
--install-pdf: install-pdf-am
--
--install-pdf-am:
--
--install-ps: install-ps-am
--
--install-ps-am:
--
--installcheck-am:
--
--maintainer-clean: maintainer-clean-am
-- -rm -rf ./$(DEPDIR)
-- -rm -f Makefile
--maintainer-clean-am: distclean-am maintainer-clean-generic
--
--mostlyclean: mostlyclean-am
--
--mostlyclean-am: mostlyclean-compile mostlyclean-generic \
-- mostlyclean-libtool
--
--pdf: pdf-am
--
--pdf-am:
--
--ps: ps-am
--
--ps-am:
--
--uninstall-am: uninstall-pkgLTLIBRARIES
--
--.MAKE: install-am install-strip
--
--.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
-- clean-libtool clean-noinstLTLIBRARIES clean-pkgLTLIBRARIES \
-- ctags distclean distclean-compile distclean-generic \
-- distclean-libtool distclean-tags distdir dvi dvi-am html \
-- html-am info info-am install install-am install-data \
-- install-data-am install-dvi install-dvi-am install-exec \
-- install-exec-am install-html install-html-am install-info \
-- install-info-am install-man install-pdf install-pdf-am \
-- install-pkgLTLIBRARIES install-ps install-ps-am install-strip \
-- installcheck installcheck-am installdirs maintainer-clean \
-- maintainer-clean-generic mostlyclean mostlyclean-compile \
-- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-- tags uninstall uninstall-am uninstall-pkgLTLIBRARIES
--
--
--# Tell versions [3.59,3.63) of GNU make to not export all variables.
--# Otherwise a system limit (for SysV at least) may be exceeded.
--.NOEXPORT:
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/Makefile.mingw
---- pidgin-2.10.7/libpurple/protocols/yahoo/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,105 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of libyahoo
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = libymsg
--YAHOO_TARGET = libyahoo
--YAHOOJP_TARGET = libyahoojp
--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)
--
--LIB_PATHS += -L. \
-- -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = util.c \
-- libymsg.c \
-- yahoochat.c \
-- yahoo_aliases.c \
-- yahoo_doodle.c \
-- yahoo_filexfer.c \
-- yahoo_friend.c \
-- yahoo_packet.c \
-- yahoo_picture.c \
-- yahoo_profile.c \
-- ycht.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--YAHOO_C_SRC = libyahoo.c
--YAHOO_OBJECTS = $(YAHOO_C_SRC:%.c=%.o)
--
--YAHOOJP_C_SRC = libyahoojp.c
--YAHOOJP_OBJECTS = $(YAHOOJP_C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = \
-- -lglib-2.0 \
-- -lws2_32 \
-- -lintl \
-- -lpurple
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--
--.PHONY: all install clean
--
--all: $(TARGET).dll $(YAHOO_TARGET).dll $(YAHOOJP_TARGET).dll
--
--install: all $(DLL_INSTALL_DIR)
-- cp $(YAHOO_TARGET).dll $(YAHOOJP_TARGET).dll $(DLL_INSTALL_DIR)
-- cp $(TARGET).dll $(PURPLE_INSTALL_DIR)
--
--$(OBJECTS): $(PURPLE_CONFIG_H)
--
--$(TARGET).dll.a $(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--output-def,$(TARGET).def,--out-implib,$(TARGET).dll.a -o $(TARGET).dll
--
--$(YAHOO_TARGET).dll: $(TARGET).dll.a $(YAHOO_OBJECTS)
-- $(CC) -shared $(YAHOO_OBJECTS) $(LIB_PATHS) $(LIBS) -lymsg $(DLL_LD_FLAGS) -o $(YAHOO_TARGET).dll
--
--$(YAHOOJP_TARGET).dll: $(TARGET).dll.a $(YAHOOJP_OBJECTS)
-- $(CC) -shared $(YAHOOJP_OBJECTS) $(LIB_PATHS) $(LIBS) -lymsg $(DLL_LD_FLAGS) -o $(YAHOOJP_TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -f $(OBJECTS) $(TARGET).dll $(TARGET).dll.a
-- rm -f $(YAHOO_OBJECTS) $(YAHOO_TARGET).dll
-- rm -f $(YAHOOJP_OBJECTS) $(YAHOOJP_TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/util.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/util.c
---- pidgin-2.10.7/libpurple/protocols/yahoo/util.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/util.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,951 +0,0 @@
--/*
-- * purple
-- *
-- * Some code copyright 2003 Tim Ringenbach <omarvo@hotmail.com>
-- * (marv on irc.freenode.net)
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#ifdef HAVE_CONFIG_H
--#include "config.h"
--#endif /* HAVE_CONFIG_H */
--
--#include "debug.h"
--#include "internal.h"
--#include "prpl.h"
--
--#include "libymsg.h"
--
--#include <string.h>
--
--gboolean
--yahoo_account_use_http_proxy(PurpleConnection *pc)
--{
-- PurpleAccount *account = purple_connection_get_account(pc);
-- PurpleProxyInfo *ppi = NULL;
-- PurpleProxyType type = PURPLE_PROXY_NONE;
-- gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE);
--
-- if(proxy_ssl)
-- ppi = purple_proxy_get_setup(account);
-- else
-- ppi = purple_proxy_get_setup(NULL);
--
-- type = purple_proxy_info_get_type(ppi);
--
-- return (type == PURPLE_PROXY_HTTP || type == PURPLE_PROXY_USE_ENVVAR);
--}
--
--/*
-- * Returns cookies formatted as a null terminated string for the given connection.
-- * Must g_free return value.
-- *
-- * TODO:will work, but must test for strict correctness
-- */
--gchar* yahoo_get_cookies(PurpleConnection *gc)
--{
-- gchar *ans = NULL;
-- gchar *cur;
-- char firstflag = 1;
-- gchar *t1,*t2,*t3;
-- GSList *tmp;
-- GSList *cookies;
-- cookies = ((YahooData*)(gc->proto_data))->cookies;
-- tmp = cookies;
-- while(tmp)
-- {
-- cur = tmp->data;
-- t1 = ans;
-- t2 = g_strrstr(cur, ";expires=");
-- if(t2 == NULL)
-- t2 = g_strrstr(cur, "; expires=");
-- if(t2 == NULL)
-- {
-- if(firstflag)
-- ans = g_strdup_printf("%c=%s", cur[0], cur+2);
-- else
-- ans = g_strdup_printf("%s; %c=%s", t1, cur[0], cur+2);
-- }
-- else
-- {
-- t3 = strstr(t2+1, ";");
-- if(t3 != NULL)
-- {
-- t2[0] = '\0';
--
-- if(firstflag)
-- ans = g_strdup_printf("%c=%s%s", cur[0], cur+2, t3);
-- else
-- ans = g_strdup_printf("%s; %c=%s%s", t1, cur[0], cur+2, t3);
--
-- t2[0] = ';';
-- }
-- else
-- {
-- t2[0] = '\0';
--
-- if(firstflag)
-- ans = g_strdup_printf("%c=%s", cur[0], cur+2);
-- else
-- ans = g_strdup_printf("%s; %c=%s", t1, cur[0], cur+2);
--
-- t2[0] = ';';
-- }
-- }
-- if(firstflag)
-- firstflag = 0;
-- else
-- g_free(t1);
-- tmp = g_slist_next(tmp);
-- }
-- return ans;
--}
--
--/**
-- * Encode some text to send to the yahoo server.
-- *
-- * @param gc The connection handle.
-- * @param str The null terminated utf8 string to encode.
-- * @param utf8 If not @c NULL, whether utf8 is okay or not.
-- * Even if it is okay, we may not use it. If we
-- * used it, we set this to @c TRUE, else to
-- * @c FALSE. If @c NULL, false is assumed, and
-- * it is not dereferenced.
-- * @return The g_malloced string in the appropriate encoding.
-- */
--char *yahoo_string_encode(PurpleConnection *gc, const char *str, gboolean *utf8)
--{
-- YahooData *yd = gc->proto_data;
-- char *ret;
-- const char *to_codeset;
--
-- if (yd->jp)
-- return g_strdup(str);
--
-- if (utf8 && *utf8) /* FIXME: maybe don't use utf8 if it'll fit in latin1 */
-- return g_strdup(str);
--
-- to_codeset = purple_account_get_string(purple_connection_get_account(gc), "local_charset", "ISO-8859-1");
-- ret = g_convert_with_fallback(str, -1, to_codeset, "UTF-8", "?", NULL, NULL, NULL);
--
-- if (ret)
-- return ret;
-- else
-- return g_strdup("");
--}
--
--/**
-- * Decode some text received from the server.
-- *
-- * @param gc The gc handle.
-- * @param str The null terminated string to decode.
-- * @param utf8 Did the server tell us it was supposed to be utf8?
-- * @return The decoded, utf-8 string, which must be g_free()'d.
-- */
--char *yahoo_string_decode(PurpleConnection *gc, const char *str, gboolean utf8)
--{
-- YahooData *yd = gc->proto_data;
-- char *ret;
-- const char *from_codeset;
--
-- if (utf8) {
-- if (g_utf8_validate(str, -1, NULL))
-- return g_strdup(str);
-- }
--
-- if (yd->jp)
-- from_codeset = "SHIFT_JIS";
-- else
-- from_codeset = purple_account_get_string(purple_connection_get_account(gc), "local_charset", "ISO-8859-1");
--
-- ret = g_convert_with_fallback(str, -1, "UTF-8", from_codeset, NULL, NULL, NULL, NULL);
--
-- if (ret)
-- return ret;
-- else
-- return g_strdup("");
--}
--
--char *yahoo_convert_to_numeric(const char *str)
--{
-- GString *gstr = NULL;
-- const unsigned char *p;
--
-- gstr = g_string_sized_new(strlen(str) * 6 + 1);
--
-- for (p = (unsigned char *)str; *p; p++) {
-- g_string_append_printf(gstr, "&#%u;", *p);
-- }
--
-- return g_string_free(gstr, FALSE);
--}
--
--/*
-- * The values in this hash table should probably be lowercase, since that's
-- * what xhtml expects. Also because yahoo_codes_to_html() does
-- * case-sensitive comparisons.
-- *
-- * I found these on some website but i don't know that they actually
-- * work (or are supposed to work). I didn't implement them yet.
-- *
-- * [0;30m ---black
-- * [1;37m ---white
-- * [0;37m ---tan
-- * [0;38m ---light black
-- * [1;39m ---dark blue
-- * [0;32m ---green
-- * [0;33m ---yellow
-- * [0;35m ---pink
-- * [1;35m ---purple
-- * [1;30m ---light blue
-- * [0;31m ---red
-- * [0;34m ---blue
-- * [0;36m ---aqua
-- * (shift+comma)lyellow(shift+period) ---light yellow
-- * (shift+comma)lgreen(shift+period) ---light green
-- * [2;30m <--white out
-- */
--
--static GHashTable *esc_codes_ht = NULL;
--static GHashTable *tags_ht = NULL;
--
--void yahoo_init_colorht()
--{
-- if (esc_codes_ht != NULL)
-- /* Hash table has already been initialized */
-- return;
--
-- /* Key is the escape code string. Value is the HTML that should be
-- * inserted in place of the escape code. */
-- esc_codes_ht = g_hash_table_new(g_str_hash, g_str_equal);
--
-- /* Key is the name of the HTML tag, for example "font" or "/font"
-- * value is the HTML that should be inserted in place of the old tag */
-- tags_ht = g_hash_table_new(g_str_hash, g_str_equal);
--
-- /* the numbers in comments are what gyach uses, but i think they're incorrect */
--#ifdef USE_CSS_FORMATTING
-- g_hash_table_insert(esc_codes_ht, "30", "<span style=\"color: #000000\">"); /* black */
-- g_hash_table_insert(esc_codes_ht, "31", "<span style=\"color: #0000FF\">"); /* blue */
-- g_hash_table_insert(esc_codes_ht, "32", "<span style=\"color: #008080\">"); /* cyan */ /* 00b2b2 */
-- g_hash_table_insert(esc_codes_ht, "33", "<span style=\"color: #808080\">"); /* gray */ /* 808080 */
-- g_hash_table_insert(esc_codes_ht, "34", "<span style=\"color: #008000\">"); /* green */ /* 00c200 */
-- g_hash_table_insert(esc_codes_ht, "35", "<span style=\"color: #FF0080\">"); /* pink */ /* ffafaf */
-- g_hash_table_insert(esc_codes_ht, "36", "<span style=\"color: #800080\">"); /* purple */ /* b200b2 */
-- g_hash_table_insert(esc_codes_ht, "37", "<span style=\"color: #FF8000\">"); /* orange */ /* ffff00 */
-- g_hash_table_insert(esc_codes_ht, "38", "<span style=\"color: #FF0000\">"); /* red */
-- g_hash_table_insert(esc_codes_ht, "39", "<span style=\"color: #808000\">"); /* olive */ /* 546b50 */
--#else
-- g_hash_table_insert(esc_codes_ht, "30", "<font color=\"#000000\">"); /* black */
-- g_hash_table_insert(esc_codes_ht, "31", "<font color=\"#0000FF\">"); /* blue */
-- g_hash_table_insert(esc_codes_ht, "32", "<font color=\"#008080\">"); /* cyan */ /* 00b2b2 */
-- g_hash_table_insert(esc_codes_ht, "33", "<font color=\"#808080\">"); /* gray */ /* 808080 */
-- g_hash_table_insert(esc_codes_ht, "34", "<font color=\"#008000\">"); /* green */ /* 00c200 */
-- g_hash_table_insert(esc_codes_ht, "35", "<font color=\"#FF0080\">"); /* pink */ /* ffafaf */
-- g_hash_table_insert(esc_codes_ht, "36", "<font color=\"#800080\">"); /* purple */ /* b200b2 */
-- g_hash_table_insert(esc_codes_ht, "37", "<font color=\"#FF8000\">"); /* orange */ /* ffff00 */
-- g_hash_table_insert(esc_codes_ht, "38", "<font color=\"#FF0000\">"); /* red */
-- g_hash_table_insert(esc_codes_ht, "39", "<font color=\"#808000\">"); /* olive */ /* 546b50 */
--#endif /* !USE_CSS_FORMATTING */
--
-- g_hash_table_insert(esc_codes_ht, "1", "<b>");
-- g_hash_table_insert(esc_codes_ht, "x1", "</b>");
-- g_hash_table_insert(esc_codes_ht, "2", "<i>");
-- g_hash_table_insert(esc_codes_ht, "x2", "</i>");
-- g_hash_table_insert(esc_codes_ht, "4", "<u>");
-- g_hash_table_insert(esc_codes_ht, "x4", "</u>");
--
-- /* these just tell us the text they surround is supposed
-- * to be a link. purple figures that out on its own so we
-- * just ignore it.
-- */
-- g_hash_table_insert(esc_codes_ht, "l", ""); /* link start */
-- g_hash_table_insert(esc_codes_ht, "xl", ""); /* link end */
--
--#ifdef USE_CSS_FORMATTING
-- g_hash_table_insert(tags_ht, "black", "<span style=\"color: #000000\">");
-- g_hash_table_insert(tags_ht, "blue", "<span style=\"color: #0000FF\">");
-- g_hash_table_insert(tags_ht, "cyan", "<span style=\"color: #008284\">");
-- g_hash_table_insert(tags_ht, "gray", "<span style=\"color: #848284\">");
-- g_hash_table_insert(tags_ht, "green", "<span style=\"color: #008200\">");
-- g_hash_table_insert(tags_ht, "pink", "<span style=\"color: #FF0084\">");
-- g_hash_table_insert(tags_ht, "purple", "<span style=\"color: #840084\">");
-- g_hash_table_insert(tags_ht, "orange", "<span style=\"color: #FF8000\">");
-- g_hash_table_insert(tags_ht, "red", "<span style=\"color: #FF0000\">");
-- g_hash_table_insert(tags_ht, "yellow", "<span style=\"color: #848200\">");
--
-- g_hash_table_insert(tags_ht, "/black", "</span>");
-- g_hash_table_insert(tags_ht, "/blue", "</span>");
-- g_hash_table_insert(tags_ht, "/cyan", "</span>");
-- g_hash_table_insert(tags_ht, "/gray", "</span>");
-- g_hash_table_insert(tags_ht, "/green", "</span>");
-- g_hash_table_insert(tags_ht, "/pink", "</span>");
-- g_hash_table_insert(tags_ht, "/purple", "</span>");
-- g_hash_table_insert(tags_ht, "/orange", "</span>");
-- g_hash_table_insert(tags_ht, "/red", "</span>");
-- g_hash_table_insert(tags_ht, "/yellow", "</span>");
--#else
-- g_hash_table_insert(tags_ht, "black", "<font color=\"#000000\">");
-- g_hash_table_insert(tags_ht, "blue", "<font color=\"#0000FF\">");
-- g_hash_table_insert(tags_ht, "cyan", "<font color=\"#008284\">");
-- g_hash_table_insert(tags_ht, "gray", "<font color=\"#848284\">");
-- g_hash_table_insert(tags_ht, "green", "<font color=\"#008200\">");
-- g_hash_table_insert(tags_ht, "pink", "<font color=\"#FF0084\">");
-- g_hash_table_insert(tags_ht, "purple", "<font color=\"#840084\">");
-- g_hash_table_insert(tags_ht, "orange", "<font color=\"#FF8000\">");
-- g_hash_table_insert(tags_ht, "red", "<font color=\"#FF0000\">");
-- g_hash_table_insert(tags_ht, "yellow", "<font color=\"#848200\">");
--
-- g_hash_table_insert(tags_ht, "/black", "</font>");
-- g_hash_table_insert(tags_ht, "/blue", "</font>");
-- g_hash_table_insert(tags_ht, "/cyan", "</font>");
-- g_hash_table_insert(tags_ht, "/gray", "</font>");
-- g_hash_table_insert(tags_ht, "/green", "</font>");
-- g_hash_table_insert(tags_ht, "/pink", "</font>");
-- g_hash_table_insert(tags_ht, "/purple", "</font>");
-- g_hash_table_insert(tags_ht, "/orange", "</font>");
-- g_hash_table_insert(tags_ht, "/red", "</font>");
-- g_hash_table_insert(tags_ht, "/yellow", "</font>");
--#endif /* !USE_CSS_FORMATTING */
--
-- /* We don't support these tags, so discard them */
-- g_hash_table_insert(tags_ht, "alt", "");
-- g_hash_table_insert(tags_ht, "fade", "");
-- g_hash_table_insert(tags_ht, "snd", "");
-- g_hash_table_insert(tags_ht, "/alt", "");
-- g_hash_table_insert(tags_ht, "/fade", "");
--
-- /* Official clients don't seem to send b, i or u tags. They use
-- * the escape codes listed above. Official clients definitely send
-- * font tags, though. I wonder if we can remove the opening and
-- * closing b, i and u tags from here? */
-- g_hash_table_insert(tags_ht, "b", "<b>");
-- g_hash_table_insert(tags_ht, "i", "<i>");
-- g_hash_table_insert(tags_ht, "u", "<u>");
-- g_hash_table_insert(tags_ht, "font", "<font>");
--
-- g_hash_table_insert(tags_ht, "/b", "</b>");
-- g_hash_table_insert(tags_ht, "/i", "</i>");
-- g_hash_table_insert(tags_ht, "/u", "</u>");
-- g_hash_table_insert(tags_ht, "/font", "</font>");
--}
--
--void yahoo_dest_colorht()
--{
-- if (esc_codes_ht == NULL)
-- /* Hash table has already been destroyed */
-- return;
--
-- g_hash_table_destroy(esc_codes_ht);
-- esc_codes_ht = NULL;
-- g_hash_table_destroy(tags_ht);
-- tags_ht = NULL;
--}
--
--#ifndef USE_CSS_FORMATTING
--static int point_to_html(int x)
--{
-- if (x < 9)
-- return 1;
-- if (x < 11)
-- return 2;
-- if (x < 13)
-- return 3;
-- if (x < 17)
-- return 4;
-- if (x < 25)
-- return 5;
-- if (x < 35)
-- return 6;
-- return 7;
--}
--#endif /* !USE_CSS_FORMATTING */
--
--static void append_attrs_datalist_foreach_cb(GQuark key_id, gpointer data, gpointer user_data)
--{
-- const char *key;
-- const char *value;
-- xmlnode *cur;
--
-- key = g_quark_to_string(key_id);
-- value = data;
-- cur = user_data;
--
-- xmlnode_set_attrib(cur, key, value);
--}
--
--/**
-- * @param cur A pointer to the position in the XML tree that we're
-- * currently building. This will be modified when opening a tag
-- * or closing an existing tag.
-- */
--static void yahoo_codes_to_html_add_tag(xmlnode **cur, const char *tag, gboolean is_closing_tag, const gchar *tag_name, gboolean is_font_tag)
--{
-- if (is_closing_tag) {
-- xmlnode *tmp;
-- GSList *dangling_tags = NULL;
--
-- /* Move up the DOM until we find the opening tag */
-- for (tmp = *cur; tmp != NULL; tmp = xmlnode_get_parent(tmp)) {
-- /* Add one to tag_name when doing this comparison because it starts with a / */
-- if (g_str_equal(tmp->name, tag_name + 1))
-- /* Found */
-- break;
-- dangling_tags = g_slist_prepend(dangling_tags, tmp);
-- }
-- if (tmp == NULL) {
-- /* This is a closing tag with no opening tag. Useless. */
-- purple_debug_error("yahoo", "Ignoring unmatched tag %s", tag);
-- g_slist_free(dangling_tags);
-- return;
-- }
--
-- /* Move our current position up, now that we've closed a tag */
-- *cur = xmlnode_get_parent(tmp);
--
-- /* Re-open any tags that were nested below the tag we just closed */
-- while (dangling_tags != NULL) {
-- tmp = dangling_tags->data;
-- dangling_tags = g_slist_delete_link(dangling_tags, dangling_tags);
--
-- /* Create a copy of this tag+attributes (but not child tags or
-- * data) at our new location */
-- *cur = xmlnode_new_child(*cur, tmp->name);
-- for (tmp = tmp->child; tmp != NULL; tmp = tmp->next)
-- if (tmp->type == XMLNODE_TYPE_ATTRIB)
-- xmlnode_set_attrib_full(*cur, tmp->name,
-- tmp->xmlns, tmp->prefix, tmp->data);
-- }
-- } else {
-- const char *start;
-- const char *end;
-- GData *attributes;
-- char *fontsize = NULL;
--
-- purple_markup_find_tag(tag_name, tag, &start, &end, &attributes);
-- *cur = xmlnode_new_child(*cur, tag_name);
--
-- if (is_font_tag) {
-- /* Special case for the font size attribute */
-- fontsize = g_strdup(g_datalist_get_data(&attributes, "size"));
-- if (fontsize != NULL)
-- g_datalist_remove_data(&attributes, "size");
-- }
--
-- /* Add all font tag attributes */
-- g_datalist_foreach(&attributes, append_attrs_datalist_foreach_cb, *cur);
-- g_datalist_clear(&attributes);
--
-- if (fontsize != NULL) {
--#ifdef USE_CSS_FORMATTING
-- /*
-- * The Yahoo font size value is given in pt, even though the HTML
-- * standard for <font size="x"> treats the size as a number on a
-- * scale between 1 and 7. So we insert the font size as a CSS
-- * style on a span tag.
-- */
-- gchar *tmp = g_strdup_printf("font-size: %spt", fontsize);
-- *cur = xmlnode_new_child(*cur, "span");
-- xmlnode_set_attrib(*cur, "style", tmp);
-- g_free(tmp);
--#else
-- /*
-- * The Yahoo font size value is given in pt, even though the HTML
-- * standard for <font size="x"> treats the size as a number on a
-- * scale between 1 and 7. So we convert it to an appropriate
-- * value. This loses precision, which is why CSS formatting is
-- * preferred. The "absz" attribute remains here for backward
-- * compatibility with UIs that might use it, but it is totally
-- * not standard at all.
-- */
-- int size, htmlsize;
-- gchar tmp[11];
-- size = strtol(fontsize, NULL, 10);
-- htmlsize = point_to_html(size);
-- sprintf(tmp, "%u", htmlsize);
-- xmlnode_set_attrib(*cur, "size", tmp);
-- xmlnode_set_attrib(*cur, "absz", fontsize);
--#endif /* !USE_CSS_FORMATTING */
-- g_free(fontsize);
-- }
-- }
--}
--
--/**
-- * Similar to purple_markup_get_tag_name(), but works with closing tags.
-- *
-- * @return The lowercase name of the tag. If this is a closing tag then
-- * this value starts with a forward slash. The caller must free
-- * this string with g_free.
-- */
--static gchar *yahoo_markup_get_tag_name(const char *tag, gboolean *is_closing_tag)
--{
-- size_t len;
--
-- *is_closing_tag = (tag[1] == '/');
-- if (*is_closing_tag)
-- len = strcspn(tag + 1, "> ");
-- else
-- len = strcspn(tag + 1, "> /");
--
-- return g_utf8_strdown(tag + 1, len);
--}
--
--/*
-- * Yahoo! messages generally aren't well-formed. Their markup is
-- * more of a flow from start to finish rather than a hierarchy from
-- * outer to inner. They tend to open tags and close them only when
-- * necessary.
-- *
-- * Example: <font size="8">size 8 <font size="16">size 16 <font size="8">size 8 again
-- *
-- * But we want to send well-formed HTML to the core, so we step through
-- * the input string and build an xmlnode tree containing sanitized HTML.
-- */
--char *yahoo_codes_to_html(const char *x)
--{
-- size_t x_len;
-- xmlnode *html, *cur;
-- GString *cdata = g_string_new(NULL);
-- int i, j;
-- gboolean no_more_gt_brackets = FALSE;
-- const char *match;
-- gchar *xmlstr1, *xmlstr2, *esc;
--
-- x_len = strlen(x);
-- html = xmlnode_new("html");
--
-- cur = html;
-- for (i = 0; i < x_len; i++) {
-- if ((x[i] == 0x1b) && (x[i+1] == '[')) {
-- /* This escape sequence signifies the beginning of some
-- * text formatting code */
-- j = i + 1;
--
-- while (j++ < x_len) {
-- gchar *code;
--
-- if (x[j] != 'm')
-- /* Keep looking for the end of this sequence */
-- continue;
--
-- /* We've reached the end of the formatting sequence, yay */
--
-- /* Append any character data that belongs in the current node */
-- if (cdata->len > 0) {
-- xmlnode_insert_data(cur, cdata->str, cdata->len);
-- g_string_truncate(cdata, 0);
-- }
--
-- code = g_strndup(x + i + 2, j - i - 2);
-- if (code[0] == '#') {
--#ifdef USE_CSS_FORMATTING
-- gchar *tmp = g_strdup_printf("color: %s", code);
-- cur = xmlnode_new_child(cur, "span");
-- xmlnode_set_attrib(cur, "style", tmp);
-- g_free(tmp);
--#else
-- cur = xmlnode_new_child(cur, "font");
-- xmlnode_set_attrib(cur, "color", code);
--#endif /* !USE_CSS_FORMATTING */
--
-- } else if ((match = g_hash_table_lookup(esc_codes_ht, code))) {
-- /* Some tags are in the hash table only because we
-- * want to ignore them */
-- if (match[0] != '\0') {
-- gboolean is_closing_tag;
-- gchar *tag_name;
-- tag_name = yahoo_markup_get_tag_name(match, &is_closing_tag);
-- yahoo_codes_to_html_add_tag(&cur, match, is_closing_tag, tag_name, FALSE);
-- g_free(tag_name);
-- }
--
-- } else {
-- purple_debug_error("yahoo",
-- "Ignoring unknown ansi code 'ESC[%sm'.\n", code);
-- }
--
-- g_free(code);
-- i = j;
-- break;
-- }
--
-- } else if (x[i] == '<' && !no_more_gt_brackets) {
-- /* The start of an HTML tag */
-- j = i;
--
-- while (j++ < x_len) {
-- gchar *tag;
-- gboolean is_closing_tag;
-- gchar *tag_name;
--
-- if (x[j] != '>') {
-- if (x[j] == '"') {
-- /* We're inside a quoted attribute value. Skip to the end */
-- j++;
-- while (j != x_len && x[j] != '"')
-- j++;
-- } else if (x[j] == '\'') {
-- /* We're inside a quoted attribute value. Skip to the end */
-- j++;
-- while (j != x_len && x[j] != '\'')
-- j++;
-- }
-- if (j != x_len)
-- /* Keep looking for the end of this tag */
-- continue;
--
-- /* This < has no corresponding > */
-- g_string_append_c(cdata, x[i]);
-- no_more_gt_brackets = TRUE;
-- break;
-- }
--
-- tag = g_strndup(x + i, j - i + 1);
-- tag_name = yahoo_markup_get_tag_name(tag, &is_closing_tag);
--
-- match = g_hash_table_lookup(tags_ht, tag_name);
-- if (match == NULL) {
-- /* Unknown tag. The user probably typed a less-than sign */
-- g_string_append_c(cdata, x[i]);
-- g_free(tag);
-- g_free(tag_name);
-- break;
-- }
--
-- /* Some tags are in the hash table only because we
-- * want to ignore them */
-- if (match[0] != '\0') {
-- /* Append any character data that belongs in the current node */
-- if (cdata->len > 0) {
-- xmlnode_insert_data(cur, cdata->str, cdata->len);
-- g_string_truncate(cdata, 0);
-- }
-- if (g_str_equal(tag_name, "font"))
-- /* Font tags are a special case. We don't
-- * necessarily want to replace the whole thing--
-- * we just want to fix the size attribute. */
-- yahoo_codes_to_html_add_tag(&cur, tag, is_closing_tag, tag_name, TRUE);
-- else
-- yahoo_codes_to_html_add_tag(&cur, match, is_closing_tag, tag_name, FALSE);
-- }
--
-- i = j;
-- g_free(tag);
-- g_free(tag_name);
-- break;
-- }
--
-- } else {
-- g_string_append_c(cdata, x[i]);
-- }
-- }
--
-- /* Append any remaining character data */
-- if (cdata->len > 0)
-- xmlnode_insert_data(cur, cdata->str, cdata->len);
-- g_string_free(cdata, TRUE);
--
-- /* Serialize our HTML */
-- xmlstr1 = xmlnode_to_str(html, NULL);
-- xmlnode_free(html);
--
-- /* Strip off the outter HTML node */
-- /* This probably isn't necessary, especially if we made the outter HTML
-- * node an empty span. But the HTML is simpler this way. */
-- if (!purple_strequal(xmlstr1, "<html/>"))
-- xmlstr2 = g_strndup(xmlstr1 + 6, strlen(xmlstr1) - 13);
-- else
-- xmlstr2 = g_strdup("");
-- g_free(xmlstr1);
--
-- esc = g_strescape(x, NULL);
-- purple_debug_misc("yahoo", "yahoo_codes_to_html(%s)=%s\n", esc, xmlstr2);
-- g_free(esc);
--
-- return xmlstr2;
--}
--
--/* borrowed from gtkimhtml */
--#define MAX_FONT_SIZE 7
--#define POINT_SIZE(x) (_point_sizes [MIN ((x > 0 ? x : 1), MAX_FONT_SIZE) - 1])
--static const gint _point_sizes [] = { 8, 10, 12, 14, 20, 30, 40 };
--
--typedef struct
--{
-- gboolean bold;
-- gboolean italic;
-- gboolean underline;
-- gboolean in_link;
-- int font_size;
-- char *font_face;
-- char *font_color;
--} CurrentMsgState;
--
--static void yahoo_htc_list_cleanup(GSList *l)
--{
-- while (l != NULL) {
-- g_free(l->data);
-- l = g_slist_delete_link(l, l);
-- }
--}
--
--static void parse_font_tag(GString *dest, const char *tag_name, const char *tag,
-- GSList **colors, GSList **tags)
--{
-- const char *start;
-- const char *end;
-- GData *attributes;
-- const char *attribute;
-- gboolean needendtag;
-- GString *tmp;
--
-- purple_markup_find_tag(tag_name, tag, &start, &end, &attributes);
--
-- needendtag = FALSE;
-- tmp = g_string_new(NULL);
--
-- attribute = g_datalist_get_data(&attributes, "color");
-- if (attribute != NULL) {
-- g_string_append(tmp, *colors ? (*colors)->data : "\033[#000000m");
-- g_string_append_printf(dest, "\033[%sm", attribute);
-- *colors = g_slist_prepend(*colors,
-- g_strdup_printf("\033[%sm", attribute));
-- } else {
-- /* We need to add a value to the colors stack even if we're not
-- * setting a color because we ALWAYS pop exactly 1 element from
-- * this stack for every </font> tag. If we don't add anything
-- * then we'll pop something that we shouldn't when we hit this
-- * corresponding </font>. */
-- *colors = g_slist_prepend(*colors,
-- *colors ? g_strdup((*colors)->data) : g_strdup("\033[#000000m"));
-- }
--
-- attribute = g_datalist_get_data(&attributes, "face");
-- if (attribute != NULL) {
-- needendtag = TRUE;
-- g_string_append(dest, "<font ");
-- g_string_append_printf(dest, "face=\"%s\" ", attribute);
-- }
--
-- attribute = g_datalist_get_data(&attributes, "size");
-- if (attribute != NULL) {
-- if (!needendtag) {
-- needendtag = TRUE;
-- g_string_append(dest, "<font ");
-- }
--
-- g_string_append_printf(dest, "size=\"%d\" ",
-- POINT_SIZE(strtol(attribute, NULL, 10)));
-- }
--
-- if (needendtag) {
-- dest->str[dest->len-1] = '>';
-- *tags = g_slist_prepend(*tags, g_strdup("</font>"));
-- g_string_free(tmp, TRUE);
-- } else {
-- *tags = g_slist_prepend(*tags, tmp->str);
-- g_string_free(tmp, FALSE);
-- }
--
-- g_datalist_clear(&attributes);
--}
--
--char *yahoo_html_to_codes(const char *src)
--{
-- GSList *colors = NULL;
--
-- /**
-- * A stack of char*s where each char* is the string that should be
-- * appended to dest in order to close all the tags that were opened
-- * by a <font> tag.
-- */
-- GSList *tags = NULL;
--
-- size_t src_len;
-- int i, j;
-- GString *dest;
-- char *esc;
-- gboolean no_more_gt_brackets = FALSE;
-- gchar *tag, *tag_name;
-- gboolean is_closing_tag;
-- CurrentMsgState current_state;
--
-- memset(&current_state, 0, sizeof(current_state));
--
-- src_len = strlen(src);
-- dest = g_string_sized_new(src_len);
--
-- for (i = 0; i < src_len; i++) {
-- if (src[i] == '<' && !no_more_gt_brackets) {
-- /* The start of an HTML tag */
-- j = i;
--
-- while (j++ < src_len) {
-- if (src[j] != '>') {
-- if (src[j] == '"') {
-- /* We're inside a quoted attribute value. Skip to the end */
-- j++;
-- while (j != src_len && src[j] != '"')
-- j++;
-- } else if (src[j] == '\'') {
-- /* We're inside a quoted attribute value. Skip to the end */
-- j++;
-- while (j != src_len && src[j] != '\'')
-- j++;
-- }
-- if (j != src_len)
-- /* Keep looking for the end of this tag */
-- continue;
--
-- /* This < has no corresponding > */
-- g_string_append_c(dest, src[i]);
-- no_more_gt_brackets = TRUE;
-- break;
-- }
--
-- tag = g_strndup(src + i, j - i + 1);
-- tag_name = yahoo_markup_get_tag_name(tag, &is_closing_tag);
--
-- if (g_str_equal(tag_name, "a")) {
-- const char *start;
-- const char *end;
-- GData *attributes;
-- const char *attribute;
--
-- /*
-- * TODO: Ideally we would replace this:
-- * <a href="http://pidgin.im/">Pidgin</a>
-- * with this:
-- * Pidgin (http://pidgin.im/)
-- *
-- * Currently we drop the text within the <a> tag and
-- * just show the URL. Doing it the fancy way is
-- * complicated when dealing with HTML tags within the
-- * <a> tag.
-- */
--
-- /* Append the URL */
-- purple_markup_find_tag(tag_name, tag, &start, &end, &attributes);
-- attribute = g_datalist_get_data(&attributes, "href");
-- if (attribute != NULL) {
-- if (purple_str_has_prefix(attribute, "mailto:"))
-- attribute += 7;
-- g_string_append(dest, attribute);
-- }
-- g_datalist_clear(&attributes);
--
-- /* Skip past the closing </a> tag */
-- end = purple_strcasestr(src + j, "</a>");
-- if (end != NULL)
-- j = end - src + 3;
--
-- } else if (g_str_equal(tag_name, "font")) {
-- parse_font_tag(dest, tag_name, tag, &colors, &tags);
-- } else if (g_str_equal(tag_name, "b")) {
-- g_string_append(dest, "\033[1m");
-- current_state.bold = TRUE;
-- } else if (g_str_equal(tag_name, "/b")) {
-- if (current_state.bold) {
-- g_string_append(dest, "\033[x1m");
-- current_state.bold = FALSE;
-- }
-- } else if (g_str_equal(tag_name, "i")) {
-- current_state.italic = TRUE;
-- g_string_append(dest, "\033[2m");
-- } else if (g_str_equal(tag_name, "/i")) {
-- if (current_state.italic) {
-- g_string_append(dest, "\033[x2m");
-- current_state.italic = FALSE;
-- }
-- } else if (g_str_equal(tag_name, "u")) {
-- current_state.underline = TRUE;
-- g_string_append(dest, "\033[4m");
-- } else if (g_str_equal(tag_name, "/u")) {
-- if (current_state.underline) {
-- g_string_append(dest, "\033[x4m");
-- current_state.underline = FALSE;
-- }
-- } else if (g_str_equal(tag_name, "/a")) {
-- /* Do nothing */
-- } else if (g_str_equal(tag_name, "br")) {
-- g_string_append_c(dest, '\n');
-- } else if (g_str_equal(tag_name, "/font")) {
-- if (tags != NULL) {
-- char *etag = tags->data;
-- tags = g_slist_delete_link(tags, tags);
-- g_string_append(dest, etag);
-- if (colors != NULL) {
-- g_free(colors->data);
-- colors = g_slist_delete_link(colors, colors);
-- }
-- g_free(etag);
-- }
-- } else if (g_str_equal(tag_name, "span") || g_str_equal(tag_name, "/span")) {
-- /* Do nothing */
-- } else {
-- /* We don't know what the tag is. Send it unmodified. */
-- g_string_append(dest, tag);
-- }
--
-- i = j;
-- g_free(tag);
-- g_free(tag_name);
-- break;
-- }
--
-- } else {
-- const char *entity;
-- int length;
--
-- entity = purple_markup_unescape_entity(src + i, &length);
-- if (entity != NULL) {
-- /* src[i] is the start of an HTML entity */
-- g_string_append(dest, entity);
-- i += length - 1;
-- } else
-- /* src[i] is a normal character */
-- g_string_append_c(dest, src[i]);
-- }
-- }
--
-- esc = g_strescape(dest->str, NULL);
-- purple_debug_misc("yahoo", "yahoo_html_to_codes(%s)=%s\n", src, esc);
-- g_free(esc);
--
-- yahoo_htc_list_cleanup(colors);
-- yahoo_htc_list_cleanup(tags);
--
-- return g_string_free(dest, FALSE);
--}
--
--YahooFederation yahoo_get_federation_from_name(const char *who)
--{
-- YahooFederation fed = YAHOO_FEDERATION_NONE;
-- if (who[3] == '/') {
-- if (!g_ascii_strncasecmp(who, "msn", 3))
-- fed = YAHOO_FEDERATION_MSN;
-- else if (!g_ascii_strncasecmp(who, "ocs", 3))
-- fed = YAHOO_FEDERATION_OCS;
-- else if (!g_ascii_strncasecmp(who, "ibm", 3))
-- fed = YAHOO_FEDERATION_IBM;
-- else if (!g_ascii_strncasecmp(who, "pbx", 3))
-- fed = YAHOO_FEDERATION_PBX;
-- }
-- return fed;
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_aliases.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_aliases.c
---- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_aliases.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_aliases.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,718 +0,0 @@
--/*
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--
--#include "internal.h"
--
--#include "account.h"
--#include "accountopt.h"
--#include "blist.h"
--#include "debug.h"
--#include "util.h"
--#include "request.h"
--#include "version.h"
--#include "libymsg.h"
--#include "yahoo_aliases.h"
--#include "yahoo_friend.h"
--#include "yahoo_packet.h"
--
--/* I hate hardcoding this stuff, but Yahoo never sends us anything to use. Someone in the know may be able to tweak this URL */
--#define YAHOO_ALIAS_FETCH_URL "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us&diffs=1&t=0&tags=short&rt=0&prog-ver=" YAHOO_CLIENT_VERSION "&useutf8=1&legenc=codepage-1252"
--#define YAHOO_ALIAS_UPDATE_URL "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us&sync=1&tags=short&noclear=1&useutf8=1&legenc=codepage-1252"
--#define YAHOOJP_ALIAS_FETCH_URL "http://address.yahoo.co.jp/yab/jp?v=XM&prog=ymsgr&.intl=jp&diffs=1&t=0&tags=short&rt=0&prog-ver=" YAHOOJP_CLIENT_VERSION
--#define YAHOOJP_ALIAS_UPDATE_URL "http://address.yahoo.co.jp/yab/jp?v=XM&prog=ymsgr&.intl=jp&sync=1&tags=short&noclear=1"
--
--void yahoo_update_alias(PurpleConnection *gc, const char *who, const char *alias);
--
--/**
-- * Stuff we want passed to the callback function
-- */
--struct callback_data {
-- PurpleConnection *gc;
-- gchar *id;
-- gchar *who;
--};
--
--void yahoo_personal_details_reset(YahooPersonalDetails *ypd, gboolean all)
--{
-- if (all)
-- g_free(ypd->id);
-- g_free(ypd->names.first);
-- g_free(ypd->names.last);
-- g_free(ypd->names.middle);
-- g_free(ypd->names.nick);
-- g_free(ypd->phone.work);
-- g_free(ypd->phone.home);
-- g_free(ypd->phone.mobile);
--}
--
--/**************************************************************************
-- * Alias Fetch Functions
-- **************************************************************************/
--
--static void
--yahoo_fetch_aliases_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message)
--{
-- PurpleConnection *gc = user_data;
-- YahooData *yd = gc->proto_data;
--
-- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
--
-- if (len == 0) {
-- purple_debug_info("yahoo", "No Aliases to process.%s%s\n",
-- error_message ? " Error:" : "", error_message ? error_message : "");
-- } else {
-- gchar *full_name, *nick_name;
-- const char *yid, *id, *fn, *ln, *nn, *alias, *mn;
-- const char *hp, *wp, *mo;
-- YahooFriend *f;
-- PurpleBuddy *b;
-- xmlnode *item, *contacts;
-- PurpleAccount *account;
--
-- account = purple_connection_get_account(gc);
-- /* Put our web response into a xmlnode for easy management */
-- contacts = xmlnode_from_str(url_text, -1);
--
-- if (contacts == NULL) {
-- purple_debug_error("yahoo", "Badly formed Alias XML\n");
-- return;
-- }
-- purple_debug_info("yahoo", "Fetched %" G_GSIZE_FORMAT
-- " bytes of alias data\n", len);
--
-- /* Loop around and around and around until we have gone through all the received aliases */
-- for(item = xmlnode_get_child(contacts, "ct"); item; item = xmlnode_get_next_twin(item)) {
-- /* Yahoo replies with two types of contact (ct) record, we are only interested in the alias ones */
-- if ((yid = xmlnode_get_attrib(item, "yi"))) {
-- YahooPersonalDetails *ypd = NULL;
-- /* Grab all the bits of information we can */
-- fn = xmlnode_get_attrib(item, "fn");
-- ln = xmlnode_get_attrib(item, "ln");
-- nn = xmlnode_get_attrib(item, "nn");
-- mn = xmlnode_get_attrib(item, "mn");
-- id = xmlnode_get_attrib(item, "id");
--
-- hp = xmlnode_get_attrib(item, "hp");
-- wp = xmlnode_get_attrib(item, "wp");
-- mo = xmlnode_get_attrib(item, "mo");
--
-- full_name = nick_name = NULL;
-- alias = NULL;
--
-- /* Yahoo stores first and last names separately, lets put them together into a full name */
-- if (yd->jp)
-- full_name = g_strstrip(g_strdup_printf("%s %s", (ln != NULL ? ln : "") , (fn != NULL ? fn : "")));
-- else
-- full_name = g_strstrip(g_strdup_printf("%s %s", (fn != NULL ? fn : "") , (ln != NULL ? ln : "")));
-- nick_name = (nn != NULL ? g_strstrip(g_strdup(nn)) : NULL);
--
-- if (nick_name != NULL)
-- alias = nick_name; /* If we have a nickname from Yahoo, let's use it */
-- else if (strlen(full_name) != 0)
-- alias = full_name; /* If no Yahoo nickname, we can use the full_name created above */
--
-- /* Find the local buddy that matches */
-- f = yahoo_friend_find(gc, yid);
-- b = purple_find_buddy(account, yid);
--
-- /* If we don't find a matching buddy, ignore the alias !! */
-- if (f != NULL && b != NULL) {
-- const char *buddy_alias = purple_buddy_get_alias(b);
-- yahoo_friend_set_alias_id(f, id);
--
-- /* Finally, if we received an alias, we better update the buddy list */
-- if (alias != NULL) {
-- serv_got_alias(gc, yid, alias);
-- purple_debug_info("yahoo", "Fetched alias '%s' (%s)\n", alias, id);
-- } else if (buddy_alias && *buddy_alias && !g_str_equal(buddy_alias, yid)) {
-- /* Or if we have an alias that Yahoo doesn't, send it up */
-- yahoo_update_alias(gc, yid, buddy_alias);
-- purple_debug_info("yahoo", "Sent updated alias '%s'\n", buddy_alias);
-- }
-- }
--
-- if (f != NULL)
-- ypd = &f->ypd;
-- else {
-- /* May be the alias is for the account? */
-- const char *yidn = purple_normalize(account, yid);
-- if (purple_strequal(yidn, purple_connection_get_display_name(gc))) {
-- ypd = &yd->ypd;
-- }
-- }
--
-- if (ypd) {
-- yahoo_personal_details_reset(ypd, TRUE);
-- ypd->id = g_strdup(id);
-- ypd->names.first = g_strdup(fn);
-- ypd->names.middle = g_strdup(mn);
-- ypd->names.last = g_strdup(ln);
-- ypd->names.nick = g_strdup(nn);
--
-- ypd->phone.work = g_strdup(wp);
-- ypd->phone.home = g_strdup(hp);
-- ypd->phone.mobile = g_strdup(mo);
-- }
--
-- g_free(full_name);
-- g_free(nick_name);
-- }
-- }
-- xmlnode_free(contacts);
-- }
--}
--
--void
--yahoo_fetch_aliases(PurpleConnection *gc)
--{
-- YahooData *yd = gc->proto_data;
-- const char *url;
-- gchar *request, *webpage, *webaddress;
-- PurpleUtilFetchUrlData *url_data;
--
-- /* use whole URL if using HTTP Proxy */
-- gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
--
-- /* Build all the info to make the web request */
-- url = yd->jp ? YAHOOJP_ALIAS_FETCH_URL : YAHOO_ALIAS_FETCH_URL;
-- purple_url_parse(url, &webaddress, NULL, &webpage, NULL, NULL);
-- request = g_strdup_printf("GET %s%s/%s HTTP/1.1\r\n"
-- "User-Agent: " YAHOO_CLIENT_USERAGENT_ALIAS "\r\n"
-- "Cookie: T=%s; Y=%s\r\n"
-- "Host: %s\r\n"
-- "Cache-Control: no-cache\r\n\r\n",
-- use_whole_url ? "http://" : "", use_whole_url ? webaddress : "", webpage,
-- yd->cookie_t, yd->cookie_y,
-- webaddress);
--
-- /* We have a URL and some header information, let's connect and get some aliases */
-- url_data = purple_util_fetch_url_request_len_with_account(purple_connection_get_account(gc),
-- url, use_whole_url, NULL, TRUE, request, FALSE, -1,
-- yahoo_fetch_aliases_cb, gc);
-- if (url_data != NULL)
-- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
--
-- g_free(webaddress);
-- g_free(webpage);
-- g_free(request);
--}
--
--/**************************************************************************
-- * Alias Update Functions
-- **************************************************************************/
--
--static void
--yahoo_update_alias_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message)
--{
-- xmlnode *node, *result;
-- struct callback_data *cb = user_data;
-- PurpleConnection *gc = cb->gc;
-- YahooData *yd;
--
-- yd = gc->proto_data;
-- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
--
-- if (len == 0 || error_message != NULL) {
-- purple_debug_info("yahoo", "Error updating alias for %s: %s\n",
-- cb->who,
-- error_message ? error_message : "");
-- g_free(cb->who);
-- g_free(cb->id);
-- g_free(cb);
-- return;
-- }
--
-- result = xmlnode_from_str(url_text, -1);
--
-- if (result == NULL) {
-- purple_debug_error("yahoo", "Alias update for %s failed: Badly formed response\n",
-- cb->who);
-- g_free(cb->who);
-- g_free(cb->id);
-- g_free(cb);
-- return;
-- }
--
-- if ((node = xmlnode_get_child(result, "ct"))) {
-- if (cb->id == NULL) {
-- const char *new_id = xmlnode_get_attrib(node, "id");
-- if (new_id != NULL) {
-- /* We now have an addressbook id for the friend; we should save it */
-- YahooFriend *f = yahoo_friend_find(cb->gc, cb->who);
--
-- purple_debug_info("yahoo", "Alias creation for %s succeeded\n", cb->who);
--
-- if (f)
-- yahoo_friend_set_alias_id(f, new_id);
-- else
-- purple_debug_error("yahoo", "Missing YahooFriend. Unable to store new addressbook id.\n");
-- } else
-- purple_debug_error("yahoo", "Missing new addressbook id in add response for %s (weird).\n",
-- cb->who);
-- } else {
-- if (g_ascii_strncasecmp(xmlnode_get_attrib(node, "id"), cb->id, strlen(cb->id))==0)
-- purple_debug_info("yahoo", "Alias update for %s succeeded\n", cb->who);
-- else
-- purple_debug_error("yahoo", "Alias update for %s failed (Contact record return mismatch)\n",
-- cb->who);
-- }
-- } else
-- purple_debug_info("yahoo", "Alias update for %s failed (No contact record returned)\n", cb->who);
--
-- g_free(cb->who);
-- g_free(cb->id);
-- g_free(cb);
-- xmlnode_free(result);
--}
--
--void
--yahoo_update_alias(PurpleConnection *gc, const char *who, const char *alias)
--{
-- YahooData *yd;
-- const char *url;
-- gchar *content, *request, *webpage, *webaddress;
-- struct callback_data *cb;
-- PurpleUtilFetchUrlData *url_data;
-- YahooFriend *f;
-- /* use whole URL if using HTTP Proxy */
-- gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
--
-- g_return_if_fail(who != NULL);
-- g_return_if_fail(gc != NULL);
--
-- if (alias == NULL)
-- alias = "";
--
-- f = yahoo_friend_find(gc, who);
-- if (f == NULL) {
-- purple_debug_error("yahoo", "Missing YahooFriend. Unable to set server alias.\n");
-- return;
-- }
--
-- yd = gc->proto_data;
--
-- /* Using callback_data so I have access to gc in the callback function */
-- cb = g_new0(struct callback_data, 1);
-- cb->who = g_strdup(who);
-- cb->id = g_strdup(yahoo_friend_get_alias_id(f));
-- cb->gc = gc;
--
-- /* Build all the info to make the web request */
-- url = yd->jp ? YAHOOJP_ALIAS_UPDATE_URL: YAHOO_ALIAS_UPDATE_URL;
-- purple_url_parse(url, &webaddress, NULL, &webpage, NULL, NULL);
--
-- if (cb->id == NULL) {
-- /* No id for this buddy, so create an address book entry */
-- purple_debug_info("yahoo", "Creating '%s' as new alias for user '%s'\n", alias, who);
--
-- if (yd->jp) {
-- gchar *alias_jp = g_convert(alias, -1, "EUC-JP", "UTF-8", NULL, NULL, NULL);
-- gchar *converted_alias_jp = yahoo_convert_to_numeric(alias_jp);
-- content = g_strdup_printf("<ab k=\"%s\" cc=\"9\">\n"
-- "<ct a=\"1\" yi='%s' nn='%s' />\n</ab>\r\n",
-- purple_account_get_username(gc->account),
-- who, converted_alias_jp);
-- g_free(converted_alias_jp);
-- g_free(alias_jp);
-- } else {
-- gchar *escaped_alias = g_markup_escape_text(alias, -1);
-- content = g_strdup_printf("<?xml version=\"1.0\" encoding=\"utf-8\"?><ab k=\"%s\" cc=\"9\">\n"
-- "<ct a=\"1\" yi='%s' nn='%s' />\n</ab>\r\n",
-- purple_account_get_username(gc->account),
-- who, escaped_alias);
-- g_free(escaped_alias);
-- }
-- } else {
-- purple_debug_info("yahoo", "Updating '%s' as new alias for user '%s'\n", alias, who);
--
-- if (yd->jp) {
-- gchar *alias_jp = g_convert(alias, -1, "EUC-JP", "UTF-8", NULL, NULL, NULL);
-- gchar *converted_alias_jp = yahoo_convert_to_numeric(alias_jp);
-- content = g_strdup_printf("<ab k=\"%s\" cc=\"1\">\n"
-- "<ct e=\"1\" yi='%s' id='%s' nn='%s' pr='0' />\n</ab>\r\n",
-- purple_account_get_username(gc->account),
-- who, cb->id, converted_alias_jp);
-- g_free(converted_alias_jp);
-- g_free(alias_jp);
-- } else {
-- gchar *escaped_alias = g_markup_escape_text(alias, -1);
-- content = g_strdup_printf("<?xml version=\"1.0\" encoding=\"utf-8\"?><ab k=\"%s\" cc=\"1\">\n"
-- "<ct e=\"1\" yi='%s' id='%s' nn='%s' pr='0' />\n</ab>\r\n",
-- purple_account_get_username(gc->account),
-- who, cb->id, escaped_alias);
-- g_free(escaped_alias);
-- }
-- }
--
-- request = g_strdup_printf("POST %s%s/%s HTTP/1.1\r\n"
-- "User-Agent: " YAHOO_CLIENT_USERAGENT_ALIAS "\r\n"
-- "Cookie: T=%s; Y=%s\r\n"
-- "Host: %s\r\n"
-- "Content-Length: %" G_GSIZE_FORMAT "\r\n"
-- "Cache-Control: no-cache\r\n\r\n"
-- "%s",
-- use_whole_url ? "http://" : "", use_whole_url ? webaddress : "", webpage,
-- yd->cookie_t, yd->cookie_y,
-- webaddress,
-- strlen(content),
-- content);
--
-- /* We have a URL and some header information, let's connect and update the alias */
-- url_data = purple_util_fetch_url_request_len_with_account(
-- purple_connection_get_account(gc), url, use_whole_url, NULL, TRUE,
-- request, FALSE, -1, yahoo_update_alias_cb, cb);
-- if (url_data != NULL)
-- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
--
-- g_free(webpage);
-- g_free(webaddress);
-- g_free(content);
-- g_free(request);
--}
--
--
--/**************************************************************************
-- * User Info Update Functions
-- **************************************************************************/
--
--#if 0
--/* This block of code can be used to send our contact details to
-- * everyone in the buddylist. But with the official messenger,
-- * doing this pops a conversation window at the receiver's end,
-- * which is stupid, and thus not really surprising. */
--
--struct yahoo_userinfo {
-- YahooData *yd;
-- char *xml;
--};
--
--static void
--yahoo_send_userinfo_to_user(struct yahoo_userinfo *yui, const char *who)
--{
-- struct yahoo_packet *pkt;
-- PurpleConnection *gc;
--
-- gc = yui->yd->gc;
-- pkt = yahoo_packet_new(YAHOO_SERVICE_CONTACT_DETAILS, 0, 0);
-- yahoo_packet_hash(pkt, "siisis",
-- 1, purple_connection_get_display_name(gc),
-- 13, 1, /* This creates a conversation window in the official client */
-- 302, 5,
-- 5, who,
-- 303, 5,
-- 280, yui->xml);
-- yahoo_packet_send_and_free(pkt, yui->yd);
--}
--
--static void
--yahoo_send_userinfo_foreach(gpointer key, gpointer value, gpointer data)
--{
-- const char *who = key;
-- YahooFriend *f = value;
--
-- if (f->status != YAHOO_STATUS_OFFLINE) {
-- yahoo_send_userinfo_to_user(data, who);
-- }
--}
--
--static void
--yahoo_sent_userinfo_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message)
--{
-- struct yahoo_userinfo *yui = user_data;
-- yahoo_fetch_aliases_cb(url_data, yui->yd->gc, url_text, len, error_message);
-- g_hash_table_foreach(yui->yd->friends, yahoo_send_userinfo_foreach, yui);
-- g_free(yui->xml);
-- g_free(yui);
--}
--#endif
--
--static void
--yahoo_set_userinfo_cb(PurpleConnection *gc, PurpleRequestFields *fields)
--{
-- xmlnode *node = xmlnode_new("ab");
-- xmlnode *ct = xmlnode_new_child(node, "ct");
-- YahooData *yd = purple_connection_get_protocol_data(gc);
-- PurpleAccount *account;
-- PurpleUtilFetchUrlData *url_data;
-- char *webaddress, *webpage;
-- char *request, *content;
-- int len;
-- int i;
-- char * yfields[] = { "fn", "ln", "nn", "mn", "hp", "wp", "mo", NULL };
--
-- account = purple_connection_get_account(gc);
--
-- xmlnode_set_attrib(node, "k", purple_connection_get_display_name(gc));
-- xmlnode_set_attrib(node, "cc", "1"); /* XXX: ? */
--
-- xmlnode_set_attrib(ct, "e", "1");
-- xmlnode_set_attrib(ct, "yi", purple_request_fields_get_string(fields, "yname"));
-- xmlnode_set_attrib(ct, "id", purple_request_fields_get_string(fields, "yid"));
-- xmlnode_set_attrib(ct, "pr", "0");
--
-- for (i = 0; yfields[i]; i++) {
-- const char *v = purple_request_fields_get_string(fields, yfields[i]);
-- xmlnode_set_attrib(ct, yfields[i], v ? v : "");
-- }
--
-- content = xmlnode_to_formatted_str(node, &len);
-- xmlnode_free(node);
-- purple_url_parse(yd->jp ? YAHOOJP_USERINFO_URL : YAHOO_USERINFO_URL, &webaddress, NULL, &webpage, NULL, NULL);
--
-- request = g_strdup_printf("POST %s HTTP/1.1\r\n"
-- "User-Agent: " YAHOO_CLIENT_USERAGENT_ALIAS "\r\n"
-- "Cookie: T=%s; path=/; domain=.yahoo.com; Y=%s;\r\n"
-- "Host: %s\r\n"
-- "Content-Length: %d\r\n"
-- "Cache-Control: no-cache\r\n\r\n"
-- "%s\r\n\r\n",
-- webpage,
-- yd->cookie_t, yd->cookie_y,
-- webaddress,
-- len + 4,
-- content);
--
--#if 0
-- {
-- /* This is if we wanted to send our contact details to everyone
-- * in the buddylist. But this cannot be done now, because in the
-- * official messenger, doing this pops a conversation window at
-- * the receiver's end, which is stupid, and thus not really
-- * surprising. */
-- struct yahoo_userinfo *ui = g_new(struct yahoo_userinfo, 1);
-- node = xmlnode_new("contact");
--
-- for (i = 0; yfields[i]; i++) {
-- const char *v = purple_request_fields_get_string(fields, yfields[i]);
-- if (v) {
-- xmlnode *nd = xmlnode_new_child(node, yfields[i]);
-- xmlnode_insert_data(nd, v, -1);
-- }
-- }
--
-- ui->yd = yd;
-- ui->xml = xmlnode_to_str(node, NULL);
-- xmlnode_free(node);
-- }
--#endif
--
-- url_data = purple_util_fetch_url_request_len_with_account(account, webaddress, FALSE,
-- YAHOO_CLIENT_USERAGENT_ALIAS, TRUE, request, FALSE, -1,
-- yahoo_fetch_aliases_cb, gc);
-- if (url_data != NULL)
-- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
--
-- g_free(webaddress);
-- g_free(webpage);
-- g_free(content);
-- g_free(request);
--}
--
--static PurpleRequestFields *
--request_fields_from_personal_details(YahooPersonalDetails *ypd, const char *id)
--{
-- PurpleRequestFields *fields;
-- PurpleRequestFieldGroup *group;
-- PurpleRequestField *field;
-- int i;
-- struct {
-- char *id;
-- char *text;
-- char *value;
-- } yfields[] = {
-- {"fn", N_("First Name"), ypd->names.first},
-- {"ln", N_("Last Name"), ypd->names.last},
-- {"nn", N_("Nickname"), ypd->names.nick},
-- {"mn", N_("Middle Name"), ypd->names.middle},
-- {"hp", N_("Home Phone Number"), ypd->phone.home},
-- {"wp", N_("Work Phone Number"), ypd->phone.work},
-- {"mo", N_("Mobile Phone Number"), ypd->phone.mobile},
-- {NULL, NULL, NULL}
-- };
--
-- fields = purple_request_fields_new();
-- group = purple_request_field_group_new(NULL);
-- purple_request_fields_add_group(fields, group);
--
-- field = purple_request_field_string_new("yname", "", id, FALSE);
-- purple_request_field_set_visible(field, FALSE);
-- purple_request_field_group_add_field(group, field);
--
-- field = purple_request_field_string_new("yid", "", ypd->id, FALSE);
-- purple_request_field_set_visible(field, FALSE);
-- purple_request_field_group_add_field(group, field);
--
-- for (i = 0; yfields[i].id; i++) {
-- field = purple_request_field_string_new(yfields[i].id, _(yfields[i].text),
-- yfields[i].value, FALSE);
-- purple_request_field_group_add_field(group, field);
-- }
--
-- return fields;
--}
--
--void yahoo_set_userinfo_for_buddy(PurpleConnection *gc, PurpleBuddy *buddy)
--{
-- PurpleRequestFields *fields;
-- YahooFriend *f;
-- const char *name;
--
-- name = purple_buddy_get_name(buddy);
-- f = yahoo_friend_find(gc, name);
-- if (!f)
-- return;
--
-- fields = request_fields_from_personal_details(&f->ypd, name);
-- purple_request_fields(gc, NULL, _("Set User Info"), NULL, fields,
-- _("OK"), G_CALLBACK(yahoo_set_userinfo_cb),
-- _("Cancel"), NULL,
-- purple_connection_get_account(gc), NULL, NULL, gc);
--}
--
--void yahoo_set_userinfo(PurpleConnection *gc)
--{
-- YahooData *yd = purple_connection_get_protocol_data(gc);
-- PurpleRequestFields *fields = request_fields_from_personal_details(&yd->ypd,
-- purple_connection_get_display_name(gc));
-- purple_request_fields(gc, NULL, _("Set User Info"), NULL, fields,
-- _("OK"), G_CALLBACK(yahoo_set_userinfo_cb),
-- _("Cancel"), NULL,
-- purple_connection_get_account(gc), NULL, NULL, gc);
--}
--
--static gboolean
--parse_contact_details(YahooData *yd, const char *who, const char *xml)
--{
-- xmlnode *node, *nd;
-- YahooFriend *f;
-- char *yid;
--
-- node = xmlnode_from_str(xml, -1);
-- if (!node) {
-- purple_debug_info("yahoo", "Received malformed XML for contact details from '%s':\n%s\n",
-- who, xml);
-- return FALSE;
-- }
--
-- nd = xmlnode_get_child(node, "yi");
-- if (!nd || !(yid = xmlnode_get_data(nd))) {
-- xmlnode_free(node);
-- return FALSE;
-- }
--
-- if (!purple_strequal(yid, who)) {
-- /* The user may not want to set the contact details about folks in the buddylist
-- to what some random dude might have sent. So it would be good if we popped
-- up a prompt requiring the user to confirm the details before we set them.
-- However, someone could send details about hundreds of users at the same time,
-- which would make things really bad. So for now, until we have a better way of
-- dealing with this, ignore this details. */
-- purple_debug_info("yahoo", "Ignoring contact details sent by %s about %s\n",
-- who, yid);
-- g_free(yid);
-- xmlnode_free(node);
-- return FALSE;
-- }
--
-- f = yahoo_friend_find(yd->gc, yid);
-- if (!f) {
-- g_free(yid);
-- xmlnode_free(node);
-- return FALSE;
-- } else {
-- int i;
-- YahooPersonalDetails *ypd = &f->ypd;
-- char *alias = NULL;
-- struct {
-- char *id;
-- char **field;
-- } details[] = {
-- {"fn", &ypd->names.first},
-- {"mn", &ypd->names.middle},
-- {"ln", &ypd->names.last},
-- {"nn", &ypd->names.nick},
-- {"wp", &ypd->phone.work},
-- {"hp", &ypd->phone.home},
-- {"mo", &ypd->phone.mobile},
-- {NULL, NULL}
-- };
--
-- yahoo_personal_details_reset(ypd, FALSE);
--
-- for (i = 0; details[i].id; i++) {
-- nd = xmlnode_get_child(node, details[i].id);
-- *details[i].field = nd ? xmlnode_get_data(nd) : NULL;
-- }
--
-- if (ypd->names.nick)
-- alias = ypd->names.nick;
-- else if (ypd->names.first || ypd->names.last) {
-- alias = g_strstrip(g_strdup_printf("%s %s",
-- ypd->names.first ? ypd->names.first : "",
-- ypd->names.last ? ypd->names.last : ""));
-- }
--
-- if (alias) {
-- serv_got_alias(yd->gc, yid, alias);
-- if (alias != ypd->names.nick)
-- g_free(alias);
-- }
-- }
--
-- xmlnode_free(node);
-- g_free(yid);
-- return TRUE;
--}
--
--/* I don't think this happens for MSN buddies. -- sad */
--void yahoo_process_contact_details(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- GSList *l = pkt->hash;
-- const char *who = NULL, *xml = NULL;
-- YahooData *yd = purple_connection_get_protocol_data(gc);
--
-- for (; l; l = l->next) {
-- struct yahoo_pair *pair = l->data;
-- switch (pair->key) {
-- case 4:
-- who = pair->value; /* This is the person who sent us the details.
-- But not necessarily about himself. */
-- break;
-- case 5:
-- break;
-- case 13:
-- /* This is '1' if 'who' is sending the contact details about herself,
-- '0' if 'who' is sending the contact details she has about buddies
-- in her list. However, in all cases, the xml in key 280 always seems
-- to contain the yid of the person, so we may as well ignore this field
-- and look into the xml instead to see who the information is about. */
-- break;
-- case 280:
-- xml = pair->value;
-- parse_contact_details(yd, who, xml);
-- break;
-- }
-- }
--}
--
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_aliases.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_aliases.h
---- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_aliases.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_aliases.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,41 +0,0 @@
--/*
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--
--#include "internal.h"
--
--#include "account.h"
--#include "accountopt.h"
--#include "blist.h"
--#include "debug.h"
--#include "util.h"
--#include "version.h"
--#include "libymsg.h"
--#include "yahoo_packet.h"
--
--void yahoo_update_alias(PurpleConnection *gc, const char *who, const char *alias);
--void yahoo_fetch_aliases(PurpleConnection *gc);
--void yahoo_set_userinfo(PurpleConnection *gc);
--void yahoo_set_userinfo_for_buddy(PurpleConnection *gc, PurpleBuddy *buddy);
--void yahoo_personal_details_reset(YahooPersonalDetails *ypd, gboolean all);
--void yahoo_process_contact_details(PurpleConnection *gc, struct yahoo_packet *pkt);
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoochat.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoochat.c
---- pidgin-2.10.7/libpurple/protocols/yahoo/yahoochat.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoochat.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1633 +0,0 @@
--/*
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * Some code copyright 2003 Tim Ringenbach <omarvo@hotmail.com>
-- * (marv on irc.freenode.net)
-- * Some code borrowed from libyahoo2, copyright (C) 2002, Philip
-- * S Tellis <philip . tellis AT gmx . net>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include "internal.h"
--
--#ifdef HAVE_CONFIG_H
--#include "config.h"
--#endif /* HAVE_CONFIG_H */
--
--#include "debug.h"
--#include "privacy.h"
--#include "prpl.h"
--
--#include "conversation.h"
--#include "notify.h"
--#include "util.h"
--
--#include "libymsg.h"
--#include "yahoo_packet.h"
--#include "yahoochat.h"
--#include "ycht.h"
--
--#define YAHOO_CHAT_ID (1)
--
--/* prototype(s) */
--static void yahoo_chat_leave(PurpleConnection *gc, const char *room, const char *dn, gboolean logout);
--
--/* special function to log us on to the yahoo chat service */
--static void yahoo_chat_online(PurpleConnection *gc)
--{
-- YahooData *yd = gc->proto_data;
-- struct yahoo_packet *pkt;
-- const char *rll;
--
-- if (yd->wm) {
-- ycht_connection_open(gc);
-- return;
-- }
--
-- rll = purple_account_get_string(purple_connection_get_account(gc),
-- "room_list_locale", YAHOO_ROOMLIST_LOCALE);
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_CHATONLINE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash(pkt, "sssss",
-- 109, purple_connection_get_display_name(gc),
-- 1, purple_connection_get_display_name(gc),
-- 6, "abcde",
-- /* I'm not sure this is the correct way to set this. */
-- 98, rll,
-- 135, yd->jp ? YAHOO_CLIENT_VERSION : YAHOOJP_CLIENT_VERSION);
-- yahoo_packet_send_and_free(pkt, yd);
--}
--
--/* this is slow, and different from the purple_* version in that it (hopefully) won't add a user twice */
--void yahoo_chat_add_users(PurpleConvChat *chat, GList *newusers)
--{
-- GList *i;
--
-- for (i = newusers; i; i = i->next) {
-- if (purple_conv_chat_find_user(chat, i->data))
-- continue;
-- purple_conv_chat_add_user(chat, i->data, NULL, PURPLE_CBFLAGS_NONE, TRUE);
-- }
--}
--
--void yahoo_chat_add_user(PurpleConvChat *chat, const char *user, const char *reason)
--{
-- if (purple_conv_chat_find_user(chat, user))
-- return;
--
-- purple_conv_chat_add_user(chat, user, reason, PURPLE_CBFLAGS_NONE, TRUE);
--}
--
--static PurpleConversation *yahoo_find_conference(PurpleConnection *gc, const char *name)
--{
-- YahooData *yd;
-- GSList *l;
--
-- yd = gc->proto_data;
--
-- for (l = yd->confs; l; l = l->next) {
-- PurpleConversation *c = l->data;
-- if (!purple_utf8_strcasecmp(purple_conversation_get_name(c), name))
-- return c;
-- }
-- return NULL;
--}
--
--
--void yahoo_process_conference_invite(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- PurpleAccount *account;
-- GSList *l;
-- char *room = NULL;
-- char *who = NULL;
-- char *msg = NULL;
-- GString *members = NULL;
-- GHashTable *components;
--
-- if ( (pkt->status == 2) || (pkt->status == 11) )
-- return; /* Status is 11 when we are being notified about invitation being sent to someone else */
--
-- account = purple_connection_get_account(gc);
--
-- for (l = pkt->hash; l; l = l->next) {
-- struct yahoo_pair *pair = l->data;
-- if (pair->key == 57)
-- {
-- room = yahoo_string_decode(gc, pair->value, FALSE);
-- if (yahoo_find_conference(gc, room) != NULL)
-- {
-- /* Looks like we got invited to an already open conference. */
-- /* Laters: Should we accept this conference rather than ignoring the invitation ? */
-- purple_debug_info("yahoo","Ignoring invitation for an already existing chat, room:%s\n",room);
-- g_free(room);
-- return;
-- }
-- }
-- }
--
-- members = g_string_sized_new(512);
--
-- for (l = pkt->hash; l; l = l->next) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 1: /* us, but we already know who we are */
-- break;
-- case 57:
-- g_free(room);
-- room = yahoo_string_decode(gc, pair->value, FALSE);
-- break;
-- case 50: /* inviter */
-- who = pair->value;
-- g_string_append_printf(members, "%s\n", who);
-- break;
-- case 51: /* This user is being invited to the conference. Comes with status = 11, so we wont reach here */
-- break;
-- case 52: /* Invited users. Assuming us invited, since we got this packet */
-- break; /* break needed, or else we add the users to the conference before they accept the invitation */
-- case 53: /* members who have already joined the conference */
-- g_string_append_printf(members, "%s\n", pair->value);
-- break;
-- case 58:
-- g_free(msg);
-- msg = yahoo_string_decode(gc, pair->value, FALSE);
-- break;
-- case 13: /* ? */
-- break;
-- }
-- }
--
-- if (!room) {
-- g_string_free(members, TRUE);
-- g_free(msg);
-- return;
-- }
--
-- if (!purple_privacy_check(account, who) ||
-- (purple_account_get_bool(account, "ignore_invites", FALSE)))
-- {
-- purple_debug_info("yahoo",
-- "Invite to conference %s from %s has been dropped.\n", room, who);
-- g_free(room);
-- g_free(msg);
-- g_string_free(members, TRUE);
-- return;
-- }
--
-- components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-- g_hash_table_replace(components, g_strdup("room"), room);
-- if (msg)
-- g_hash_table_replace(components, g_strdup("topic"), msg);
-- g_hash_table_replace(components, g_strdup("type"), g_strdup("Conference"));
-- g_hash_table_replace(components, g_strdup("members"), g_string_free(members, FALSE));
-- serv_got_chat_invite(gc, room, who, msg, components);
--
--}
--
--void yahoo_process_conference_decline(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- GSList *l;
-- char *room = NULL;
-- char *who = NULL;
-- char *msg = NULL;
-- PurpleConversation *c = NULL;
-- int utf8 = 0;
--
-- for (l = pkt->hash; l; l = l->next) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 57:
-- g_free(room);
-- room = yahoo_string_decode(gc, pair->value, FALSE);
-- break;
-- case 54:
-- who = pair->value;
-- break;
-- case 14:
-- g_free(msg);
-- msg = yahoo_string_decode(gc, pair->value, FALSE);
-- break;
-- case 97:
-- utf8 = strtol(pair->value, NULL, 10);
-- break;
-- }
-- }
-- if (!purple_privacy_check(purple_connection_get_account(gc), who))
-- {
-- g_free(room);
-- g_free(msg);
-- return;
-- }
--
-- if (who && room) {
-- /* make sure we're in the room before we process a decline message for it */
-- if((c = yahoo_find_conference(gc, room))) {
-- char *tmp = NULL, *msg_tmp = NULL;
-- if(msg)
-- {
-- msg_tmp = yahoo_string_decode(gc, msg, utf8);
-- msg = yahoo_codes_to_html(msg_tmp);
-- serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)), who, 0, msg, time(NULL));
-- g_free(msg_tmp);
-- g_free(msg);
-- }
--
-- tmp = g_strdup_printf(_("%s has declined to join."), who);
-- purple_conversation_write(c, NULL, tmp, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, time(NULL));
--
-- g_free(tmp);
-- }
--
-- g_free(room);
-- }
--}
--
--void yahoo_process_conference_logon(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- GSList *l;
-- char *room = NULL;
-- char *who = NULL;
-- PurpleConversation *c;
--
-- for (l = pkt->hash; l; l = l->next) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 57:
-- g_free(room);
-- room = yahoo_string_decode(gc, pair->value, FALSE);
-- break;
-- case 53:
-- who = pair->value;
-- break;
-- }
-- }
--
-- if (who && room) {
-- c = yahoo_find_conference(gc, room);
-- if (c)
-- { /* Prevent duplicate users in the chat */
-- if( !purple_conv_chat_find_user(PURPLE_CONV_CHAT(c), who) )
-- yahoo_chat_add_user(PURPLE_CONV_CHAT(c), who, NULL);
-- }
-- g_free(room);
-- }
--}
--
--void yahoo_process_conference_logoff(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- GSList *l;
-- char *room = NULL;
-- char *who = NULL;
-- PurpleConversation *c;
--
-- for (l = pkt->hash; l; l = l->next) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 57:
-- g_free(room);
-- room = yahoo_string_decode(gc, pair->value, FALSE);
-- break;
-- case 56:
-- who = pair->value;
-- break;
-- }
-- }
--
-- if (who && room) {
-- c = yahoo_find_conference(gc, room);
-- if (c)
-- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(c), who, NULL);
-- g_free(room);
-- }
--}
--
--void yahoo_process_conference_message(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- GSList *l;
-- char *room = NULL;
-- char *who = NULL;
-- char *msg = NULL;
-- int utf8 = 0;
-- PurpleConversation *c;
--
-- for (l = pkt->hash; l; l = l->next) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 57:
-- g_free(room);
-- room = yahoo_string_decode(gc, pair->value, FALSE);
-- break;
-- case 3:
-- who = pair->value;
-- break;
-- case 14:
-- msg = pair->value;
-- break;
-- case 97:
-- utf8 = strtol(pair->value, NULL, 10);
-- break;
-- }
-- }
--
-- if (room && who && msg) {
-- char *msg2;
--
-- c = yahoo_find_conference(gc, room);
-- if (!c) {
-- g_free(room);
-- return;
-- }
--
-- msg2 = yahoo_string_decode(gc, msg, utf8);
-- msg = yahoo_codes_to_html(msg2);
-- serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)), who, 0, msg, time(NULL));
-- g_free(msg);
-- g_free(msg2);
-- }
--
-- g_free(room);
--}
--
--static void yahoo_chat_join(PurpleConnection *gc, const char *dn, const char *room, const char *topic, const char *id)
--{
-- YahooData *yd = gc->proto_data;
-- struct yahoo_packet *pkt;
-- char *room2;
-- gboolean utf8 = TRUE;
--
-- if (yd->wm) {
-- g_return_if_fail(yd->ycht != NULL);
-- ycht_chat_join(yd->ycht, room);
-- return;
-- }
--
-- /* apparently room names are always utf8, or else always not utf8,
-- * so we don't have to actually pass the flag in the packet. Or something. */
-- room2 = yahoo_string_encode(gc, room, &utf8);
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_CHATJOIN, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash(pkt, "ssss",
-- 1, purple_connection_get_display_name(gc),
-- 104, room2,
-- 62, "2",
-- 129, id ? id : "0");
-- yahoo_packet_send_and_free(pkt, yd);
-- g_free(room2);
--}
--
--/* this is a confirmation of yahoo_chat_online(); */
--void yahoo_process_chat_online(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- YahooData *yd = (YahooData *) gc->proto_data;
--
-- if (pkt->status == 1) {
-- yd->chat_online = TRUE;
--
-- /* We need to goto a user in chat */
-- if (yd->pending_chat_goto) {
-- struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_CHATGOTO, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash(pkt, "sss",
-- 109, yd->pending_chat_goto,
-- 1, purple_connection_get_display_name(gc),
-- 62, "2");
-- yahoo_packet_send_and_free(pkt, yd);
-- } else if (yd->pending_chat_room) {
-- yahoo_chat_join(gc, purple_connection_get_display_name(gc), yd->pending_chat_room,
-- yd->pending_chat_topic, yd->pending_chat_id);
-- }
--
-- g_free(yd->pending_chat_room);
-- yd->pending_chat_room = NULL;
-- g_free(yd->pending_chat_id);
-- yd->pending_chat_id = NULL;
-- g_free(yd->pending_chat_topic);
-- yd->pending_chat_topic = NULL;
-- g_free(yd->pending_chat_goto);
-- yd->pending_chat_goto = NULL;
-- }
--}
--
--/* this is basicly the opposite of chat_online */
--void yahoo_process_chat_logout(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- YahooData *yd = (YahooData *) gc->proto_data;
-- GSList *l;
--
-- for (l = pkt->hash; l; l = l->next) {
-- struct yahoo_pair *pair = l->data;
--
-- if (pair->key == 1)
-- if (g_ascii_strcasecmp(pair->value,
-- purple_connection_get_display_name(gc)))
-- return;
-- }
--
-- if (pkt->status == 1) {
-- yd->chat_online = FALSE;
-- g_free(yd->pending_chat_room);
-- yd->pending_chat_room = NULL;
-- g_free(yd->pending_chat_id);
-- yd->pending_chat_id = NULL;
-- g_free(yd->pending_chat_topic);
-- yd->pending_chat_topic = NULL;
-- g_free(yd->pending_chat_goto);
-- yd->pending_chat_goto = NULL;
-- if (yd->in_chat)
-- yahoo_c_leave(gc, YAHOO_CHAT_ID);
-- }
--}
--
--void yahoo_process_chat_join(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- PurpleAccount *account = purple_connection_get_account(gc);
-- YahooData *yd = (YahooData *) gc->proto_data;
-- PurpleConversation *c = NULL;
-- GSList *l;
-- GList *members = NULL;
-- GList *roomies = NULL;
-- char *room = NULL;
-- char *topic = NULL;
-- char *someid, *someotherid, *somebase64orhashosomething, *somenegativenumber;
--
-- if (pkt->status == -1) {
-- /* We can't join */
-- struct yahoo_pair *pair = pkt->hash->data;
-- gchar const *failed_to_join = _("Failed to join chat");
-- switch (atoi(pair->value)) {
-- case 0xFFFFFFFA: /* -6 */
-- purple_notify_error(gc, NULL, failed_to_join, _("Unknown room"));
-- break;
-- case 0xFFFFFFF1: /* -15 */
-- purple_notify_error(gc, NULL, failed_to_join, _("Maybe the room is full"));
-- break;
-- case 0xFFFFFFDD: /* -35 */
-- purple_notify_error(gc, NULL, failed_to_join, _("Not available"));
-- break;
-- default:
-- purple_notify_error(gc, NULL, failed_to_join,
-- _("Unknown error. You may need to logout and wait five minutes before being able to rejoin a chatroom"));
-- }
-- return;
-- }
--
-- for (l = pkt->hash; l; l = l->next) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
--
-- case 104:
-- g_free(room);
-- room = yahoo_string_decode(gc, pair->value, TRUE);
-- break;
-- case 105:
-- g_free(topic);
-- topic = yahoo_string_decode(gc, pair->value, TRUE);
-- break;
-- case 128:
-- someid = pair->value;
-- break;
-- case 108: /* number of joiners */
-- break;
-- case 129:
-- someotherid = pair->value;
-- break;
-- case 130:
-- somebase64orhashosomething = pair->value;
-- break;
-- case 126:
-- somenegativenumber = pair->value;
-- break;
-- case 13: /* this is 1. maybe its the type of room? (normal, user created, private, etc?) */
-- break;
-- case 61: /*this looks similar to 130 */
-- break;
--
-- /* the previous section was just room info. this next section is
-- info about individual room members, (including us) */
--
-- case 109: /* the yahoo id */
-- members = g_list_append(members, pair->value);
-- break;
-- case 110: /* age */
-- break;
-- case 141: /* nickname */
-- break;
-- case 142: /* location */
-- break;
-- case 113: /* bitmask */
-- break;
-- }
-- }
--
-- if (room && yd->chat_name && purple_utf8_strcasecmp(room, yd->chat_name))
-- yahoo_chat_leave(gc, room,
-- purple_connection_get_display_name(gc), FALSE);
--
-- c = purple_find_chat(gc, YAHOO_CHAT_ID);
--
-- if (room && (!c || purple_conv_chat_has_left(PURPLE_CONV_CHAT(c))) &&
-- members && (members->next ||
-- !g_ascii_strcasecmp(members->data, purple_connection_get_display_name(gc)))) {
-- GList *l;
-- GList *flags = NULL;
-- for (l = members; l; l = l->next)
-- flags = g_list_prepend(flags, GINT_TO_POINTER(PURPLE_CBFLAGS_NONE));
-- if (c && purple_conv_chat_has_left(PURPLE_CONV_CHAT(c))) {
-- /* this might be a hack, but oh well, it should nicely */
-- char *tmpmsg;
--
-- purple_conversation_set_name(c, room);
--
-- c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room);
-- if (topic) {
-- purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic);
-- /* Also print the topic to the backlog so that the captcha link is clickable */
-- purple_conv_chat_write(PURPLE_CONV_CHAT(c), "", topic, PURPLE_MESSAGE_SYSTEM, time(NULL));
-- }
-- yd->in_chat = 1;
-- yd->chat_name = g_strdup(room);
-- purple_conv_chat_add_users(PURPLE_CONV_CHAT(c), members, NULL, flags, FALSE);
--
-- tmpmsg = g_strdup_printf(_("You are now chatting in %s."), room);
-- purple_conv_chat_write(PURPLE_CONV_CHAT(c), "", tmpmsg, PURPLE_MESSAGE_SYSTEM, time(NULL));
-- g_free(tmpmsg);
-- } else {
-- c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room);
-- if (topic) {
-- purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic);
-- /* Also print the topic to the backlog so that the captcha link is clickable */
-- purple_conv_chat_write(PURPLE_CONV_CHAT(c), "", topic, PURPLE_MESSAGE_SYSTEM, time(NULL));
-- }
-- yd->in_chat = 1;
-- yd->chat_name = g_strdup(room);
-- purple_conv_chat_add_users(PURPLE_CONV_CHAT(c), members, NULL, flags, FALSE);
-- }
-- g_list_free(flags);
-- } else if (c) {
-- if (topic) {
-- const char *cur_topic = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(c));
-- if (cur_topic == NULL || strcmp(cur_topic, topic) != 0)
-- purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic);
-- }
-- yahoo_chat_add_users(PURPLE_CONV_CHAT(c), members);
-- }
--
-- if (account->deny && c) {
-- PurpleConversationUiOps *ops = purple_conversation_get_ui_ops(c);
-- for (l = account->deny; l != NULL; l = l->next) {
-- for (roomies = members; roomies; roomies = roomies->next) {
-- if (!purple_utf8_strcasecmp((char *)l->data, roomies->data)) {
-- purple_debug_info("yahoo", "Ignoring room member %s in room %s\n" , (char *)roomies->data, room ? room : "");
-- purple_conv_chat_ignore(PURPLE_CONV_CHAT(c),roomies->data);
-- ops->chat_update_user(c, roomies->data);
-- }
-- }
-- }
-- }
-- g_list_free(roomies);
-- g_list_free(members);
-- g_free(room);
-- g_free(topic);
--}
--
--void yahoo_process_chat_exit(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- char *who = NULL;
-- char *room = NULL;
-- GSList *l;
--
-- for (l = pkt->hash; l; l = l->next) {
-- struct yahoo_pair *pair = l->data;
--
-- if (pair->key == 104) {
-- g_free(room);
-- room = yahoo_string_decode(gc, pair->value, TRUE);
-- }
-- if (pair->key == 109)
-- who = pair->value;
-- }
--
-- if (who && room) {
-- PurpleConversation *c = purple_find_chat(gc, YAHOO_CHAT_ID);
-- if (c && !purple_utf8_strcasecmp(purple_conversation_get_name(c), room))
-- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(c), who, NULL);
--
-- }
-- g_free(room);
--}
--
--void yahoo_process_chat_message(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- char *room = NULL, *who = NULL, *msg = NULL, *msg2;
-- int msgtype = 1, utf8 = 1; /* default to utf8 */
-- PurpleConversation *c = NULL;
-- GSList *l;
--
-- for (l = pkt->hash; l; l = l->next) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
--
-- case 97:
-- utf8 = strtol(pair->value, NULL, 10);
-- break;
-- case 104:
-- g_free(room);
-- room = yahoo_string_decode(gc, pair->value, TRUE);
-- break;
-- case 109:
-- who = pair->value;
-- break;
-- case 117:
-- msg = pair->value;
-- break;
-- case 124:
-- msgtype = strtol(pair->value, NULL, 10);
-- break;
-- }
-- }
--
-- c = purple_find_chat(gc, YAHOO_CHAT_ID);
-- if (!who || !c) {
-- if (room)
-- g_free(room);
-- /* we still get messages after we part, funny that */
-- return;
-- }
--
-- if (!msg) {
-- purple_debug_misc("yahoo", "Got a message packet with no message.\nThis probably means something important, but we're ignoring it.\n");
-- return;
-- }
-- msg2 = yahoo_string_decode(gc, msg, utf8);
-- msg = yahoo_codes_to_html(msg2);
-- g_free(msg2);
--
-- if (msgtype == 2 || msgtype == 3) {
-- char *tmp;
-- tmp = g_strdup_printf("/me %s", msg);
-- g_free(msg);
-- msg = tmp;
-- }
--
-- serv_got_chat_in(gc, YAHOO_CHAT_ID, who, 0, msg, time(NULL));
-- g_free(msg);
-- g_free(room);
--}
--
--void yahoo_process_chat_addinvite(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- PurpleAccount *account;
-- GSList *l;
-- char *room = NULL;
-- char *msg = NULL;
-- char *who = NULL;
--
-- account = purple_connection_get_account(gc);
--
-- for (l = pkt->hash; l; l = l->next) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 104:
-- g_free(room);
-- room = yahoo_string_decode(gc, pair->value, TRUE);
-- break;
-- case 129: /* room id? */
-- break;
-- case 126: /* ??? */
-- break;
-- case 117:
-- g_free(msg);
-- msg = yahoo_string_decode(gc, pair->value, FALSE);
-- break;
-- case 119:
-- who = pair->value;
-- break;
-- case 118: /* us */
-- break;
-- }
-- }
--
-- if (room && who) {
-- GHashTable *components;
--
-- if (!purple_privacy_check(account, who) ||
-- (purple_account_get_bool(account, "ignore_invites", FALSE)))
-- {
-- purple_debug_info("yahoo", "Invite to room %s from %s has been dropped.\n", room, who);
-- g_free(room);
-- g_free(msg);
-- return;
-- }
--
-- components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-- g_hash_table_replace(components, g_strdup("room"), g_strdup(room));
-- serv_got_chat_invite(gc, room, who, msg, components);
-- }
--
-- g_free(room);
-- g_free(msg);
--}
--
--void yahoo_process_chat_goto(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- if (pkt->status == -1)
-- purple_notify_error(gc, NULL, _("Failed to join buddy in chat"),
-- _("Maybe they're not in a chat?"));
--}
--
--/*
-- * Functions dealing with conferences
-- * I think conference names are always ascii.
-- */
--
--void yahoo_conf_leave(YahooData *yd, const char *room, const char *dn, GList *who)
--{
-- struct yahoo_packet *pkt;
-- GList *w;
--
-- purple_debug_misc("yahoo", "leaving conference %s\n", room);
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGOFF, YAHOO_STATUS_AVAILABLE, yd->session_id);
--
-- yahoo_packet_hash_str(pkt, 1, dn);
-- for (w = who; w; w = w->next) {
-- const char *name = purple_conv_chat_cb_get_name(w->data);
-- yahoo_packet_hash_str(pkt, 3, name);
-- }
--
-- yahoo_packet_hash_str(pkt, 57, room);
-- yahoo_packet_send_and_free(pkt, yd);
--}
--
--static int yahoo_conf_send(PurpleConnection *gc, const char *dn, const char *room,
-- GList *members, const char *what)
--{
-- YahooData *yd = gc->proto_data;
-- struct yahoo_packet *pkt;
-- GList *who;
-- char *msg, *msg2;
-- int utf8 = 1;
--
-- msg = yahoo_html_to_codes(what);
-- msg2 = yahoo_string_encode(gc, msg, &utf8);
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_CONFMSG, YAHOO_STATUS_AVAILABLE, yd->session_id);
--
-- yahoo_packet_hash_str(pkt, 1, dn);
-- for (who = members; who; who = who->next) {
-- const char *name = purple_conv_chat_cb_get_name(who->data);
-- yahoo_packet_hash_str(pkt, 53, name);
-- }
-- yahoo_packet_hash(pkt, "ss", 57, room, 14, msg2);
-- if (utf8)
-- yahoo_packet_hash_str(pkt, 97, "1"); /* utf-8 */
--
-- yahoo_packet_send_and_free(pkt, yd);
-- g_free(msg);
-- g_free(msg2);
--
-- return 0;
--}
--
--static void yahoo_conf_join(YahooData *yd, PurpleConversation *c, const char *dn, const char *room,
-- const char *topic, const char *members)
--{
-- struct yahoo_packet *pkt;
-- char **memarr = NULL;
-- int i;
--
-- if (members)
-- memarr = g_strsplit(members, "\n", 0);
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGON, YAHOO_STATUS_AVAILABLE, yd->session_id);
--
-- yahoo_packet_hash(pkt, "sss", 1, dn, 3, dn, 57, room);
-- if (memarr) {
-- for(i = 0 ; memarr[i]; i++) {
-- if (!strcmp(memarr[i], "") || !strcmp(memarr[i], dn))
-- continue;
-- yahoo_packet_hash_str(pkt, 3, memarr[i]);
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(c), memarr[i], NULL, PURPLE_CBFLAGS_NONE, TRUE);
-- }
-- }
-- yahoo_packet_send_and_free(pkt, yd);
--
-- if (memarr)
-- g_strfreev(memarr);
--}
--
--static void yahoo_conf_invite(PurpleConnection *gc, PurpleConversation *c,
-- const char *dn, const char *buddy, const char *room, const char *msg)
--{
-- YahooData *yd = gc->proto_data;
-- struct yahoo_packet *pkt;
-- GList *members;
-- char *msg2 = NULL;
--
-- if (msg)
-- msg2 = yahoo_string_encode(gc, msg, NULL);
--
-- members = purple_conv_chat_get_users(PURPLE_CONV_CHAT(c));
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_CONFADDINVITE, YAHOO_STATUS_AVAILABLE, yd->session_id);
--
-- yahoo_packet_hash(pkt, "sssss", 1, dn, 51, buddy, 57, room, 58, msg?msg2:"", 13, "0");
-- for(; members; members = members->next) {
-- const char *name = purple_conv_chat_cb_get_name(members->data);
-- if (!strcmp(name, dn))
-- continue;
-- yahoo_packet_hash(pkt, "ss", 52, name, 53, name);
-- }
--
-- yahoo_packet_send_and_free(pkt, yd);
-- g_free(msg2);
--}
--
--/*
-- * Functions dealing with chats
-- */
--
--static void yahoo_chat_leave(PurpleConnection *gc, const char *room, const char *dn, gboolean logout)
--{
-- YahooData *yd = gc->proto_data;
-- struct yahoo_packet *pkt;
--
-- char *eroom;
-- gboolean utf8 = 1;
--
-- if (yd->wm) {
-- g_return_if_fail(yd->ycht != NULL);
--
-- ycht_chat_leave(yd->ycht, room, logout);
-- return;
-- }
--
-- eroom = yahoo_string_encode(gc, room, &utf8);
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_CHATEXIT, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash(pkt, "sss", 104, eroom, 109, dn, 108, "1");
-- yahoo_packet_hash_str(pkt, 112, "0"); /* what does this one mean? */
-- yahoo_packet_send_and_free(pkt, yd);
--
-- yd->in_chat = 0;
-- if (yd->chat_name) {
-- g_free(yd->chat_name);
-- yd->chat_name = NULL;
-- }
--
-- if (purple_find_chat(gc, YAHOO_CHAT_ID) != NULL)
-- serv_got_chat_left(gc, YAHOO_CHAT_ID);
--
-- if (!logout)
-- return;
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_CHATLOGOUT,
-- YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash_str(pkt, 1, dn);
-- yahoo_packet_send_and_free(pkt, yd);
--
-- yd->chat_online = FALSE;
-- g_free(yd->pending_chat_room);
-- yd->pending_chat_room = NULL;
-- g_free(yd->pending_chat_id);
-- yd->pending_chat_id = NULL;
-- g_free(yd->pending_chat_topic);
-- yd->pending_chat_topic = NULL;
-- g_free(yd->pending_chat_goto);
-- yd->pending_chat_goto = NULL;
-- g_free(eroom);
--}
--
--static int yahoo_chat_send(PurpleConnection *gc, const char *dn, const char *room, const char *what, PurpleMessageFlags flags)
--{
-- YahooData *yd = gc->proto_data;
-- struct yahoo_packet *pkt;
-- int me = 0;
-- char *msg1, *msg2, *room2;
-- gboolean utf8 = TRUE;
--
-- if (yd->wm) {
-- g_return_val_if_fail(yd->ycht != NULL, 1);
--
-- return ycht_chat_send(yd->ycht, room, what);
-- }
--
-- msg1 = g_strdup(what);
--
-- if (purple_message_meify(msg1, -1))
-- me = 1;
--
-- msg2 = yahoo_html_to_codes(msg1);
-- g_free(msg1);
-- msg1 = yahoo_string_encode(gc, msg2, &utf8);
-- g_free(msg2);
-- room2 = yahoo_string_encode(gc, room, NULL);
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_COMMENT, YAHOO_STATUS_AVAILABLE, yd->session_id);
--
-- yahoo_packet_hash(pkt, "sss", 1, dn, 104, room2, 117, msg1);
-- if (me)
-- yahoo_packet_hash_str(pkt, 124, "2");
-- else
-- yahoo_packet_hash_str(pkt, 124, "1");
-- /* fixme: what about /think? (124=3) */
-- if (utf8)
-- yahoo_packet_hash_str(pkt, 97, "1");
--
-- yahoo_packet_send_and_free(pkt, yd);
-- g_free(msg1);
-- g_free(room2);
--
-- return 0;
--}
--
--
--static void yahoo_chat_invite(PurpleConnection *gc, const char *dn, const char *buddy,
-- const char *room, const char *msg)
--{
-- YahooData *yd = gc->proto_data;
-- struct yahoo_packet *pkt;
-- char *room2, *msg2 = NULL;
-- gboolean utf8 = TRUE;
--
-- if (yd->wm) {
-- g_return_if_fail(yd->ycht != NULL);
-- ycht_chat_send_invite(yd->ycht, room, buddy, msg);
-- return;
-- }
--
-- room2 = yahoo_string_encode(gc, room, &utf8);
-- if (msg)
-- msg2 = yahoo_string_encode(gc, msg, NULL);
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_CHATADDINVITE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash(pkt, "sssss", 1, dn, 118, buddy, 104, room2, 117, (msg2?msg2:""), 129, "0");
-- yahoo_packet_send_and_free(pkt, yd);
--
-- g_free(room2);
-- g_free(msg2);
--}
--
--void yahoo_chat_goto(PurpleConnection *gc, const char *name)
--{
-- YahooData *yd;
-- struct yahoo_packet *pkt;
--
-- yd = gc->proto_data;
--
-- if (yd->wm) {
-- g_return_if_fail(yd->ycht != NULL);
-- ycht_chat_goto_user(yd->ycht, name);
-- return;
-- }
--
-- if (!yd->chat_online) {
-- yahoo_chat_online(gc);
-- g_free(yd->pending_chat_room);
-- yd->pending_chat_room = NULL;
-- g_free(yd->pending_chat_id);
-- yd->pending_chat_id = NULL;
-- g_free(yd->pending_chat_topic);
-- yd->pending_chat_topic = NULL;
-- g_free(yd->pending_chat_goto);
-- yd->pending_chat_goto = g_strdup(name);
-- return;
-- }
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_CHATGOTO, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash(pkt, "sss", 109, name, 1, purple_connection_get_display_name(gc), 62, "2");
-- yahoo_packet_send_and_free(pkt, yd);
--}
--/*
-- * These are the functions registered with the core
-- * which get called for both chats and conferences.
-- */
--
--void yahoo_c_leave(PurpleConnection *gc, int id)
--{
-- YahooData *yd = (YahooData *) gc->proto_data;
-- PurpleConversation *c;
--
-- if (!yd)
-- return;
--
-- c = purple_find_chat(gc, id);
-- if (!c)
-- return;
--
-- if (id != YAHOO_CHAT_ID) {
-- yahoo_conf_leave(yd, purple_conversation_get_name(c),
-- purple_connection_get_display_name(gc), purple_conv_chat_get_users(PURPLE_CONV_CHAT(c)));
-- yd->confs = g_slist_remove(yd->confs, c);
-- } else {
-- yahoo_chat_leave(gc, purple_conversation_get_name(c), purple_connection_get_display_name(gc), TRUE);
-- }
--
-- serv_got_chat_left(gc, id);
--}
--
--int yahoo_c_send(PurpleConnection *gc, int id, const char *what, PurpleMessageFlags flags)
--{
-- PurpleConversation *c;
-- int ret;
-- YahooData *yd;
--
-- yd = (YahooData *) gc->proto_data;
-- if (!yd)
-- return -1;
--
-- c = purple_find_chat(gc, id);
-- if (!c)
-- return -1;
--
-- if (id != YAHOO_CHAT_ID) {
-- ret = yahoo_conf_send(gc, purple_connection_get_display_name(gc),
-- purple_conversation_get_name(c), purple_conv_chat_get_users(PURPLE_CONV_CHAT(c)), what);
-- } else {
-- ret = yahoo_chat_send(gc, purple_connection_get_display_name(gc),
-- purple_conversation_get_name(c), what, flags);
-- if (!ret)
-- serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)),
-- purple_connection_get_display_name(gc), flags, what, time(NULL));
-- }
-- return ret;
--}
--
--GList *yahoo_c_info(PurpleConnection *gc)
--{
-- GList *m = NULL;
-- struct proto_chat_entry *pce;
--
-- pce = g_new0(struct proto_chat_entry, 1);
-- pce->label = _("_Room:");
-- pce->identifier = "room";
-- pce->required = TRUE;
-- m = g_list_append(m, pce);
--
-- return m;
--}
--
--GHashTable *yahoo_c_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, "room", g_strdup(chat_name));
--
-- return defaults;
--}
--
--char *yahoo_get_chat_name(GHashTable *data)
--{
-- return g_strdup(g_hash_table_lookup(data, "room"));
--}
--
--void yahoo_c_join(PurpleConnection *gc, GHashTable *data)
--{
-- YahooData *yd;
-- char *room, *topic, *type;
-- PurpleConversation *c;
--
-- yd = (YahooData *) gc->proto_data;
-- if (!yd)
-- return;
--
-- room = g_hash_table_lookup(data, "room");
-- if (!room)
-- return;
--
-- topic = g_hash_table_lookup(data, "topic");
-- if (!topic)
-- topic = "";
--
-- if ((type = g_hash_table_lookup(data, "type")) && !strcmp(type, "Conference")) {
-- int id;
-- const char *members = g_hash_table_lookup(data, "members");
-- id = yd->conf_id++;
-- c = serv_got_joined_chat(gc, id, room);
-- yd->confs = g_slist_prepend(yd->confs, c);
-- purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), purple_connection_get_display_name(gc), topic);
-- yahoo_conf_join(yd, c, purple_connection_get_display_name(gc), room, topic, members);
-- return;
-- } else {
-- const char *id;
-- /*if (yd->in_chat)
-- yahoo_chat_leave(gc, room,
-- purple_connection_get_display_name(gc),
-- FALSE);*/
--
-- id = g_hash_table_lookup(data, "id");
--
-- if (!yd->chat_online) {
-- yahoo_chat_online(gc);
-- g_free(yd->pending_chat_room);
-- yd->pending_chat_room = g_strdup(room);
-- g_free(yd->pending_chat_id);
-- yd->pending_chat_id = g_strdup(id);
-- g_free(yd->pending_chat_topic);
-- yd->pending_chat_topic = g_strdup(topic);
-- g_free(yd->pending_chat_goto);
-- yd->pending_chat_goto = NULL;
-- } else {
-- yahoo_chat_join(gc, purple_connection_get_display_name(gc), room, topic, id);
-- }
-- return;
-- }
--}
--
--void yahoo_c_invite(PurpleConnection *gc, int id, const char *msg, const char *name)
--{
-- PurpleConversation *c;
--
-- c = purple_find_chat(gc, id);
-- if (!c || !c->name)
-- return;
--
-- if (id != YAHOO_CHAT_ID) {
-- yahoo_conf_invite(gc, c, purple_connection_get_display_name(gc), name,
-- purple_conversation_get_name(c), msg);
-- } else {
-- yahoo_chat_invite(gc, purple_connection_get_display_name(gc), name,
-- purple_conversation_get_name(c), msg);
-- }
--}
--
--struct yahoo_roomlist {
-- int fd;
-- int inpa;
-- gchar *txbuf;
-- gsize tx_written;
-- guchar *rxqueue;
-- int rxlen;
-- gboolean started;
-- char *path;
-- char *host;
-- PurpleRoomlist *list;
-- PurpleRoomlistRoom *cat;
-- PurpleRoomlistRoom *ucat;
-- GMarkupParseContext *parse;
--};
--
--static void yahoo_roomlist_destroy(struct yahoo_roomlist *yrl)
--{
-- if (yrl->inpa)
-- purple_input_remove(yrl->inpa);
-- g_free(yrl->txbuf);
-- g_free(yrl->rxqueue);
-- g_free(yrl->path);
-- g_free(yrl->host);
-- if (yrl->parse)
-- g_markup_parse_context_free(yrl->parse);
-- g_free(yrl);
--}
--
--enum yahoo_room_type {
-- yrt_yahoo,
-- yrt_user
--};
--
--struct yahoo_chatxml_state {
-- PurpleRoomlist *list;
-- struct yahoo_roomlist *yrl;
-- GQueue *q;
-- struct {
-- enum yahoo_room_type type;
-- char *name;
-- char *topic;
-- char *id;
-- int users, voices, webcams;
-- } room;
--};
--
--struct yahoo_lobby {
-- int count, users, voices, webcams;
--};
--
--static struct yahoo_chatxml_state *yahoo_chatxml_state_new(PurpleRoomlist *list, struct yahoo_roomlist *yrl)
--{
-- struct yahoo_chatxml_state *s;
--
-- s = g_new0(struct yahoo_chatxml_state, 1);
-- s->list = list;
-- s->yrl = yrl;
-- s->q = g_queue_new();
--
-- return s;
--}
--
--static void yahoo_chatxml_state_destroy(struct yahoo_chatxml_state *s)
--{
-- g_queue_free(s->q);
-- g_free(s->room.name);
-- g_free(s->room.topic);
-- g_free(s->room.id);
-- g_free(s);
--}
--
--static void yahoo_chatlist_start_element(GMarkupParseContext *context,
-- const gchar *ename, const gchar **anames,
-- const gchar **avalues, gpointer user_data,
-- GError **error)
--{
-- struct yahoo_chatxml_state *s = user_data;
-- PurpleRoomlist *list = s->list;
-- PurpleRoomlistRoom *r;
-- PurpleRoomlistRoom *parent;
-- int i;
--
-- if (!strcmp(ename, "category")) {
-- const gchar *name = NULL, *id = NULL;
--
-- for (i = 0; anames[i]; i++) {
-- if (!strcmp(anames[i], "id"))
-- id = avalues[i];
-- if (!strcmp(anames[i], "name"))
-- name = avalues[i];
-- }
-- if (!name || !id)
-- return;
--
-- parent = g_queue_peek_head(s->q);
-- r = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY, name, parent);
-- purple_roomlist_room_add_field(list, r, (gpointer)name);
-- purple_roomlist_room_add_field(list, r, (gpointer)id);
-- purple_roomlist_room_add(list, r);
-- g_queue_push_head(s->q, r);
-- } else if (!strcmp(ename, "room")) {
-- s->room.users = s->room.voices = s->room.webcams = 0;
--
-- for (i = 0; anames[i]; i++) {
-- if (!strcmp(anames[i], "id")) {
-- g_free(s->room.id);
-- s->room.id = g_strdup(avalues[i]);
-- } else if (!strcmp(anames[i], "name")) {
-- g_free(s->room.name);
-- s->room.name = g_strdup(avalues[i]);
-- } else if (!strcmp(anames[i], "topic")) {
-- g_free(s->room.topic);
-- s->room.topic = g_strdup(avalues[i]);
-- } else if (!strcmp(anames[i], "type")) {
-- if (!strcmp("yahoo", avalues[i]))
-- s->room.type = yrt_yahoo;
-- else
-- s->room.type = yrt_user;
-- }
-- }
--
-- } else if (!strcmp(ename, "lobby")) {
-- struct yahoo_lobby *lob = g_new0(struct yahoo_lobby, 1);
--
-- for (i = 0; anames[i]; i++) {
-- if (!strcmp(anames[i], "count")) {
-- lob->count = strtol(avalues[i], NULL, 10);
-- } else if (!strcmp(anames[i], "users")) {
-- s->room.users += lob->users = strtol(avalues[i], NULL, 10);
-- } else if (!strcmp(anames[i], "voices")) {
-- s->room.voices += lob->voices = strtol(avalues[i], NULL, 10);
-- } else if (!strcmp(anames[i], "webcams")) {
-- s->room.webcams += lob->webcams = strtol(avalues[i], NULL, 10);
-- }
-- }
-- g_queue_push_head(s->q, lob);
-- }
--}
--
--static void yahoo_chatlist_end_element(GMarkupParseContext *context, const gchar *ename,
-- gpointer user_data, GError **error)
--{
-- struct yahoo_chatxml_state *s = user_data;
--
-- if (!strcmp(ename, "category")) {
-- g_queue_pop_head(s->q);
-- } else if (!strcmp(ename, "room")) {
-- struct yahoo_lobby *lob;
-- PurpleRoomlistRoom *r, *l;
--
-- if (s->room.type == yrt_yahoo)
-- r = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY|PURPLE_ROOMLIST_ROOMTYPE_ROOM,
-- s->room.name, s->yrl->cat);
-- else
-- r = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY|PURPLE_ROOMLIST_ROOMTYPE_ROOM,
-- s->room.name, s->yrl->ucat);
--
-- purple_roomlist_room_add_field(s->list, r, s->room.name);
-- purple_roomlist_room_add_field(s->list, r, s->room.id);
-- purple_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.users));
-- purple_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.voices));
-- purple_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.webcams));
-- purple_roomlist_room_add_field(s->list, r, s->room.topic);
-- purple_roomlist_room_add(s->list, r);
--
-- while ((lob = g_queue_pop_head(s->q))) {
-- char *name = g_strdup_printf("%s:%d", s->room.name, lob->count);
-- l = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, name, r);
--
-- purple_roomlist_room_add_field(s->list, l, name);
-- purple_roomlist_room_add_field(s->list, l, s->room.id);
-- purple_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->users));
-- purple_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->voices));
-- purple_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->webcams));
-- purple_roomlist_room_add_field(s->list, l, s->room.topic);
-- purple_roomlist_room_add(s->list, l);
--
-- g_free(name);
-- g_free(lob);
-- }
-- }
--}
--
--static GMarkupParser parser = {
-- yahoo_chatlist_start_element,
-- yahoo_chatlist_end_element,
-- NULL,
-- NULL,
-- NULL
--};
--
--static void yahoo_roomlist_cleanup(PurpleRoomlist *list, struct yahoo_roomlist *yrl)
--{
-- purple_roomlist_set_in_progress(list, FALSE);
--
-- if (yrl) {
-- list->proto_data = g_list_remove(list->proto_data, yrl);
-- yahoo_roomlist_destroy(yrl);
-- }
--
-- purple_roomlist_unref(list);
--}
--
--static void yahoo_roomlist_pending(gpointer data, gint source, PurpleInputCondition cond)
--{
-- struct yahoo_roomlist *yrl = data;
-- PurpleRoomlist *list = yrl->list;
-- char buf[1024];
-- int len;
-- guchar *start;
-- struct yahoo_chatxml_state *s;
--
-- len = read(yrl->fd, buf, sizeof(buf));
--
-- if (len < 0 && errno == EAGAIN)
-- return;
--
-- if (len <= 0) {
-- if (yrl->parse)
-- g_markup_parse_context_end_parse(yrl->parse, NULL);
-- yahoo_roomlist_cleanup(list, yrl);
-- return;
-- }
--
-- yrl->rxqueue = g_realloc(yrl->rxqueue, len + yrl->rxlen);
-- memcpy(yrl->rxqueue + yrl->rxlen, buf, len);
-- yrl->rxlen += len;
--
-- if (!yrl->started) {
-- yrl->started = TRUE;
-- start = (guchar *)g_strstr_len((char *)yrl->rxqueue, yrl->rxlen, "\r\n\r\n");
-- if (!start || (start - yrl->rxqueue + 4) >= yrl->rxlen)
-- return;
-- start += 4;
-- } else {
-- start = yrl->rxqueue;
-- }
--
-- if (yrl->parse == NULL) {
-- s = yahoo_chatxml_state_new(list, yrl);
-- yrl->parse = g_markup_parse_context_new(&parser, 0, s,
-- (GDestroyNotify)yahoo_chatxml_state_destroy);
-- }
--
-- if (!g_markup_parse_context_parse(yrl->parse, (char *)start, (yrl->rxlen - (start - yrl->rxqueue)), NULL)) {
--
-- yahoo_roomlist_cleanup(list, yrl);
-- return;
-- }
--
-- yrl->rxlen = 0;
--}
--
--static void yahoo_roomlist_send_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- struct yahoo_roomlist *yrl;
-- PurpleRoomlist *list;
-- int written, remaining;
--
-- yrl = data;
-- list = yrl->list;
--
-- remaining = strlen(yrl->txbuf) - yrl->tx_written;
-- written = write(yrl->fd, yrl->txbuf + yrl->tx_written, remaining);
--
-- if (written < 0 && errno == EAGAIN)
-- written = 0;
-- else if (written <= 0) {
-- purple_input_remove(yrl->inpa);
-- yrl->inpa = 0;
-- g_free(yrl->txbuf);
-- yrl->txbuf = NULL;
-- purple_notify_error(purple_account_get_connection(list->account), NULL, _("Unable to connect"), _("Fetching the room list failed."));
-- yahoo_roomlist_cleanup(list, yrl);
-- return;
-- }
--
-- if (written < remaining) {
-- yrl->tx_written += written;
-- return;
-- }
--
-- g_free(yrl->txbuf);
-- yrl->txbuf = NULL;
--
-- purple_input_remove(yrl->inpa);
-- yrl->inpa = purple_input_add(yrl->fd, PURPLE_INPUT_READ,
-- yahoo_roomlist_pending, yrl);
--
--}
--
--static void yahoo_roomlist_got_connected(gpointer data, gint source, const gchar *error_message)
--{
-- struct yahoo_roomlist *yrl = data;
-- PurpleRoomlist *list = yrl->list;
-- YahooData *yd = purple_account_get_connection(list->account)->proto_data;
--
-- if (source < 0) {
-- purple_notify_error(purple_account_get_connection(list->account), NULL, _("Unable to connect"), _("Fetching the room list failed."));
-- yahoo_roomlist_cleanup(list, yrl);
-- return;
-- }
--
-- yrl->fd = source;
--
-- yrl->txbuf = g_strdup_printf(
-- "GET http://%s/%s HTTP/1.0\r\n"
-- "Host: %s\r\n"
-- "Cookie: Y=%s; T=%s\r\n\r\n",
-- yrl->host, yrl->path, yrl->host, yd->cookie_y,
-- yd->cookie_t);
--
--
-- yrl->inpa = purple_input_add(yrl->fd, PURPLE_INPUT_WRITE,
-- yahoo_roomlist_send_cb, yrl);
-- yahoo_roomlist_send_cb(yrl, yrl->fd, PURPLE_INPUT_WRITE);
--}
--
--PurpleRoomlist *yahoo_roomlist_get_list(PurpleConnection *gc)
--{
-- PurpleAccount *account;
-- PurpleRoomlist *rl;
-- PurpleRoomlistField *f;
-- GList *fields = NULL;
-- struct yahoo_roomlist *yrl;
-- const char *rll, *rlurl;
-- char *url;
--
-- account = purple_connection_get_account(gc);
--
-- /* for Yahoo Japan, it appears there is only one valid URL and locale */
-- if(purple_account_get_bool(account, "yahoojp", FALSE)) {
-- rll = YAHOOJP_ROOMLIST_LOCALE;
-- rlurl = YAHOOJP_ROOMLIST_URL;
-- }
-- else { /* but for the rest of the world that isn't the case */
-- rll = purple_account_get_string(account, "room_list_locale", YAHOO_ROOMLIST_LOCALE);
-- rlurl = purple_account_get_string(account, "room_list", YAHOO_ROOMLIST_URL);
-- }
--
-- url = g_strdup_printf("%s?chatcat=0&intl=%s", rlurl, rll);
--
-- yrl = g_new0(struct yahoo_roomlist, 1);
-- rl = purple_roomlist_new(account);
-- yrl->list = rl;
--
-- purple_url_parse(url, &(yrl->host), NULL, &(yrl->path), NULL, NULL);
-- g_free(url);
--
-- f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", "room", TRUE);
-- fields = g_list_append(fields, f);
--
-- f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", "id", 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_INT, _("Voices"), "voices", FALSE);
-- fields = g_list_append(fields, f);
--
-- f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_INT, _("Webcams"), "webcams", 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(rl, fields);
--
-- if (purple_proxy_connect(gc, account, yrl->host, 80,
-- yahoo_roomlist_got_connected, yrl) == NULL)
-- {
-- purple_notify_error(gc, NULL, _("Connection problem"), _("Unable to fetch room list."));
-- yahoo_roomlist_cleanup(rl, yrl);
-- return NULL;
-- }
--
-- rl->proto_data = g_list_append(rl->proto_data, yrl);
--
-- purple_roomlist_set_in_progress(rl, TRUE);
-- return rl;
--}
--
--void yahoo_roomlist_cancel(PurpleRoomlist *list)
--{
-- GList *l, *k;
--
-- k = l = list->proto_data;
-- list->proto_data = NULL;
--
-- purple_roomlist_set_in_progress(list, FALSE);
--
-- for (; l; l = l->next) {
-- yahoo_roomlist_destroy(l->data);
-- purple_roomlist_unref(list);
-- }
-- g_list_free(k);
--}
--
--void yahoo_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category)
--{
-- struct yahoo_roomlist *yrl;
-- char *url;
-- char *id;
-- const char *rll;
--
-- if (category->type != PURPLE_ROOMLIST_ROOMTYPE_CATEGORY)
-- return;
--
-- if (!(id = g_list_nth_data(category->fields, 1))) {
-- purple_roomlist_set_in_progress(list, FALSE);
-- return;
-- }
--
-- rll = purple_account_get_string(list->account, "room_list_locale",
-- YAHOO_ROOMLIST_LOCALE);
--
-- if (rll != NULL && *rll != '\0') {
-- url = g_strdup_printf("%s?chatroom_%s=0&intl=%s",
-- purple_account_get_string(list->account,"room_list",
-- YAHOO_ROOMLIST_URL), id, rll);
-- } else {
-- url = g_strdup_printf("%s?chatroom_%s=0",
-- purple_account_get_string(list->account,"room_list",
-- YAHOO_ROOMLIST_URL), id);
-- }
--
-- yrl = g_new0(struct yahoo_roomlist, 1);
-- yrl->list = list;
-- yrl->cat = category;
-- list->proto_data = g_list_append(list->proto_data, yrl);
--
-- purple_url_parse(url, &(yrl->host), NULL, &(yrl->path), NULL, NULL);
-- g_free(url);
--
-- yrl->ucat = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY, _("User Rooms"), yrl->cat);
-- purple_roomlist_room_add(list, yrl->ucat);
--
-- if (purple_proxy_connect(purple_account_get_connection(list->account),
-- list->account, yrl->host, 80,
-- yahoo_roomlist_got_connected, yrl) == NULL)
-- {
-- purple_notify_error(purple_account_get_connection(list->account),
-- NULL, _("Connection problem"), _("Unable to fetch room list."));
-- purple_roomlist_ref(list);
-- yahoo_roomlist_cleanup(list, yrl);
-- return;
-- }
--
-- purple_roomlist_set_in_progress(list, TRUE);
-- purple_roomlist_ref(list);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoochat.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoochat.h
---- pidgin-2.10.7/libpurple/protocols/yahoo/yahoochat.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoochat.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,66 +0,0 @@
--/**
-- * @file yahoochat.h The Yahoo! protocol plugin, chat and conference stuff
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _YAHOOCHAT_H_
--#define _YAHOOCHAT_H_
--
--#include "roomlist.h"
--#include "yahoo_packet.h"
--
--void yahoo_process_conference_invite(PurpleConnection *gc, struct yahoo_packet *pkt);
--void yahoo_process_conference_decline(PurpleConnection *gc, struct yahoo_packet *pkt);
--void yahoo_process_conference_logon(PurpleConnection *gc, struct yahoo_packet *pkt);
--void yahoo_process_conference_logoff(PurpleConnection *gc, struct yahoo_packet *pkt);
--void yahoo_process_conference_message(PurpleConnection *gc, struct yahoo_packet *pkt);
--
--void yahoo_process_chat_online(PurpleConnection *gc, struct yahoo_packet *pkt);
--void yahoo_process_chat_logout(PurpleConnection *gc, struct yahoo_packet *pkt);
--void yahoo_process_chat_join(PurpleConnection *gc, struct yahoo_packet *pkt);
--void yahoo_process_chat_exit(PurpleConnection *gc, struct yahoo_packet *pkt);
--void yahoo_process_chat_message(PurpleConnection *gc, struct yahoo_packet *pkt);
--void yahoo_process_chat_addinvite(PurpleConnection *gc, struct yahoo_packet *pkt);
--void yahoo_process_chat_goto(PurpleConnection *gc, struct yahoo_packet *pkt);
--
--void yahoo_c_leave(PurpleConnection *gc, int id);
--int yahoo_c_send(PurpleConnection *gc, int id, const char *what, PurpleMessageFlags flags);
--GList *yahoo_c_info(PurpleConnection *gc);
--GHashTable *yahoo_c_info_defaults(PurpleConnection *gc, const char *chat_name);
--void yahoo_c_join(PurpleConnection *gc, GHashTable *data);
--char *yahoo_get_chat_name(GHashTable *data);
--void yahoo_c_invite(PurpleConnection *gc, int id, const char *msg, const char *name);
--
--void yahoo_conf_leave(YahooData *yd, const char *room, const char *dn, GList *who);
--
--void yahoo_chat_goto(PurpleConnection *gc, const char *name);
--
--/* room listing functions */
--PurpleRoomlist *yahoo_roomlist_get_list(PurpleConnection *gc);
--void yahoo_roomlist_cancel(PurpleRoomlist *list);
--void yahoo_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category);
--
--/* util */
--void yahoo_chat_add_users(PurpleConvChat *chat, GList *newusers);
--void yahoo_chat_add_user(PurpleConvChat *chat, const char *user, const char *reason);
--
--#endif /* _YAHOO_CHAT_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_doodle.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_doodle.c
---- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_doodle.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_doodle.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,611 +0,0 @@
--/*
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--/******************************************************************************
-- * INCLUDES
-- *****************************************************************************/
--#include "internal.h"
--
--#include "account.h"
--#include "accountopt.h"
--#include "blist.h"
--#include "cipher.h"
--#include "cmds.h"
--#include "debug.h"
--#include "notify.h"
--#include "privacy.h"
--#include "prpl.h"
--#include "proxy.h"
--#include "request.h"
--#include "server.h"
--#include "util.h"
--#include "version.h"
--
--#include "libymsg.h"
--#include "yahoo_packet.h"
--#include "yahoo_friend.h"
--#include "yahoochat.h"
--#include "ycht.h"
--#include "yahoo_filexfer.h"
--#include "yahoo_picture.h"
--
--#include "whiteboard.h"
--#include "yahoo_doodle.h"
--
--/******************************************************************************
-- * Globals
-- *****************************************************************************/
--#if 0
--const int DefaultColorRGB24[] =
--{
-- DOODLE_COLOR_RED,
-- DOODLE_COLOR_ORANGE,
-- DOODLE_COLOR_YELLOW,
-- DOODLE_COLOR_GREEN,
-- DOODLE_COLOR_CYAN,
-- DOODLE_COLOR_BLUE,
-- DOODLE_COLOR_VIOLET,
-- DOODLE_COLOR_PURPLE,
-- DOODLE_COLOR_TAN,
-- DOODLE_COLOR_BROWN,
-- DOODLE_COLOR_BLACK,
-- DOODLE_COLOR_GREY,
-- DOODLE_COLOR_WHITE
--};
--#endif
--
--/******************************************************************************
-- * Functions
-- *****************************************************************************/
--PurpleCmdRet yahoo_doodle_purple_cmd_start(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data)
--{
-- PurpleAccount *account;
-- PurpleConnection *gc;
-- const gchar *name;
--
-- if(*args && args[0])
-- return PURPLE_CMD_RET_FAILED;
--
-- account = purple_conversation_get_account(conv);
-- gc = purple_account_get_connection(account);
-- name = purple_conversation_get_name(conv);
-- yahoo_doodle_initiate(gc, name);
--
-- /* Write a local message to this conversation showing that a request for a
-- * Doodle session has been made
-- */
-- purple_conv_im_write(PURPLE_CONV_IM(conv), "", _("Sent Doodle request."),
-- PURPLE_MESSAGE_NICK | PURPLE_MESSAGE_RECV, time(NULL));
--
-- return PURPLE_CMD_RET_OK;
--}
--
--void yahoo_doodle_initiate(PurpleConnection *gc, const char *name)
--{
-- PurpleAccount *account;
-- char *to = (char*)name;
-- PurpleWhiteboard *wb;
--
-- g_return_if_fail(gc);
-- g_return_if_fail(name);
--
-- account = purple_connection_get_account(gc);
-- wb = purple_whiteboard_get_session(account, to);
--
-- if(wb == NULL)
-- {
-- /* Insert this 'session' in the list. At this point, it's only a
-- * requested session.
-- */
-- wb = purple_whiteboard_create(account, to, DOODLE_STATE_REQUESTING);
-- }
--
-- /* NOTE Perhaps some careful handling of remote assumed established
-- * sessions
-- */
--
-- yahoo_doodle_command_send_ready(gc, to, DOODLE_IMV_KEY);
-- yahoo_doodle_command_send_request(gc, to, DOODLE_IMV_KEY);
--
--}
--
--static void yahoo_doodle_command_got_request(PurpleConnection *gc, const char *from, const char *imv_key)
--{
-- PurpleAccount *account;
-- PurpleWhiteboard *wb;
--
-- purple_debug_info("yahoo", "doodle: Got Request (%s)\n", from);
--
-- account = purple_connection_get_account(gc);
--
-- /* Only handle this if local client requested Doodle session (else local
-- * client would have sent one)
-- */
-- wb = purple_whiteboard_get_session(account, from);
--
-- /* If a session with the remote user doesn't exist */
-- if(wb == NULL)
-- {
-- doodle_session *ds;
-- /* Ask user if they wish to accept the request for a doodle session */
-- /* TODO Ask local user to start Doodle session with remote user */
-- /* NOTE This if/else statement won't work right--must use dialog
-- * results
-- */
--
-- /* char dialog_message[64];
-- g_sprintf(dialog_message, "%s is requesting to start a Doodle session with you.", from);
--
-- purple_notify_message(NULL, PURPLE_NOTIFY_MSG_INFO, "Doodle",
-- dialog_message, NULL, NULL, NULL);
-- */
--
-- wb = purple_whiteboard_create(account, from, DOODLE_STATE_REQUESTED);
-- ds = wb->proto_data;
-- ds->imv_key = g_strdup(imv_key);
--
-- yahoo_doodle_command_send_ready(gc, from, imv_key);
-- }
--
-- /* TODO Might be required to clear the canvas of an existing doodle
-- * session at this point
-- */
--}
--
--static void yahoo_doodle_command_got_ready(PurpleConnection *gc, const char *from, const char *imv_key)
--{
-- PurpleAccount *account;
-- PurpleWhiteboard *wb;
--
-- purple_debug_info("yahoo", "doodle: Got Ready(%s)\n", from);
--
-- account = purple_connection_get_account(gc);
--
-- /* Only handle this if local client requested Doodle session (else local
-- * client would have sent one)
-- */
-- wb = purple_whiteboard_get_session(account, from);
--
-- if(wb == NULL)
-- return;
--
-- if(wb->state == DOODLE_STATE_REQUESTING)
-- {
-- doodle_session *ds = wb->proto_data;
-- purple_whiteboard_start(wb);
--
-- wb->state = DOODLE_STATE_ESTABLISHED;
--
-- yahoo_doodle_command_send_confirm(gc, from, imv_key);
-- /* Let's steal the imv_key and reuse it */
-- g_free(ds->imv_key);
-- ds->imv_key = g_strdup(imv_key);
-- }
-- else if(wb->state == DOODLE_STATE_ESTABLISHED)
-- {
-- /* TODO Ask whether to save picture too */
-- purple_whiteboard_clear(wb);
-- }
--
-- /* NOTE Not sure about this... I am trying to handle if the remote user
-- * already thinks we're in a session with them (when their chat message
-- * contains the doodle imv key)
-- */
-- else if(wb->state == DOODLE_STATE_REQUESTED)
-- {
-- /* purple_whiteboard_start(wb); */
-- yahoo_doodle_command_send_ready(gc, from, imv_key);
-- }
--}
--
--static void yahoo_doodle_command_got_draw(PurpleConnection *gc, const char *from, const char *message)
--{
-- PurpleAccount *account;
-- PurpleWhiteboard *wb;
-- char **tokens;
-- int i;
-- GList *d_list = NULL; /* a local list of drawing info */
--
-- g_return_if_fail(message != NULL);
--
-- purple_debug_info("yahoo", "doodle: Got Draw (%s)\n", from);
-- purple_debug_info("yahoo", "doodle: Draw message: %s\n", message);
--
-- account = purple_connection_get_account(gc);
--
-- /* Only handle this if local client requested Doodle session (else local
-- * client would have sent one)
-- */
-- wb = purple_whiteboard_get_session(account, from);
--
-- if(wb == NULL)
-- return;
--
-- /* TODO Functionalize
-- * Convert drawing packet message to an integer list
-- */
--
-- /* Check to see if the message begans and ends with quotes */
-- if((message[0] != '\"') || (message[strlen(message) - 1] != '\"'))
-- return;
--
-- /* Ignore the inital quotation mark. */
-- message += 1;
--
-- tokens = g_strsplit(message, ",", 0);
--
-- /* Traverse and extract all integers divided by commas */
-- for (i = 0; tokens[i] != NULL; i++)
-- {
-- int last = strlen(tokens[i]) - 1;
-- if (tokens[i][last] == '"')
-- tokens[i][last] = '\0';
--
-- d_list = g_list_prepend(d_list, GINT_TO_POINTER(atoi(tokens[i])));
-- }
-- d_list = g_list_reverse(d_list);
--
-- g_strfreev(tokens);
--
-- yahoo_doodle_draw_stroke(wb, d_list);
--
-- /* goodle_doodle_session_set_canvas_as_icon(ds); */
--
-- g_list_free(d_list);
--}
--
--
--static void yahoo_doodle_command_got_clear(PurpleConnection *gc, const char *from)
--{
-- PurpleAccount *account;
-- PurpleWhiteboard *wb;
--
-- purple_debug_info("yahoo", "doodle: Got Clear (%s)\n", from);
--
-- account = purple_connection_get_account(gc);
--
-- /* Only handle this if local client requested Doodle session (else local
-- * client would have sent one)
-- */
-- wb = purple_whiteboard_get_session(account, from);
--
-- if(wb == NULL)
-- return;
--
-- if(wb->state == DOODLE_STATE_ESTABLISHED)
-- {
-- /* TODO Ask user whether to save the image before clearing it */
--
-- purple_whiteboard_clear(wb);
-- }
--}
--
--
--static void
--yahoo_doodle_command_got_extra(PurpleConnection *gc, const char *from, const char *message, const char *imv_key)
--{
-- purple_debug_info("yahoo", "doodle: Got Extra (%s)\n", from);
--
-- /* I do not like these 'extra' features, so I'll only handle them in one
-- * way, which is returning them with the command/packet to turn them off
-- */
-- yahoo_doodle_command_send_extra(gc, from, DOODLE_EXTRA_NONE, imv_key);
--}
--
--static void yahoo_doodle_command_got_confirm(PurpleConnection *gc, const char *from)
--{
-- PurpleAccount *account;
-- PurpleWhiteboard *wb;
--
-- purple_debug_info("yahoo", "doodle: Got Confirm (%s)\n", from);
--
-- /* Get the doodle session */
-- account = purple_connection_get_account(gc);
--
-- /* Only handle this if local client requested Doodle session (else local
-- * client would have sent one)
-- */
-- wb = purple_whiteboard_get_session(account, from);
--
-- if(wb == NULL)
-- return;
--
-- /* TODO Combine the following IF's? */
--
-- /* Check if we requested a doodle session */
-- /*if(wb->state == DOODLE_STATE_REQUESTING)
-- {
-- wb->state = DOODLE_STATE_ESTABLISHED;
--
-- purple_whiteboard_start(wb);
--
-- yahoo_doodle_command_send_confirm(gc, from);
-- }*/
--
-- /* Check if we accepted a request for a doodle session */
-- if(wb->state == DOODLE_STATE_REQUESTED)
-- {
-- wb->state = DOODLE_STATE_ESTABLISHED;
--
-- purple_whiteboard_start(wb);
-- }
--}
--
--void yahoo_doodle_command_got_shutdown(PurpleConnection *gc, const char *from)
--{
-- PurpleAccount *account;
-- PurpleWhiteboard *wb;
--
-- g_return_if_fail(from != NULL);
--
-- purple_debug_info("yahoo", "doodle: Got Shutdown (%s)\n", from);
--
-- account = purple_connection_get_account(gc);
--
-- /* Only handle this if local client requested Doodle session (else local
-- * client would have sent one)
-- */
-- wb = purple_whiteboard_get_session(account, from);
--
-- if(wb == NULL)
-- return;
--
-- /* TODO Ask if user wants to save picture before the session is closed */
--
-- wb->state = DOODLE_STATE_CANCELLED;
-- purple_whiteboard_destroy(wb);
--}
--
--static void yahoo_doodle_command_send_generic(const char *type,
-- PurpleConnection *gc,
-- const char *to,
-- const char *message,
-- int command,
-- const char *imv,
-- const char *sixtyfour)
--{
-- YahooData *yd;
-- struct yahoo_packet *pkt;
--
-- purple_debug_info("yahoo", "doodle: Sent %s (%s)\n", type, to);
--
-- yd = gc->proto_data;
--
-- /* Make and send an acknowledge (ready) Doodle packet */
-- pkt = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash_str(pkt, 49, "IMVIRONMENT");
-- yahoo_packet_hash_str(pkt, 1, purple_account_get_username(gc->account));
-- yahoo_packet_hash_str(pkt, 14, message);
-- yahoo_packet_hash_int(pkt, 13, command);
-- yahoo_packet_hash_str(pkt, 5, to);
-- yahoo_packet_hash_str(pkt, 63, imv ? imv : DOODLE_IMV_KEY);
-- yahoo_packet_hash_str(pkt, 64, sixtyfour);
-- yahoo_packet_hash_str(pkt, 1002, "1");
--
-- yahoo_packet_send_and_free(pkt, yd);
--}
--
--void yahoo_doodle_command_send_ready(PurpleConnection *gc, const char *to, const char *imv_key)
--{
-- yahoo_doodle_command_send_generic("Ready", gc, to, "1", DOODLE_CMD_READY, imv_key, "1");
--}
--
--void yahoo_doodle_command_send_request(PurpleConnection *gc, const char *to, const char *imv_key)
--{
-- yahoo_doodle_command_send_generic("Request", gc, to, "", DOODLE_CMD_REQUEST, imv_key, "0");
--}
--
--void yahoo_doodle_command_send_draw(PurpleConnection *gc, const char *to, const char *message, const char *imv_key)
--{
-- yahoo_doodle_command_send_generic("Draw", gc, to, message, DOODLE_CMD_DRAW, imv_key, "1");
--}
--
--void yahoo_doodle_command_send_clear(PurpleConnection *gc, const char *to, const char *imv_key)
--{
-- yahoo_doodle_command_send_generic("Clear", gc, to, " ", DOODLE_CMD_CLEAR, imv_key, "1");
--}
--
--void yahoo_doodle_command_send_extra(PurpleConnection *gc, const char *to, const char *message, const char *imv_key)
--{
-- yahoo_doodle_command_send_generic("Extra", gc, to, message, DOODLE_CMD_EXTRA, imv_key, "1");
--}
--
--void yahoo_doodle_command_send_confirm(PurpleConnection *gc, const char *to, const char *imv_key)
--{
-- yahoo_doodle_command_send_generic("Confirm", gc, to, "1", DOODLE_CMD_CONFIRM, imv_key, "1");
--}
--
--void yahoo_doodle_command_send_shutdown(PurpleConnection *gc, const char *to)
--{
-- yahoo_doodle_command_send_generic("Shutdown", gc, to, "", DOODLE_CMD_SHUTDOWN, ";0", "0");
--}
--
--void yahoo_doodle_start(PurpleWhiteboard *wb)
--{
-- doodle_session *ds = g_new0(doodle_session, 1);
--
-- /* purple_debug_debug("yahoo", "doodle: yahoo_doodle_start()\n"); */
--
-- /* Set default brush size and color */
-- ds->brush_size = DOODLE_BRUSH_SMALL;
-- ds->brush_color = DOODLE_COLOR_RED;
--
-- wb->proto_data = ds;
--}
--
--void yahoo_doodle_end(PurpleWhiteboard *wb)
--{
-- PurpleConnection *gc = purple_account_get_connection(wb->account);
-- doodle_session *ds = wb->proto_data;
--
-- /* g_debug_debug("yahoo", "doodle: yahoo_doodle_end()\n"); */
--
-- if (gc && wb->state != DOODLE_STATE_CANCELLED)
-- yahoo_doodle_command_send_shutdown(gc, wb->who);
--
-- g_free(ds->imv_key);
-- g_free(wb->proto_data);
--}
--
--void yahoo_doodle_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height)
--{
-- /* standard Doodle canvases are of one size: 368x256 */
-- *width = DOODLE_CANVAS_WIDTH;
-- *height = DOODLE_CANVAS_HEIGHT;
--}
--
--static char *yahoo_doodle_build_draw_string(doodle_session *ds, GList *draw_list)
--{
-- GString *message;
--
-- g_return_val_if_fail(draw_list != NULL, NULL);
--
-- message = g_string_new("");
-- g_string_printf(message, "\"%d,%d", ds->brush_color, ds->brush_size);
--
-- for(; draw_list != NULL; draw_list = draw_list->next)
-- {
-- g_string_append_printf(message, ",%d", GPOINTER_TO_INT(draw_list->data));
-- }
-- g_string_append_c(message, '"');
--
-- return g_string_free(message, FALSE);
--}
--
--void yahoo_doodle_send_draw_list(PurpleWhiteboard *wb, GList *draw_list)
--{
-- doodle_session *ds = wb->proto_data;
-- char *message;
--
-- g_return_if_fail(draw_list != NULL);
--
-- message = yahoo_doodle_build_draw_string(ds, draw_list);
-- yahoo_doodle_command_send_draw(wb->account->gc, wb->who, message, ds->imv_key);
-- g_free(message);
--}
--
--void yahoo_doodle_clear(PurpleWhiteboard *wb)
--{
-- doodle_session *ds = wb->proto_data;
-- yahoo_doodle_command_send_clear(wb->account->gc, wb->who, ds->imv_key);
--}
--
--
--/* Traverse through the list and draw the points and lines */
--void yahoo_doodle_draw_stroke(PurpleWhiteboard *wb, GList *draw_list)
--{
-- int brush_color;
-- int brush_size;
-- int x;
-- int y;
--
-- g_return_if_fail(draw_list != NULL);
--
-- brush_color = GPOINTER_TO_INT(draw_list->data);
-- draw_list = draw_list->next;
-- g_return_if_fail(draw_list != NULL);
--
-- brush_size = GPOINTER_TO_INT(draw_list->data);
-- draw_list = draw_list->next;
-- g_return_if_fail(draw_list != NULL);
--
-- x = GPOINTER_TO_INT(draw_list->data);
-- draw_list = draw_list->next;
-- g_return_if_fail(draw_list != NULL);
--
-- y = GPOINTER_TO_INT(draw_list->data);
-- draw_list = draw_list->next;
-- g_return_if_fail(draw_list != NULL);
--
-- /*
-- purple_debug_debug("yahoo", "doodle: Drawing: color=%d, size=%d, (%d,%d)\n", brush_color, brush_size, x, y);
-- */
--
-- while(draw_list != NULL && draw_list->next != NULL)
-- {
-- int dx = GPOINTER_TO_INT(draw_list->data);
-- int dy = GPOINTER_TO_INT(draw_list->next->data);
--
-- purple_whiteboard_draw_line(wb,
-- x, y,
-- x + dx, y + dy,
-- brush_color, brush_size);
--
-- x += dx;
-- y += dy;
--
-- draw_list = draw_list->next->next;
-- }
--}
--
--void yahoo_doodle_get_brush(const PurpleWhiteboard *wb, int *size, int *color)
--{
-- doodle_session *ds = wb->proto_data;
-- *size = ds->brush_size;
-- *color = ds->brush_color;
--}
--
--void yahoo_doodle_set_brush(PurpleWhiteboard *wb, int size, int color)
--{
-- doodle_session *ds = wb->proto_data;
-- ds->brush_size = size;
-- ds->brush_color = color;
--
-- /* Notify the core about the changes */
-- purple_whiteboard_set_brush(wb, size, color);
--}
--
--void yahoo_doodle_process(PurpleConnection *gc, const char *me, const char *from,
-- const char *command, const char *message, const char *imv_key)
--{
-- if(!command)
-- return;
--
-- /* Now check to see what sort of Doodle message it is */
-- switch(atoi(command))
-- {
-- case DOODLE_CMD_REQUEST:
-- yahoo_doodle_command_got_request(gc, from, imv_key);
-- break;
--
-- case DOODLE_CMD_READY:
-- yahoo_doodle_command_got_ready(gc, from, imv_key);
-- break;
--
-- case DOODLE_CMD_CLEAR:
-- yahoo_doodle_command_got_clear(gc, from);
-- break;
--
-- case DOODLE_CMD_DRAW:
-- yahoo_doodle_command_got_draw(gc, from, message);
-- break;
--
-- case DOODLE_CMD_EXTRA:
-- yahoo_doodle_command_got_extra(gc, from, message, imv_key);
-- break;
--
-- case DOODLE_CMD_CONFIRM:
-- yahoo_doodle_command_got_confirm(gc, from);
-- break;
-- }
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_doodle.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_doodle.h
---- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_doodle.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_doodle.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,131 +0,0 @@
--/**
-- * @file yahoo_doodle.h The Yahoo! protocol plugin Doodle IMVironment object
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _YAHOO_DOODLE_H_
--#define _YAHOO_DOODLE_H_
--
--/******************************************************************************
-- * Includes
-- *****************************************************************************/
--#include "whiteboard.h"
--#include "cmds.h"
--
--#define DOODLE_IMV_KEY "doodle;106"
--
--/******************************************************************************
-- * Defines
-- *****************************************************************************/
--/* Doodle communication commands */
--/* TODO: Should be an enum. */
--#define DOODLE_CMD_REQUEST 0
--#define DOODLE_CMD_CLEAR 1
--#define DOODLE_CMD_DRAW 2
--#define DOODLE_CMD_EXTRA 3
--#define DOODLE_CMD_READY 4
--#define DOODLE_CMD_CONFIRM 5
--/* Doodle communication command for shutting down (also 0) */
--#define DOODLE_CMD_SHUTDOWN 0
--
--#define DOODLE_EXTRA_NONE "\"1\""
--#define DOODLE_EXTRA_TICTACTOE "\"3\""
--#define DOODLE_EXTRA_DOTS "\"2\""
--
--/* Doodle session states */
--/* TODO: Should be an enum. */
--#define DOODLE_STATE_REQUESTING 0
--#define DOODLE_STATE_REQUESTED 1
--#define DOODLE_STATE_ESTABLISHED 2
--#define DOODLE_STATE_CANCELLED 3
--
--/* Doodle canvas dimensions */
--#define DOODLE_CANVAS_WIDTH 368
--#define DOODLE_CANVAS_HEIGHT 256
--
--/* Doodle color codes (most likely RGB) */
--/* TODO: Should be an enum and sorted by color name. */
--#define DOODLE_COLOR_RED 13369344
--#define DOODLE_COLOR_ORANGE 16737792
--#define DOODLE_COLOR_YELLOW 15658496
--#define DOODLE_COLOR_GREEN 52224
--#define DOODLE_COLOR_CYAN 52428
--#define DOODLE_COLOR_BLUE 204
--#define DOODLE_COLOR_VIOLET 5381277
--#define DOODLE_COLOR_PURPLE 13369548
--#define DOODLE_COLOR_TAN 12093547
--#define DOODLE_COLOR_BROWN 5256485
--#define DOODLE_COLOR_BLACK 0
--#define DOODLE_COLOR_GREY 11184810
--#define DOODLE_COLOR_WHITE 16777215
--
--#define PALETTE_NUM_OF_COLORS 12
--
--/* Doodle brush sizes (most likely variable) */
--#define DOODLE_BRUSH_SMALL 2
--#define DOODLE_BRUSH_MEDIUM 5
--#define DOODLE_BRUSH_LARGE 10
--
--#define DOODLE_MAX_BRUSH_MOTIONS 100
--
--/******************************************************************************
-- * Datatypes
-- *****************************************************************************/
--typedef struct _doodle_session
--{
-- int brush_size; /* Size of drawing brush */
-- int brush_color; /* Color of drawing brush */
-- gchar *imv_key;
--} doodle_session;
--
--/******************************************************************************
-- * API
-- *****************************************************************************/
--
--PurpleCmdRet yahoo_doodle_purple_cmd_start(PurpleConversation *conv, const char *cmd, char **args,
-- char **error, void *data);
--
--void yahoo_doodle_process(PurpleConnection *gc, const char *me, const char *from,
-- const char *command, const char *message, const char *imv_key);
--void yahoo_doodle_initiate(PurpleConnection *gc, const char *to);
--
--void yahoo_doodle_command_got_shutdown(PurpleConnection *gc, const char *from);
--
--void yahoo_doodle_command_send_request(PurpleConnection *gc, const char *to, const char *imv_key);
--void yahoo_doodle_command_send_ready(PurpleConnection *gc, const char *to, const char *imv_key);
--void yahoo_doodle_command_send_draw(PurpleConnection *gc, const char *to, const char *message, const char *imv_key);
--void yahoo_doodle_command_send_clear(PurpleConnection *gc, const char *to, const char *imv_key);
--void yahoo_doodle_command_send_extra(PurpleConnection *gc, const char *to, const char *message, const char *imv_key);
--void yahoo_doodle_command_send_confirm(PurpleConnection *gc, const char *to, const char *imv_key);
--void yahoo_doodle_command_send_shutdown(PurpleConnection *gc, const char *to);
--
--void yahoo_doodle_start(PurpleWhiteboard *wb);
--void yahoo_doodle_end(PurpleWhiteboard *wb);
--void yahoo_doodle_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height);
--void yahoo_doodle_send_draw_list(PurpleWhiteboard *wb, GList *draw_list);
--void yahoo_doodle_clear(PurpleWhiteboard *wb);
--
--void yahoo_doodle_draw_stroke(PurpleWhiteboard *wb, GList *draw_list);
--void yahoo_doodle_get_brush(const PurpleWhiteboard *wb, int *size, int *color);
--void yahoo_doodle_set_brush(PurpleWhiteboard *wb, int size, int color);
--
--#endif /* _YAHOO_DOODLE_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_filexfer.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_filexfer.c
---- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_filexfer.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_filexfer.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1951 +0,0 @@
--/*
-- * @file yahoo_filexfer.c Yahoo Filetransfer
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "dnsquery.h"
--
--#include "prpl.h"
--#include "util.h"
--#include "debug.h"
--#include "network.h"
--#include "notify.h"
--#include "proxy.h"
--#include "ft.h"
--#include "libymsg.h"
--#include "yahoo_packet.h"
--#include "yahoo_filexfer.h"
--#include "yahoo_doodle.h"
--#include "yahoo_friend.h"
--
--struct yahoo_xfer_data {
-- gchar *host;
-- gchar *path;
-- int port;
-- PurpleConnection *gc;
-- long expires;
-- gboolean started;
-- gchar *txbuf;
-- gsize txbuflen;
-- gsize txbuf_written;
-- guint tx_handler;
-- gchar *rxqueue;
-- guint rxlen;
-- gchar *xfer_peer_idstring;
-- gchar *xfer_idstring_for_relay;
-- int version; /* 0 for old, 15 for Y7(YMSG 15) */
-- int info_val_249;
--
-- enum {
-- STARTED = 0,
-- HEAD_REQUESTED,
-- HEAD_REPLY_RECEIVED,
-- TRANSFER_PHASE,
-- ACCEPTED,
-- P2P_HEAD_REQUESTED,
-- P2P_HEAD_REPLIED,
-- P2P_GET_REQUESTED
-- } status_15;
--
-- /* contains all filenames, in case of multiple transfers, with the first
-- * one in the list being the current file's name (ymsg15) */
-- GSList *filename_list;
-- GSList *size_list; /* corresponds to filename_list, with size as **STRING** */
-- gboolean firstoflist;
-- gchar *xfer_url; /* url of the file, used when we are p2p server */
-- int yahoo_local_p2p_ft_server_fd;
-- int yahoo_local_p2p_ft_server_port;
-- int yahoo_p2p_ft_server_watcher;
-- int input_event;
--};
--
--static void yahoo_xfer_data_free(struct yahoo_xfer_data *xd)
--{
-- PurpleConnection *gc;
-- YahooData *yd;
-- PurpleXfer *xfer;
-- GSList *l;
--
-- gc = xd->gc;
-- yd = gc->proto_data;
--
-- /* remove entry from map */
-- if(xd->xfer_peer_idstring) {
-- xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xd->xfer_peer_idstring);
-- if(xfer)
-- g_hash_table_remove(yd->xfer_peer_idstring_map, xd->xfer_peer_idstring);
-- }
--
-- /* empty file & filesize list */
-- for (l = xd->filename_list; l; l = l->next) {
-- g_free(l->data);
-- l->data=NULL;
-- }
-- for (l = xd->size_list; l; l = l->next) {
-- g_free(l->data);
-- l->data=NULL;
-- }
-- g_slist_free(xd->filename_list);
-- g_slist_free(xd->size_list);
--
-- g_free(xd->host);
-- g_free(xd->path);
-- g_free(xd->txbuf);
-- g_free(xd->xfer_peer_idstring);
-- g_free(xd->xfer_idstring_for_relay);
-- if (xd->tx_handler)
-- purple_input_remove(xd->tx_handler);
-- g_free(xd);
--}
--
--static void yahoo_receivefile_send_cb(gpointer data, gint source, PurpleInputCondition condition)
--{
-- PurpleXfer *xfer;
-- struct yahoo_xfer_data *xd;
-- int remaining, written;
--
-- xfer = data;
-- xd = xfer->data;
--
-- remaining = xd->txbuflen - xd->txbuf_written;
-- written = write(xfer->fd, xd->txbuf + xd->txbuf_written, remaining);
--
-- if (written < 0 && errno == EAGAIN)
-- written = 0;
-- else if (written <= 0) {
-- purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno);
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
--
-- if (written < remaining) {
-- xd->txbuf_written += written;
-- return;
-- }
--
-- purple_input_remove(xd->tx_handler);
-- xd->tx_handler = 0;
-- g_free(xd->txbuf);
-- xd->txbuf = NULL;
-- xd->txbuflen = 0;
--
-- purple_xfer_start(xfer, source, NULL, 0);
--
--}
--
--static void yahoo_receivefile_connected(gpointer data, gint source, const gchar *error_message)
--{
-- PurpleXfer *xfer;
-- struct yahoo_xfer_data *xd;
--
-- purple_debug_info("yahoo", "in yahoo_receivefile_connected\n");
--
-- if (!(xfer = data))
-- return;
-- if (!(xd = xfer->data))
-- return;
-- if ((source < 0) || (xd->path == NULL) || (xd->host == NULL)) {
-- purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer),
-- xfer->who, _("Unable to connect."));
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
--
-- xfer->fd = source;
--
-- /* The first time we get here, assemble the tx buffer */
-- if (xd->txbuflen == 0) {
-- xd->txbuf = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n",
-- xd->path, xd->host);
-- xd->txbuflen = strlen(xd->txbuf);
-- xd->txbuf_written = 0;
-- }
--
-- if (!xd->tx_handler)
-- {
-- xd->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE,
-- yahoo_receivefile_send_cb, xfer);
-- yahoo_receivefile_send_cb(xfer, source, PURPLE_INPUT_WRITE);
-- }
--}
--
--static void yahoo_sendfile_send_cb(gpointer data, gint source, PurpleInputCondition condition)
--{
-- PurpleXfer *xfer;
-- struct yahoo_xfer_data *xd;
-- int written, remaining;
--
-- xfer = data;
-- xd = xfer->data;
--
-- remaining = xd->txbuflen - xd->txbuf_written;
-- written = write(xfer->fd, xd->txbuf + xd->txbuf_written, remaining);
--
-- if (written < 0 && errno == EAGAIN)
-- written = 0;
-- else if (written <= 0) {
-- purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno);
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
--
-- if (written < remaining) {
-- xd->txbuf_written += written;
-- return;
-- }
--
-- purple_input_remove(xd->tx_handler);
-- xd->tx_handler = 0;
-- g_free(xd->txbuf);
-- xd->txbuf = NULL;
-- xd->txbuflen = 0;
--
-- purple_xfer_start(xfer, source, NULL, 0);
--}
--
--static void yahoo_sendfile_connected(gpointer data, gint source, const gchar *error_message)
--{
-- PurpleXfer *xfer;
-- struct yahoo_xfer_data *xd;
-- struct yahoo_packet *pkt;
-- gchar *size, *filename, *encoded_filename, *header;
-- guchar *pkt_buf;
-- const char *host;
-- int port;
-- size_t content_length, header_len, pkt_buf_len;
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- YahooData *yd;
--
-- purple_debug_info("yahoo", "in yahoo_sendfile_connected\n");
--
-- if (!(xfer = data))
-- return;
-- if (!(xd = xfer->data))
-- return;
--
-- if (source < 0) {
-- purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer),
-- xfer->who, _("Unable to connect."));
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
--
-- xfer->fd = source;
--
-- /* Assemble the tx buffer */
-- gc = xd->gc;
-- account = purple_connection_get_account(gc);
-- yd = gc->proto_data;
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANSFER,
-- YAHOO_STATUS_AVAILABLE, yd->session_id);
--
-- size = g_strdup_printf("%" G_GSIZE_FORMAT, purple_xfer_get_size(xfer));
-- filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
-- encoded_filename = yahoo_string_encode(gc, filename, NULL);
--
-- yahoo_packet_hash(pkt, "sssss", 0, purple_connection_get_display_name(gc),
-- 5, xfer->who, 14, "", 27, encoded_filename, 28, size);
-- g_free(size);
-- g_free(encoded_filename);
-- g_free(filename);
--
-- content_length = YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt);
--
-- pkt_buf_len = yahoo_packet_build(pkt, 4, FALSE, yd->jp, &pkt_buf);
-- yahoo_packet_free(pkt);
--
-- host = purple_account_get_string(account, "xfer_host", YAHOO_XFER_HOST);
-- port = purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT);
-- header = g_strdup_printf(
-- "POST http://%s:%d/notifyft HTTP/1.0\r\n"
-- "Content-length: %" G_GSIZE_FORMAT "\r\n"
-- "Host: %s:%d\r\n"
-- "Cookie: Y=%s; T=%s\r\n"
-- "\r\n",
-- host, port, content_length + 4 + purple_xfer_get_size(xfer),
-- host, port, yd->cookie_y, yd->cookie_t);
--
-- header_len = strlen(header);
--
-- xd->txbuflen = header_len + pkt_buf_len + 4;
-- xd->txbuf = g_malloc(xd->txbuflen);
--
-- memcpy(xd->txbuf, header, header_len);
-- g_free(header);
-- memcpy(xd->txbuf + header_len, pkt_buf, pkt_buf_len);
-- g_free(pkt_buf);
-- memcpy(xd->txbuf + header_len + pkt_buf_len, "29\xc0\x80", 4);
--
-- xd->txbuf_written = 0;
--
-- if (xd->tx_handler == 0)
-- {
-- xd->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE,
-- yahoo_sendfile_send_cb, xfer);
-- yahoo_sendfile_send_cb(xfer, source, PURPLE_INPUT_WRITE);
-- }
--}
--
--static void yahoo_xfer_init(PurpleXfer *xfer)
--{
-- struct yahoo_xfer_data *xfer_data;
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- YahooData *yd;
--
-- xfer_data = xfer->data;
-- gc = xfer_data->gc;
-- yd = gc->proto_data;
-- account = purple_connection_get_account(gc);
--
-- if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
-- if (yd->jp) {
-- if (purple_proxy_connect(gc, account, purple_account_get_string(account, "xferjp_host", YAHOOJP_XFER_HOST),
-- purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT),
-- yahoo_sendfile_connected, xfer) == NULL)
-- {
-- purple_notify_error(gc, NULL, _("File Transfer Failed"),
-- _("Unable to establish file descriptor."));
-- purple_xfer_cancel_remote(xfer);
-- }
-- } else {
-- if (purple_proxy_connect(gc, account, purple_account_get_string(account, "xfer_host", YAHOO_XFER_HOST),
-- purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT),
-- yahoo_sendfile_connected, xfer) == NULL)
-- {
-- purple_notify_error(gc, NULL, _("File Transfer Failed"),
-- _("Unable to establish file descriptor."));
-- purple_xfer_cancel_remote(xfer);
-- }
-- }
-- } else {
-- xfer->fd = -1;
-- if (purple_proxy_connect(gc, account, xfer_data->host, xfer_data->port,
-- yahoo_receivefile_connected, xfer) == NULL) {
-- purple_notify_error(gc, NULL, _("File Transfer Failed"),
-- _("Unable to establish file descriptor."));
-- purple_xfer_cancel_remote(xfer);
-- }
-- }
--}
--
--static void yahoo_xfer_init_15(PurpleXfer *xfer)
--{
-- struct yahoo_xfer_data *xfer_data;
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- YahooData *yd;
-- struct yahoo_packet *pkt;
--
-- xfer_data = xfer->data;
-- gc = xfer_data->gc;
-- yd = gc->proto_data;
-- account = purple_connection_get_account(gc);
--
-- if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
-- gchar *filename;
-- filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
-- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
-- YAHOO_STATUS_AVAILABLE,
-- yd->session_id);
-- yahoo_packet_hash(pkt, "sssiiiisiii",
-- 1, purple_normalize(account, purple_account_get_username(account)),
-- 5, xfer->who,
-- 265, xfer_data->xfer_peer_idstring,
-- 222, 1,
-- 266, 1,
-- 302, 268,
-- 300, 268,
-- 27, filename,
-- 28, xfer->size,
-- 301, 268,
-- 303, 268);
-- g_free(filename);
-- } else {
-- if(xfer_data->firstoflist == TRUE) {
-- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
-- YAHOO_STATUS_AVAILABLE, yd->session_id);
--
-- yahoo_packet_hash(pkt, "sssi",
-- 1, purple_normalize(account, purple_account_get_username(account)),
-- 5, xfer->who,
-- 265, xfer_data->xfer_peer_idstring,
-- 222, 3);
-- } else {
-- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15,
-- YAHOO_STATUS_AVAILABLE, yd->session_id);
--
-- yahoo_packet_hash(pkt, "sssi",
-- 1, purple_normalize(account, purple_account_get_username(account)),
-- 5, xfer->who,
-- 265, xfer_data->xfer_peer_idstring,
-- 271, 1);
-- }
-- }
-- yahoo_packet_send_and_free(pkt, yd);
--}
--
--static void yahoo_xfer_start(PurpleXfer *xfer)
--{
-- /* We don't need to do anything here, do we? */
--}
--
--static guint calculate_length(const gchar *l, size_t len)
--{
-- int i;
--
-- for (i = 0; i < len; i++) {
-- if (!g_ascii_isdigit(l[i]))
-- continue;
-- return strtol(l + i, NULL, 10);
-- }
-- return 0;
--}
--
--static gssize yahoo_xfer_read(guchar **buffer, PurpleXfer *xfer)
--{
-- gchar buf[4096];
-- gssize len;
-- gchar *start = NULL;
-- gchar *length;
-- gchar *end;
-- int filelen;
-- struct yahoo_xfer_data *xd = xfer->data;
--
-- if (purple_xfer_get_type(xfer) != PURPLE_XFER_RECEIVE) {
-- return 0;
-- }
--
-- len = read(xfer->fd, buf, sizeof(buf));
--
-- if (len <= 0) {
-- if ((purple_xfer_get_size(xfer) > 0) &&
-- (purple_xfer_get_bytes_sent(xfer) >= purple_xfer_get_size(xfer))) {
-- purple_xfer_set_completed(xfer, TRUE);
-- return 0;
-- } else
-- return -1;
-- }
--
-- if (!xd->started) {
-- xd->rxqueue = g_realloc(xd->rxqueue, len + xd->rxlen);
-- memcpy(xd->rxqueue + xd->rxlen, buf, len);
-- xd->rxlen += len;
--
-- length = g_strstr_len(xd->rxqueue, len, "Content-length:");
-- /* some proxies re-write this header, changing the capitalization :(
-- * technically that's allowed since headers are case-insensitive
-- * [RFC 2616, section 4.2] */
-- if (length == NULL)
-- length = g_strstr_len(xd->rxqueue, len, "Content-Length:");
-- if (length) {
-- end = g_strstr_len(length, length - xd->rxqueue, "\r\n");
-- if (!end)
-- return 0;
-- if ((filelen = calculate_length(length, len - (length - xd->rxqueue))))
-- purple_xfer_set_size(xfer, filelen);
-- }
-- start = g_strstr_len(xd->rxqueue, len, "\r\n\r\n");
-- if (start)
-- start += 4;
-- if (!start || start > (xd->rxqueue + len))
-- return 0;
-- xd->started = TRUE;
--
-- len -= (start - xd->rxqueue);
--
-- *buffer = g_malloc(len);
-- memcpy(*buffer, start, len);
-- g_free(xd->rxqueue);
-- xd->rxqueue = NULL;
-- xd->rxlen = 0;
-- } else {
-- *buffer = g_malloc(len);
-- memcpy(*buffer, buf, len);
-- }
--
-- return len;
--}
--
--static gssize yahoo_xfer_write(const guchar *buffer, size_t size, PurpleXfer *xfer)
--{
-- gssize len;
-- struct yahoo_xfer_data *xd = xfer->data;
--
-- if (!xd)
-- return -1;
--
-- if (purple_xfer_get_type(xfer) != PURPLE_XFER_SEND) {
-- return -1;
-- }
--
-- len = write(xfer->fd, buffer, size);
--
-- if (len == -1) {
-- if (purple_xfer_get_bytes_sent(xfer) >= purple_xfer_get_size(xfer))
-- purple_xfer_set_completed(xfer, TRUE);
-- if ((errno != EAGAIN) && (errno != EINTR))
-- return -1;
-- return 0;
-- }
--
-- return len;
--}
--
--static void yahoo_xfer_cancel_send(PurpleXfer *xfer)
--{
-- struct yahoo_xfer_data *xfer_data;
--
-- xfer_data = xfer->data;
--
-- if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15)
-- {
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- YahooData *yd;
-- struct yahoo_packet *pkt;
--
-- gc = xfer_data->gc;
-- yd = gc->proto_data;
-- account = purple_connection_get_account(gc);
-- if(xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */
-- {
-- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15,
-- YAHOO_STATUS_DISCONNECTED,
-- yd->session_id);
-- yahoo_packet_hash(pkt, "sssi",
-- 1, purple_normalize(account, purple_account_get_username(account)),
-- 5, xfer->who,
-- 265, xfer_data->xfer_peer_idstring,
-- 66, -1);
-- }
-- else
-- {
-- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
-- YAHOO_STATUS_AVAILABLE,
-- yd->session_id);
-- yahoo_packet_hash(pkt, "sssi",
-- 1, purple_normalize(account, purple_account_get_username(account)),
-- 5, xfer->who,
-- 265, xfer_data->xfer_peer_idstring,
-- 222, 2);
-- }
-- yahoo_packet_send_and_free(pkt, yd);
-- }
--
--
-- if (xfer_data)
-- yahoo_xfer_data_free(xfer_data);
-- xfer->data = NULL;
--}
--
--static void yahoo_xfer_cancel_recv(PurpleXfer *xfer)
--{
-- struct yahoo_xfer_data *xfer_data;
--
-- xfer_data = xfer->data;
--
-- if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15)
-- {
--
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- YahooData *yd;
-- struct yahoo_packet *pkt;
--
-- gc = xfer_data->gc;
-- yd = gc->proto_data;
-- account = purple_connection_get_account(gc);
-- if(!xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */
-- {
-- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
-- YAHOO_STATUS_AVAILABLE,
-- yd->session_id);
-- yahoo_packet_hash(pkt, "sssi",
-- 1, purple_normalize(account, purple_account_get_username(account)),
-- 5, xfer->who,
-- 265, xfer_data->xfer_peer_idstring,
-- 222, 4);
-- }
-- else
-- {
-- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
-- YAHOO_STATUS_DISCONNECTED,
-- yd->session_id);
-- yahoo_packet_hash(pkt, "sssi",
-- 1, purple_normalize(account, purple_account_get_username(account)),
-- 5, xfer->who,
-- 265, xfer_data->xfer_peer_idstring,
-- 66, -1);
-- }
-- yahoo_packet_send_and_free(pkt, yd);
-- }
--
-- if (xfer_data)
-- yahoo_xfer_data_free(xfer_data);
-- xfer->data = NULL;
--}
--
--/* Send HTTP OK after receiving file */
--static void yahoo_p2p_ft_server_send_OK(PurpleXfer *xfer)
--{
-- char *tx = NULL;
-- int written;
--
-- tx = g_strdup_printf("HTTP/1.1 200 OK\r\nContent-Length: 0\r\nContent-Type: application/octet-stream\r\nConnection: close\r\n\r\n");
-- written = write(xfer->fd, tx, strlen(tx));
--
-- if (written < 0 && errno == EAGAIN)
-- written = 0;
-- else if (written <= 0)
-- purple_debug_info("yahoo", "p2p filetransfer: Unable to write HTTP OK");
--
-- /* close connection */
-- close(xfer->fd);
-- xfer->fd = -1;
-- g_free(tx);
--}
--
--static void yahoo_xfer_end(PurpleXfer *xfer_old)
--{
-- struct yahoo_xfer_data *xfer_data;
-- PurpleXfer *xfer = NULL;
-- PurpleConnection *gc;
-- YahooData *yd;
--
-- xfer_data = xfer_old->data;
-- if(xfer_data && xfer_data->version == 15
-- && purple_xfer_get_type(xfer_old) == PURPLE_XFER_RECEIVE
-- && xfer_data->filename_list) {
--
-- /* Send HTTP OK in case of p2p transfer, when we act as server */
-- if((xfer_data->xfer_url != NULL) && (xfer_old->fd >=0) && (purple_xfer_get_status(xfer_old) == PURPLE_XFER_STATUS_DONE))
-- yahoo_p2p_ft_server_send_OK(xfer_old);
--
-- /* removing top of filename & size list completely */
-- g_free( xfer_data->filename_list->data );
-- g_free( xfer_data->size_list->data );
--
-- xfer_data->filename_list->data = NULL;
-- xfer_data->size_list->data = NULL;
--
-- xfer_data->filename_list = g_slist_delete_link(xfer_data->filename_list, xfer_data->filename_list);
-- xfer_data->size_list = g_slist_delete_link(xfer_data->size_list, xfer_data->size_list);
--
-- /* if there are still more files */
-- if(xfer_data->filename_list)
-- {
-- gchar* filename;
-- long filesize;
--
-- filename = xfer_data->filename_list->data;
-- filesize = atol( xfer_data->size_list->data );
--
-- gc = xfer_data->gc;
-- yd = gc->proto_data;
--
-- /* setting up xfer_data for next file's tranfer */
-- g_free(xfer_data->host);
-- g_free(xfer_data->path);
-- g_free(xfer_data->txbuf);
-- g_free(xfer_data->rxqueue);
-- g_free(xfer_data->xfer_idstring_for_relay);
-- if (xfer_data->tx_handler)
-- purple_input_remove(xfer_data->tx_handler);
-- xfer_data->host = NULL;
-- xfer_data->host = NULL;
-- xfer_data->port = 0;
-- xfer_data->expires = 0;
-- xfer_data->started = FALSE;
-- xfer_data->txbuf = NULL;
-- xfer_data->txbuflen = 0;
-- xfer_data->txbuf_written = 0;
-- xfer_data->tx_handler = 0;
-- xfer_data->rxqueue = NULL;
-- xfer_data->rxlen = 0;
-- xfer_data->xfer_idstring_for_relay = NULL;
-- xfer_data->info_val_249 = 0;
-- xfer_data->status_15 = STARTED;
-- xfer_data->firstoflist = FALSE;
--
-- /* Dereference xfer_data from old xfer */
-- xfer_old->data = NULL;
--
-- /* Build the file transfer handle. */
-- xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, xfer_old->who);
--
--
-- if (xfer) {
-- /* Set the info about the incoming file. */
-- char *utf8_filename = yahoo_string_decode(gc, filename, TRUE);
-- purple_xfer_set_filename(xfer, utf8_filename);
-- g_free(utf8_filename);
-- purple_xfer_set_size(xfer, filesize);
--
-- xfer->data = xfer_data;
--
-- /* Setup our I/O op functions */
-- purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15);
-- purple_xfer_set_start_fnc(xfer, yahoo_xfer_start);
-- purple_xfer_set_end_fnc(xfer, yahoo_xfer_end);
-- purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send);
-- purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv);
-- purple_xfer_set_read_fnc(xfer, yahoo_xfer_read);
-- purple_xfer_set_write_fnc(xfer, yahoo_xfer_write);
-- purple_xfer_set_request_denied_fnc(xfer,yahoo_xfer_cancel_recv);
--
-- /* update map to current xfer */
-- g_hash_table_remove(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring);
-- g_hash_table_insert(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring, xfer);
--
-- /* Now perform the request */
-- purple_xfer_request(xfer);
-- }
-- return;
-- }
-- }
-- if (xfer_data)
-- yahoo_xfer_data_free(xfer_data);
-- xfer_old->data = NULL;
--
--}
--
--void yahoo_process_p2pfilexfer(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- GSList *l = pkt->hash;
--
-- char *me = NULL;
-- char *from = NULL;
-- char *service = NULL;
-- char *message = NULL;
-- char *command = NULL;
-- char *imv = NULL;
-- char *unknown = NULL;
--
-- /* Get all the necessary values from this new packet */
-- while(l != NULL)
-- {
-- struct yahoo_pair *pair = l->data;
--
-- switch(pair->key) {
-- case 5: /* Get who the packet is for */
-- me = pair->value;
-- break;
-- case 4: /* Get who the packet is from */
-- from = pair->value;
-- break;
-- case 49: /* Get the type of service */
-- service = pair->value;
-- break;
-- case 14: /* Get the 'message' of the packet */
-- message = pair->value;
-- break;
-- case 13: /* Get the command associated with this packet */
-- command = pair->value;
-- break;
-- case 63: /* IMVironment name and version */
-- imv = pair->value;
-- break;
-- case 64: /* Not sure, but it does vary with initialization of Doodle */
-- unknown = pair->value; /* So, I'll keep it (for a little while atleast) */
-- break;
-- }
--
-- l = l->next;
-- }
--
-- /* If this packet is an IMVIRONMENT, handle it accordingly */
-- if(service != NULL && imv != NULL && !strcmp(service, "IMVIRONMENT"))
-- {
-- /* Check for a Doodle packet and handle it accordingly */
-- if(strstr(imv, "doodle;") != NULL)
-- yahoo_doodle_process(gc, me, from, command, message, imv);
--
-- /* If an IMVIRONMENT packet comes without a specific imviroment name */
-- if(!strcmp(imv, ";0"))
-- {
-- /* It is unfortunately time to close all IMVironments with the remote client */
-- yahoo_doodle_command_got_shutdown(gc, from);
-- }
-- }
--}
--
--void yahoo_process_filetransfer(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- char *from = NULL;
-- char *to = NULL;
-- char *msg = NULL;
-- char *url = NULL;
-- char *imv = NULL;
-- long expires = 0;
-- PurpleXfer *xfer;
-- YahooData *yd;
-- struct yahoo_xfer_data *xfer_data;
-- char *service = NULL;
-- char *filename = NULL;
-- unsigned long filesize = 0L;
-- GSList *l;
--
-- yd = gc->proto_data;
--
-- for (l = pkt->hash; l; l = l->next) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 4:
-- from = pair->value;
-- break;
-- case 5:
-- to = pair->value;
-- break;
-- case 14:
-- msg = pair->value;
-- break;
-- case 20:
-- url = pair->value;
-- break;
-- case 38:
-- expires = strtol(pair->value, NULL, 10);
-- break;
-- case 27:
-- filename = pair->value;
-- break;
-- case 28:
-- filesize = atol(pair->value);
-- break;
-- case 49:
-- service = pair->value;
-- break;
-- case 63:
-- imv = pair->value;
-- break;
-- }
-- }
--
-- /*
-- * The remote user has changed their IMVironment. We
-- * record it for later use.
-- */
-- if (from && imv && service && (strcmp("IMVIRONMENT", service) == 0)) {
-- g_hash_table_replace(yd->imvironments, g_strdup(from), g_strdup(imv));
-- return;
-- }
--
-- if (pkt->service == YAHOO_SERVICE_P2PFILEXFER) {
-- if (service && (strcmp("FILEXFER", service) != 0)) {
-- purple_debug_misc("yahoo", "unhandled service 0x%02x\n", pkt->service);
-- return;
-- }
-- }
--
-- if (msg) {
-- char *tmp;
-- tmp = strchr(msg, '\006');
-- if (tmp)
-- *tmp = '\0';
-- }
--
-- if (!url || !from)
-- return;
--
-- /* Setup the Yahoo-specific file transfer data */
-- xfer_data = g_new0(struct yahoo_xfer_data, 1);
-- xfer_data->gc = gc;
-- if (!purple_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL)) {
-- g_free(xfer_data);
-- return;
-- }
--
-- purple_debug_misc("yahoo_filexfer", "Host is %s, port is %d, path is %s, and the full url was %s.\n",
-- xfer_data->host, xfer_data->port, xfer_data->path, url);
--
-- /* Build the file transfer handle. */
-- xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, from);
-- if (xfer == NULL) {
-- g_free(xfer_data);
-- g_return_if_reached();
-- }
--
-- xfer->data = xfer_data;
--
-- /* Set the info about the incoming file. */
-- if (filename) {
-- char *utf8_filename = yahoo_string_decode(gc, filename, TRUE);
-- purple_xfer_set_filename(xfer, utf8_filename);
-- g_free(utf8_filename);
-- } else {
-- gchar *start, *end;
-- start = g_strrstr(xfer_data->path, "/");
-- if (start)
-- start++;
-- end = g_strrstr(xfer_data->path, "?");
-- if (start && *start && end) {
-- char *utf8_filename;
-- filename = g_strndup(start, end - start);
-- utf8_filename = yahoo_string_decode(gc, filename, TRUE);
-- g_free(filename);
-- purple_xfer_set_filename(xfer, utf8_filename);
-- g_free(utf8_filename);
-- filename = NULL;
-- }
-- }
--
-- purple_xfer_set_size(xfer, filesize);
--
-- /* Setup our I/O op functions */
-- purple_xfer_set_init_fnc(xfer, yahoo_xfer_init);
-- purple_xfer_set_start_fnc(xfer, yahoo_xfer_start);
-- purple_xfer_set_end_fnc(xfer, yahoo_xfer_end);
-- purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send);
-- purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv);
-- purple_xfer_set_read_fnc(xfer, yahoo_xfer_read);
-- purple_xfer_set_write_fnc(xfer, yahoo_xfer_write);
--
-- /* Now perform the request */
-- purple_xfer_request(xfer);
--}
--
--PurpleXfer *yahoo_new_xfer(PurpleConnection *gc, const char *who)
--{
-- PurpleXfer *xfer;
-- struct yahoo_xfer_data *xfer_data;
--
-- g_return_val_if_fail(who != NULL, NULL);
--
-- xfer_data = g_new0(struct yahoo_xfer_data, 1);
-- xfer_data->gc = gc;
--
-- /* Build the file transfer handle. */
-- xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who);
-- if (xfer == NULL)
-- {
-- g_free(xfer_data);
-- g_return_val_if_reached(NULL);
-- }
--
-- xfer->data = xfer_data;
--
-- /* Setup our I/O op functions */
-- purple_xfer_set_init_fnc(xfer, yahoo_xfer_init);
-- purple_xfer_set_start_fnc(xfer, yahoo_xfer_start);
-- purple_xfer_set_end_fnc(xfer, yahoo_xfer_end);
-- purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send);
-- purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv);
-- purple_xfer_set_read_fnc(xfer, yahoo_xfer_read);
-- purple_xfer_set_write_fnc(xfer, yahoo_xfer_write);
--
-- return xfer;
--}
--
--static gchar* yahoo_xfer_new_xfer_id(void)
--{
-- gchar *ans;
-- int i,j;
-- ans = g_strnfill(24, ' ');
-- ans[23] = '$';
-- ans[22] = '$';
-- for(i = 0; i < 22; i++)
-- {
-- j = g_random_int_range (0,61);
-- if(j < 26)
-- ans[i] = j + 'a';
-- else if(j < 52)
-- ans[i] = j - 26 + 'A';
-- else
-- ans[i] = j - 52 + '0';
-- }
-- return ans;
--}
--
--static void yahoo_xfer_dns_connected_15(GSList *hosts, gpointer data, const char *error_message)
--{
-- PurpleXfer *xfer;
-- struct yahoo_xfer_data *xd;
-- struct sockaddr_in *addr;
-- struct yahoo_packet *pkt;
-- unsigned long actaddr;
-- unsigned char a,b,c,d;
-- PurpleConnection *gc;
-- PurpleAccount *account;
-- YahooData *yd;
-- gchar *url;
-- gchar *filename;
--
-- if (!(xfer = data))
-- return;
-- if (!(xd = xfer->data))
-- return;
-- gc = xd->gc;
-- account = purple_connection_get_account(gc);
-- yd = gc->proto_data;
--
-- if(!hosts)
-- {
-- purple_debug_error("yahoo", "Unable to find an IP address for relay.msg.yahoo.com\n");
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
--
-- /* Discard the length... */
-- hosts = g_slist_remove(hosts, hosts->data);
-- if(!hosts)
-- {
-- purple_debug_error("yahoo", "Unable to find an IP address for relay.msg.yahoo.com\n");
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
--
-- /* TODO:actually, u must try with addr no.1 , if its not working addr no.2 ..... */
-- addr = hosts->data;
-- actaddr = addr->sin_addr.s_addr;
-- d = actaddr & 0xff;
-- actaddr >>= 8;
-- c = actaddr & 0xff;
-- actaddr >>= 8;
-- b = actaddr & 0xff;
-- actaddr >>= 8;
-- a = actaddr & 0xff;
-- if(yd->jp)
-- xd->port = YAHOOJP_XFER_RELAY_PORT;
-- else
-- xd->port = YAHOO_XFER_RELAY_PORT;
--
-- url = g_strdup_printf("%u.%u.%u.%u", d, c, b, a);
--
-- /* Free the address... */
-- g_free(hosts->data);
-- hosts = g_slist_remove(hosts, hosts->data);
-- addr = NULL;
-- while (hosts != NULL)
-- {
-- /* Discard the length... */
-- hosts = g_slist_remove(hosts, hosts->data);
-- /* Free the address... */
-- g_free(hosts->data);
-- hosts = g_slist_remove(hosts, hosts->data);
-- }
--
-- if (!purple_url_parse(url, &(xd->host), &(xd->port), &(xd->path), NULL, NULL)) {
-- purple_xfer_cancel_remote(xfer);
-- g_free(url);
-- return;
-- }
-- g_free(url);
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
--
-- yahoo_packet_hash(pkt, "ssssis",
-- 1, purple_normalize(account, purple_account_get_username(account)),
-- 5, xfer->who,
-- 265, xd->xfer_peer_idstring,
-- 27, filename,
-- 249, 3,
-- 250, xd->host);
--
-- g_free(filename);
-- yahoo_packet_send_and_free(pkt, yd);
--}
--
--gboolean yahoo_can_receive_file(PurpleConnection *gc, const char *who)
--{
-- if (!who || yahoo_get_federation_from_name(who) != YAHOO_FEDERATION_NONE)
-- return FALSE;
-- return TRUE;
--}
--
--void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file)
--{
-- struct yahoo_xfer_data *xfer_data;
-- YahooData *yd = gc->proto_data;
-- PurpleXfer *xfer = yahoo_new_xfer(gc, who);
--
-- g_return_if_fail(xfer != NULL);
--
-- /* if we don't have a p2p connection, try establishing it now */
-- if( !g_hash_table_lookup(yd->peers, who) )
-- yahoo_send_p2p_pkt(gc, who, 0);
--
-- xfer_data = xfer->data;
-- xfer_data->status_15 = STARTED;
-- purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15);
-- xfer_data->version = 15;
-- xfer_data->xfer_peer_idstring = yahoo_xfer_new_xfer_id();
-- g_hash_table_insert(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring, xfer);
--
-- /* Now perform the request */
-- if (file)
-- purple_xfer_request_accepted(xfer, file);
-- else
-- purple_xfer_request(xfer);
--}
--
--static void yahoo_p2p_ft_server_listen_cb(int listenfd, gpointer data); /* using this in yahoo_xfer_send_cb_15 */
--static void yahoo_xfer_connected_15(gpointer data, gint source, const gchar *error_message);/* using this in recv_cb */
--
--static void yahoo_xfer_recv_cb_15(gpointer data, gint source, PurpleInputCondition condition)
--{
-- PurpleXfer *xfer;
-- struct yahoo_xfer_data *xd;
-- int did;
-- gchar* buf;
-- gchar* t;
-- PurpleAccount *account;
-- PurpleConnection *gc;
--
-- xfer = data;
-- xd = xfer->data;
-- account = purple_connection_get_account(xd->gc);
-- gc = xd->gc;
--
-- buf=g_strnfill(1000, 0);
-- while((did = read(source, buf, 998)) > 0)
-- {
-- xd->txbuflen += did;
-- buf[did] = '\0';
-- t = xd->txbuf;
-- xd->txbuf = g_strconcat(t,buf,NULL);
-- g_free(t);
-- }
-- g_free(buf);
--
-- if (did < 0 && errno == EAGAIN)
-- return;
-- else if (did < 0) {
-- purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno);
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
--
-- purple_input_remove(xd->tx_handler);
-- xd->tx_handler = 0;
-- xd->txbuflen = 0;
--
-- if(xd->status_15 == HEAD_REQUESTED) {
-- xd->status_15 = HEAD_REPLY_RECEIVED;
-- close(source);/* Is this required? */
-- g_free(xd->txbuf);
-- xd->txbuf = NULL;
-- if (purple_proxy_connect(gc, account, xd->host, xd->port, yahoo_xfer_connected_15, xfer) == NULL)
-- {
-- purple_notify_error(gc, NULL, _("File Transfer Failed"),
-- _("Unable to establish file descriptor."));
-- purple_xfer_cancel_remote(xfer);
-- }
-- } else {
-- purple_debug_error("yahoo","Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n",
-- purple_xfer_get_type(xfer),
-- xd->status_15);
-- return;
-- }
--}
--
--static void yahoo_xfer_send_cb_15(gpointer data, gint source, PurpleInputCondition condition)
--{
-- PurpleXfer *xfer;
-- struct yahoo_xfer_data *xd;
-- int remaining, written;
--
-- xfer = data;
-- xd = xfer->data;
-- remaining = xd->txbuflen - xd->txbuf_written;
-- written = write(source, xd->txbuf + xd->txbuf_written, remaining);
--
-- if (written < 0 && errno == EAGAIN)
-- written = 0;
-- else if (written <= 0) {
-- purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno);
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
--
-- if (written < remaining) {
-- xd->txbuf_written += written;
-- return;
-- }
--
-- purple_input_remove(xd->tx_handler);
-- xd->tx_handler = 0;
-- g_free(xd->txbuf);
-- xd->txbuf = NULL;
-- xd->txbuflen = 0;
-- xd->txbuf_written = 0;
--
-- if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == STARTED)
-- {
-- xd->status_15 = HEAD_REQUESTED;
-- xd->tx_handler = purple_input_add(source, PURPLE_INPUT_READ, yahoo_xfer_recv_cb_15, xfer);
-- yahoo_xfer_recv_cb_15(xfer, source, PURPLE_INPUT_READ);
-- }
-- else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == HEAD_REPLY_RECEIVED)
-- {
-- xd->status_15 = TRANSFER_PHASE;
-- xfer->fd = source;
-- purple_xfer_start(xfer, source, NULL, 0);
-- }
-- else if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && (xd->status_15 == ACCEPTED || xd->status_15 == P2P_GET_REQUESTED) )
-- {
-- xd->status_15 = TRANSFER_PHASE;
-- xfer->fd = source;
-- /* Remove Read event */
-- purple_input_remove(xd->input_event);
-- xd->input_event = 0;
-- purple_xfer_start(xfer, source, NULL, 0);
-- }
-- else if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && xd->status_15 == P2P_HEAD_REQUESTED)
-- {
-- xd->status_15 = P2P_HEAD_REPLIED;
-- /* Remove Read event and close descriptor */
-- purple_input_remove(xd->input_event);
-- xd->input_event = 0;
-- close(source);
-- xfer->fd = -1;
-- /* start local server, listen for connections */
-- purple_network_listen(xd->yahoo_local_p2p_ft_server_port, SOCK_STREAM, yahoo_p2p_ft_server_listen_cb, xfer);
-- }
-- else
-- {
-- purple_debug_error("yahoo", "Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n", purple_xfer_get_type(xfer), xd->status_15);
-- return;
-- }
--}
--
--static void yahoo_xfer_connected_15(gpointer data, gint source, const gchar *error_message)
--{
-- PurpleXfer *xfer;
-- struct yahoo_xfer_data *xd;
-- PurpleAccount *account;
-- PurpleConnection *gc;
--
-- if (!(xfer = data))
-- return;
-- if (!(xd = xfer->data))
-- return;
-- gc = xd->gc;
-- account = purple_connection_get_account(gc);
-- if ((source < 0) || (xd->path == NULL) || (xd->host == NULL)) {
-- purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer),
-- xfer->who, _("Unable to connect."));
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
-- /* The first time we get here, assemble the tx buffer */
-- if (xd->txbuflen == 0)
-- {
-- gchar* cookies;
-- YahooData *yd = gc->proto_data;
--
-- /* cookies = yahoo_get_cookies(gc);
-- * This doesn't seem to be working. The function is returning NULL, which yahoo servers don't like
-- * For now let us not use this function */
--
-- cookies = g_strdup_printf("Y=%s; T=%s", yd->cookie_y, yd->cookie_t);
--
-- if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && xd->status_15 == ACCEPTED)
-- {
-- if(xd->info_val_249 == 2)
-- {
-- /* sending file via p2p, we are connected as client */
-- xd->txbuf = g_strdup_printf("POST /%s HTTP/1.1\r\n"
-- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-- "Host: %s\r\n"
-- "Content-Length: %ld\r\n"
-- "Cache-Control: no-cache\r\n\r\n",
-- xd->path,
-- xd->host,
-- (long int)xfer->size); /* to do, add Referer */
-- }
-- else
-- {
-- /* sending file via relaying */
-- xd->txbuf = g_strdup_printf("POST /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n"
-- "Cookie:%s\r\n"
-- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-- "Host: %s\r\n"
-- "Content-Length: %ld\r\n"
-- "Cache-Control: no-cache\r\n\r\n",
-- purple_url_encode(xd->xfer_idstring_for_relay),
-- purple_normalize(account, purple_account_get_username(account)),
-- xfer->who,
-- cookies,
-- xd->host,
-- (long int)xfer->size);
-- }
-- }
-- else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == STARTED)
-- {
-- if(xd->info_val_249 == 1)
-- {
-- /* receiving file via p2p, connected as client */
-- xd->txbuf = g_strdup_printf("HEAD /%s HTTP/1.1\r\n"
-- "Accept: */*\r\n"
-- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-- "Host: %s\r\n"
-- "Content-Length: 0\r\n"
-- "Cache-Control: no-cache\r\n\r\n",
-- xd->path,xd->host);
-- }
-- else
-- {
-- /* receiving file via relaying */
-- xd->txbuf = g_strdup_printf("HEAD /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n"
-- "Accept: */*\r\n"
-- "Cookie: %s\r\n"
-- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-- "Host: %s\r\n"
-- "Content-Length: 0\r\n"
-- "Cache-Control: no-cache\r\n\r\n",
-- purple_url_encode(xd->xfer_idstring_for_relay),
-- purple_normalize(account, purple_account_get_username(account)),
-- xfer->who,
-- cookies,
-- xd->host);
-- }
-- }
-- else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == HEAD_REPLY_RECEIVED)
-- {
-- if(xd->info_val_249 == 1)
-- {
-- /* receiving file via p2p, connected as client */
-- xd->txbuf = g_strdup_printf("GET /%s HTTP/1.1\r\n"
-- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-- "Host: %s\r\n"
-- "Connection: Keep-Alive\r\n\r\n",
-- xd->path, xd->host);
-- }
-- else
-- {
-- /* receiving file via relaying */
-- xd->txbuf = g_strdup_printf("GET /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n"
-- "Cookie: %s\r\n"
-- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-- "Host: %s\r\n"
-- "Connection: Keep-Alive\r\n\r\n",
-- purple_url_encode(xd->xfer_idstring_for_relay),
-- purple_normalize(account, purple_account_get_username(account)),
-- xfer->who,
-- cookies,
-- xd->host);
-- }
-- }
-- else
-- {
-- purple_debug_error("yahoo", "Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n", purple_xfer_get_type(xfer), xd->status_15);
-- g_free(cookies);
-- return;
-- }
-- xd->txbuflen = strlen(xd->txbuf);
-- xd->txbuf_written = 0;
-- g_free(cookies);
-- }
--
-- if (!xd->tx_handler)
-- {
-- xd->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE,
-- yahoo_xfer_send_cb_15, xfer);
-- yahoo_xfer_send_cb_15(xfer, source, PURPLE_INPUT_WRITE);
-- }
--}
--
--static void yahoo_p2p_ft_POST_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- PurpleXfer *xfer;
-- struct yahoo_xfer_data *xd;
--
-- xfer = data;
-- if (!(xd = xfer->data)) {
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
--
-- purple_input_remove(xd->input_event);
-- xd->status_15 = TRANSFER_PHASE;
-- xfer->fd = source;
-- purple_xfer_start(xfer, source, NULL, 0);
--}
--
--static void yahoo_p2p_ft_HEAD_GET_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- PurpleXfer *xfer;
-- struct yahoo_xfer_data *xd;
-- guchar buf[1024];
-- int len;
-- char *url_head;
-- char *url_get;
-- time_t unix_time;
-- char *time_str;
--
-- xfer = data;
-- if (!(xd = xfer->data)) {
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
--
-- len = read(source, buf, sizeof(buf));
-- if ((len < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
-- return ; /* No Worries*/
-- else if (len <= 0) {
-- purple_debug_warning("yahoo","p2p-ft: Error in connection, or host disconnected\n");
-- purple_input_remove(xd->input_event);
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
--
-- url_head = g_strdup_printf("HEAD %s", xd->xfer_url);
-- url_get = g_strdup_printf("GET %s", xd->xfer_url);
--
-- if( strncmp(url_head, (char *)buf, strlen(url_head)) == 0 )
-- xd->status_15 = P2P_HEAD_REQUESTED;
-- else if( strncmp(url_get, (char *)buf, strlen(url_get)) == 0 )
-- xd->status_15 = P2P_GET_REQUESTED;
-- else {
-- purple_debug_warning("yahoo","p2p-ft: Wrong HEAD/GET request from peer, disconnecting host\n");
-- purple_input_remove(xd->input_event);
-- purple_xfer_cancel_remote(xfer);
-- g_free(url_head);
-- return;
-- }
--
-- unix_time = time(NULL);
-- time_str = ctime(&unix_time);
-- time_str[strlen(time_str) - 1] = '\0';
--
-- if (xd->txbuflen == 0) {
-- xd->txbuf = g_strdup_printf("HTTP/1.0 200 OK\r\n"
-- "Date: %s GMT\r\n"
-- "Server: Y!/1.0\r\n"
-- "MIME-version: 1.0\r\n"
-- "Last-modified: %s GMT\r\n"
-- "Content-length: %" G_GSIZE_FORMAT "\r\n\r\n",
-- time_str, time_str, xfer->size);
-- xd->txbuflen = strlen(xd->txbuf);
-- xd->txbuf_written = 0;
-- }
--
-- if (!xd->tx_handler) {
-- xd->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE, yahoo_xfer_send_cb_15, xfer);
-- yahoo_xfer_send_cb_15(xfer, source, PURPLE_INPUT_WRITE);
-- }
--
-- g_free(url_head);
-- g_free(url_get);
--}
--
--static void yahoo_p2p_ft_server_send_connected_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- int acceptfd;
-- PurpleXfer *xfer;
-- struct yahoo_xfer_data *xd;
--
-- xfer = data;
-- if (!(xd = xfer->data)) {
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
--
-- acceptfd = accept(source, NULL, 0);
-- if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
-- return;
-- else if(acceptfd == -1) {
-- purple_debug_warning("yahoo","yahoo_p2p_server_send_connected_cb: accept: %s\n", g_strerror(errno));
-- purple_xfer_cancel_remote(xfer);
-- /* remove watcher and close p2p ft server */
-- purple_input_remove(xd->yahoo_p2p_ft_server_watcher);
-- close(xd->yahoo_local_p2p_ft_server_fd);
-- return;
-- }
--
-- /* remove watcher and close p2p ft server */
-- purple_input_remove(xd->yahoo_p2p_ft_server_watcher);
-- close(xd->yahoo_local_p2p_ft_server_fd);
--
-- /* Add an Input Read event to the file descriptor */
-- xfer->fd = acceptfd;
-- if(xfer->type == PURPLE_XFER_RECEIVE)
-- xd->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_ft_POST_cb, data);
-- else
-- xd->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_ft_HEAD_GET_cb, data);
--}
--
--static void yahoo_p2p_ft_server_listen_cb(int listenfd, gpointer data)
--{
-- PurpleXfer *xfer;
-- struct yahoo_xfer_data *xd;
-- struct yahoo_packet *pkt;
-- PurpleAccount *account;
-- YahooData *yd;
-- gchar *filename;
-- const char *local_ip;
-- gchar *url_to_send = NULL;
-- char *filename_without_spaces = NULL;
--
-- xfer = data;
-- if (!(xd = xfer->data) || (listenfd == -1)) {
-- purple_debug_warning("yahoo","p2p: error starting server for p2p file transfer\n");
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
--
-- if( (xfer->type == PURPLE_XFER_RECEIVE) || (xd->status_15 != P2P_HEAD_REPLIED) ) {
-- yd = xd->gc->proto_data;
-- account = purple_connection_get_account(xd->gc);
-- local_ip = purple_network_get_my_ip(listenfd);
-- xd->yahoo_local_p2p_ft_server_port = purple_network_get_port_from_fd(listenfd);
--
-- filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
-- filename_without_spaces = g_strdup(filename);
-- purple_util_chrreplace(filename_without_spaces, ' ', '+');
-- xd->xfer_url = g_strdup_printf("/Messenger.%s.%d000%s?AppID=Messenger&UserID=%s&K=lc9lu2u89gz1llmplwksajkjx", xfer->who, (int)time(NULL), filename_without_spaces, xfer->who);
-- url_to_send = g_strdup_printf("http://%s:%d%s", local_ip, xd->yahoo_local_p2p_ft_server_port, xd->xfer_url);
--
-- if(xfer->type == PURPLE_XFER_RECEIVE) {
-- xd->info_val_249 = 2; /* 249=2: we are p2p server, and receiving file */
-- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15,
-- YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash(pkt, "ssssis",
-- 1, purple_normalize(account, purple_account_get_username(account)),
-- 5, xfer->who,
-- 265, xd->xfer_peer_idstring,
-- 27, xfer->filename,
-- 249, 2,
-- 250, url_to_send);
-- }
-- else {
-- xd->info_val_249 = 1; /* 249=1: we are p2p server, and sending file */
-- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash(pkt, "ssssis",
-- 1, purple_normalize(account, purple_account_get_username(account)),
-- 5, xfer->who,
-- 265, xd->xfer_peer_idstring,
-- 27, filename,
-- 249, 1,
-- 250, url_to_send);
-- }
--
-- yahoo_packet_send_and_free(pkt, yd);
--
-- g_free(filename);
-- g_free(url_to_send);
-- g_free(filename_without_spaces);
-- }
--
-- /* Add an Input Read event to the file descriptor */
-- xd->yahoo_local_p2p_ft_server_fd = listenfd;
-- xd->yahoo_p2p_ft_server_watcher = purple_input_add(listenfd, PURPLE_INPUT_READ, yahoo_p2p_ft_server_send_connected_cb, data);
--}
--
--/* send (p2p) file transfer information */
--static void yahoo_p2p_client_send_ft_info(PurpleConnection *gc, PurpleXfer *xfer)
--{
-- struct yahoo_xfer_data *xd;
-- struct yahoo_packet *pkt;
-- PurpleAccount *account;
-- YahooData *yd;
-- gchar *filename;
-- struct yahoo_p2p_data *p2p_data;
--
-- if (!(xd = xfer->data))
-- return;
--
-- account = purple_connection_get_account(gc);
-- yd = gc->proto_data;
--
-- p2p_data = g_hash_table_lookup(yd->peers, xfer->who);
-- if( p2p_data->connection_type == YAHOO_P2P_WE_ARE_SERVER )
-- if(purple_network_listen_range(0, 0, SOCK_STREAM, yahoo_p2p_ft_server_listen_cb, xfer))
-- return;
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
--
-- yahoo_packet_hash(pkt, "ssssi",
-- 1, purple_normalize(account, purple_account_get_username(account)),
-- 5, xfer->who,
-- 265, xd->xfer_peer_idstring,
-- 27, filename,
-- 249, 2); /* 249=2: we are p2p client */
-- xd->info_val_249 = 2;
-- yahoo_packet_send_and_free(pkt, yd);
--
-- g_free(filename);
--}
--
--void yahoo_process_filetrans_15(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- char *from = NULL;
-- char *to = NULL;
-- char *imv = NULL;
-- long val_222 = 0L;
-- PurpleXfer *xfer;
-- YahooData *yd;
-- struct yahoo_xfer_data *xfer_data;
-- char *service = NULL;
-- char *filename = NULL;
-- char *xfer_peer_idstring = NULL;
-- char *utf8_filename;
-- unsigned long filesize = 0L;
-- GSList *l;
-- GSList *filename_list = NULL;
-- GSList *size_list = NULL;
-- int nooffiles = 0;
--
-- yd = gc->proto_data;
--
-- for (l = pkt->hash; l; l = l->next) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 4:
-- from = pair->value;
-- break;
-- case 5:
-- to = pair->value;
-- break;
-- case 265:
-- xfer_peer_idstring = pair->value;
-- break;
-- case 27:
-- filename_list = g_slist_prepend(filename_list, g_strdup(pair->value));
-- nooffiles++;
-- break;
-- case 28:
-- size_list = g_slist_prepend(size_list, g_strdup(pair->value));
-- break;
-- case 222:
-- val_222 = atol(pair->value);
-- /* 1=send, 2=cancel, 3=accept, 4=reject */
-- break;
--
-- /* check for p2p and imviron .... not sure it comes by this service packet. Since it was bundled with filexfer in old ymsg version, still keeping it. */
-- case 49:
-- service = pair->value;
-- break;
-- case 63:
-- imv = pair->value;
-- break;
-- /* end check */
--
-- }
-- }
-- if(!xfer_peer_idstring)
-- return;
--
-- if(val_222 == 2 || val_222 == 4)
-- {
-- xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map,
-- xfer_peer_idstring);
-- if(!xfer) return;
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
-- if(val_222 == 3)
-- {
-- PurpleAccount *account;
-- xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map,
-- xfer_peer_idstring);
-- if(!xfer)
-- return;
-- /*
-- * In the file trans info packet that we must reply with, we are
-- * supposed to mention the ip address...
-- * purple connect does not give me a way of finding the ip address...
-- * so, purple dnsquery is used... but retries, trying with next ip
-- * address etc. is not implemented..TODO
-- */
--
-- /* To send through p2p */
-- if( g_hash_table_lookup(yd->peers, from) ) {
-- /* send p2p file transfer information */
-- yahoo_p2p_client_send_ft_info(gc, xfer);
-- return;
-- }
--
-- account = purple_connection_get_account(gc);
-- if (yd->jp)
-- {
-- purple_dnsquery_a_account(account, YAHOOJP_XFER_RELAY_HOST,
-- YAHOOJP_XFER_RELAY_PORT,
-- yahoo_xfer_dns_connected_15, xfer);
-- }
-- else
-- {
-- purple_dnsquery_a_account(account, YAHOO_XFER_RELAY_HOST,
-- YAHOO_XFER_RELAY_PORT,
-- yahoo_xfer_dns_connected_15, xfer);
-- }
-- return;
-- }
--
-- /* processing for p2p and imviron .... not sure it comes by this service packet. Since it was bundled with filexfer in old ymsg version, still keeping it. */
-- /*
-- * The remote user has changed their IMVironment. We
-- * record it for later use.
-- */
-- if (from && imv && service && (strcmp("IMVIRONMENT", service) == 0)) {
-- g_hash_table_replace(yd->imvironments, g_strdup(from), g_strdup(imv));
-- return;
-- }
--
-- if (pkt->service == YAHOO_SERVICE_P2PFILEXFER) {
-- if (service && (strcmp("FILEXFER", service) != 0)) {
-- purple_debug_misc("yahoo", "unhandled service 0x%02x\n", pkt->service);
-- return;
-- }
-- }
-- /* end processing */
--
-- if(!filename_list)
-- return;
-- /* have to change list into order in which client at other end sends */
-- filename_list = g_slist_reverse(filename_list);
-- size_list = g_slist_reverse(size_list);
-- filename = filename_list->data;
-- filesize = atol(size_list->data);
--
-- if(!from) return;
-- xfer_data = g_new0(struct yahoo_xfer_data, 1);
-- xfer_data->version = 15;
-- xfer_data->firstoflist = TRUE;
-- xfer_data->gc = gc;
-- xfer_data->xfer_peer_idstring = g_strdup(xfer_peer_idstring);
-- xfer_data->filename_list = filename_list;
-- xfer_data->size_list = size_list;
--
-- /* Build the file transfer handle. */
-- xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, from);
-- if (xfer == NULL)
-- {
-- g_free(xfer_data);
-- g_return_if_reached();
-- }
--
-- xfer->message = NULL;
--
-- /* Set the info about the incoming file. */
-- utf8_filename = yahoo_string_decode(gc, filename, TRUE);
-- purple_xfer_set_filename(xfer, utf8_filename);
-- g_free(utf8_filename);
-- purple_xfer_set_size(xfer, filesize);
--
-- xfer->data = xfer_data;
--
-- /* Setup our I/O op functions */
-- purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15);
-- purple_xfer_set_start_fnc(xfer, yahoo_xfer_start);
-- purple_xfer_set_end_fnc(xfer, yahoo_xfer_end);
-- purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send);
-- purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv);
-- purple_xfer_set_read_fnc(xfer, yahoo_xfer_read);
-- purple_xfer_set_write_fnc(xfer, yahoo_xfer_write);
-- purple_xfer_set_request_denied_fnc(xfer,yahoo_xfer_cancel_recv);
--
-- g_hash_table_insert(yd->xfer_peer_idstring_map,
-- xfer_data->xfer_peer_idstring,
-- xfer);
--
-- if(nooffiles > 1) {
-- gchar* message;
-- message = g_strdup_printf(_("%s is trying to send you a group of %d files.\n"), xfer->who, nooffiles);
-- purple_xfer_conversation_write(xfer, message, FALSE);
-- g_free(message);
-- }
-- /* Now perform the request */
-- purple_xfer_request(xfer);
--}
--
--void yahoo_process_filetrans_info_15(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- char *from = NULL;
-- char *to = NULL;
-- char *url = NULL;
-- long val_249 = 0;
-- long val_66 = 0;
-- PurpleXfer *xfer;
-- YahooData *yd;
-- struct yahoo_xfer_data *xfer_data;
-- char *filename = NULL;
-- char *xfer_peer_idstring = NULL;
-- char *xfer_idstring_for_relay = NULL;
-- GSList *l;
-- struct yahoo_packet *pkt_to_send;
-- struct yahoo_p2p_data *p2p_data;
--
-- yd = gc->proto_data;
--
-- for (l = pkt->hash; l; l = l->next) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 4:
-- from = pair->value;
-- break;
-- case 5:
-- to = pair->value;
-- break;
-- case 265:
-- xfer_peer_idstring = pair->value;
-- break;
-- case 27:
-- filename = pair->value;
-- break;
-- case 66:
-- val_66 = strtol(pair->value, NULL, 10);
-- break;
-- case 249:
-- val_249 = strtol(pair->value, NULL, 10);
-- /* 249 has value 1 or 2 when doing p2p transfer and value 3 when relaying through yahoo server */
-- break;
-- case 250:
-- url = pair->value;
-- break;
-- case 251:
-- xfer_idstring_for_relay = pair->value;
-- break;
-- }
-- }
--
-- if(!xfer_peer_idstring)
-- return;
--
-- xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xfer_peer_idstring);
--
-- if(!xfer) return;
--
-- if(val_66==-1)
-- {
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
--
-- xfer_data = xfer->data;
--
-- xfer_data->info_val_249 = val_249;
-- xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay);
-- if(val_249 == 1 || val_249 == 3) {
-- PurpleAccount *account;
-- if (!purple_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL)) {
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
--
-- account = purple_connection_get_account(xfer_data->gc);
--
-- pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15,
-- YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash(pkt_to_send, "ssssis",
-- 1, purple_normalize(account, purple_account_get_username(account)),
-- 5, xfer->who,
-- 265, xfer_data->xfer_peer_idstring,
-- 27, xfer->filename,
-- 249, xfer_data->info_val_249,
-- 251, xfer_data->xfer_idstring_for_relay);
--
-- yahoo_packet_send_and_free(pkt_to_send, yd);
--
-- if (purple_proxy_connect(gc, account, xfer_data->host, xfer_data->port,
-- yahoo_xfer_connected_15, xfer) == NULL) {
-- purple_notify_error(gc, NULL, _("File Transfer Failed"),
-- _("Unable to establish file descriptor."));
-- purple_xfer_cancel_remote(xfer);
-- }
-- }
-- else if(val_249 == 2) {
-- p2p_data = g_hash_table_lookup(yd->peers, xfer->who);
-- if( !( p2p_data && (p2p_data->connection_type == YAHOO_P2P_WE_ARE_SERVER) ) ) {
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
-- if(!purple_network_listen_range(0, 0, SOCK_STREAM, yahoo_p2p_ft_server_listen_cb, xfer)) {
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
-- }
--}
--
--/* TODO: Check filename etc. No probs till some hacker comes in the way */
--void yahoo_process_filetrans_acc_15(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- gchar *xfer_peer_idstring = NULL;
-- gchar *xfer_idstring_for_relay = NULL;
-- PurpleXfer *xfer;
-- YahooData *yd;
-- struct yahoo_xfer_data *xfer_data;
-- GSList *l;
-- PurpleAccount *account;
-- long val_66 = 0;
-- gchar *url = NULL;
-- int val_249 = 0;
--
-- yd = gc->proto_data;
-- for (l = pkt->hash; l; l = l->next) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 251:
-- xfer_idstring_for_relay = pair->value;
-- break;
-- case 265:
-- xfer_peer_idstring = pair->value;
-- break;
-- case 66:
-- val_66 = atol(pair->value);
-- break;
-- case 249:
-- val_249 = atol(pair->value);
-- break;
-- case 250:
-- url = pair->value; /* we get a p2p url here when sending file, connected as client */
-- break;
-- }
-- }
--
-- xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xfer_peer_idstring);
-- if(!xfer) return;
--
-- if(val_66 == -1 || ( (!(xfer_idstring_for_relay)) && (val_249 != 2) ))
-- {
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
--
-- if( (val_249 == 2) && (!(url)) )
-- {
-- purple_xfer_cancel_remote(xfer);
-- return;
-- }
--
-- xfer_data = xfer->data;
-- if(url)
-- purple_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL);
--
-- xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay);
-- xfer_data->status_15 = ACCEPTED;
-- account = purple_connection_get_account(gc);
--
-- if (purple_proxy_connect(gc, account, xfer_data->host, xfer_data->port,
-- yahoo_xfer_connected_15, xfer) == NULL)
-- {
-- purple_notify_error(gc, NULL, _("File Transfer Failed"),_("Unable to connect"));
-- purple_xfer_cancel_remote(xfer);
-- }
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_filexfer.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_filexfer.h
---- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_filexfer.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_filexfer.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,70 +0,0 @@
--/*
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef _YAHOO_FILEXFER_H_
--#define _YAHOO_FILEXFER_H_
--
--#include "ft.h"
--
--/**
-- * Process ymsg events, particular IMViroments like Doodle
-- */
--void yahoo_process_p2pfilexfer( PurpleConnection *gc, struct yahoo_packet *pkt );
--
--/**
-- * Process ymsg file receive invites.
-- */
--void yahoo_process_filetransfer(PurpleConnection *gc, struct yahoo_packet *pkt);
--
--/**
-- * Create a new PurpleXfer
-- *
-- * @param gc The PurpleConnection handle.
-- * @param who Who will we be sending it to?
-- */
--PurpleXfer *yahoo_new_xfer(PurpleConnection *gc, const char *who);
--
--/**
-- * Returns TRUE if the buddy can receive file, FALSE otherwise.
-- * Federated users cannot receive files. So this will return FALSE only
-- * for them.
-- *
-- * @param gc The connection
-- * @param who The name of the remote user
-- *
-- * @return TRUE or FALSE
-- */
--gboolean yahoo_can_receive_file(PurpleConnection *gc, const char *who);
--
--/**
-- * Send a file.
-- *
-- * @param gc The PurpleConnection handle.
-- * @param who Who are we sending it to?
-- * @param file What file? If NULL, user will choose after this call.
-- */
--void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file);
--
--void yahoo_process_filetrans_15(PurpleConnection *gc, struct yahoo_packet *pkt);
--void yahoo_process_filetrans_info_15(PurpleConnection *gc, struct yahoo_packet *pkt);
--void yahoo_process_filetrans_acc_15(PurpleConnection *gc, struct yahoo_packet *pkt);
--
--#endif
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_friend.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_friend.c
---- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_friend.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_friend.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,325 +0,0 @@
--/*
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include "internal.h"
--#include "prpl.h"
--#include "util.h"
--#include "debug.h"
--
--#include "yahoo_friend.h"
--#include "yahoo_aliases.h"
--
--static YahooFriend *yahoo_friend_new(void)
--{
-- YahooFriend *ret;
--
-- ret = g_new0(YahooFriend, 1);
-- ret->status = YAHOO_STATUS_OFFLINE;
-- ret->presence = YAHOO_PRESENCE_DEFAULT;
--
-- return ret;
--}
--
--YahooFriend *yahoo_friend_find(PurpleConnection *gc, const char *name)
--{
-- YahooData *yd;
-- const char *norm;
--
-- g_return_val_if_fail(gc != NULL, NULL);
-- g_return_val_if_fail(gc->proto_data != NULL, NULL);
--
-- yd = gc->proto_data;
-- norm = purple_normalize(purple_connection_get_account(gc), name);
--
-- return g_hash_table_lookup(yd->friends, norm);
--}
--
--YahooFriend *yahoo_friend_find_or_new(PurpleConnection *gc, const char *name)
--{
-- YahooFriend *f;
-- YahooData *yd;
-- const char *norm;
--
-- g_return_val_if_fail(gc != NULL, NULL);
-- g_return_val_if_fail(gc->proto_data != NULL, NULL);
--
-- yd = gc->proto_data;
-- norm = purple_normalize(purple_connection_get_account(gc), name);
--
-- f = g_hash_table_lookup(yd->friends, norm);
-- if (!f) {
-- f = yahoo_friend_new();
-- g_hash_table_insert(yd->friends, g_strdup(norm), f);
-- }
--
-- return f;
--}
--
--void yahoo_friend_set_ip(YahooFriend *f, const char *ip)
--{
-- g_free(f->ip);
-- f->ip = g_strdup(ip);
--}
--
--const char *yahoo_friend_get_ip(YahooFriend *f)
--{
-- return f->ip;
--}
--
--void yahoo_friend_set_game(YahooFriend *f, const char *game)
--{
-- g_free(f->game);
--
-- if (game)
-- f->game = g_strdup(game);
-- else
-- f->game = NULL;
--}
--
--const char *yahoo_friend_get_game(YahooFriend *f)
--{
-- return f->game;
--}
--
--void yahoo_friend_set_status_message(YahooFriend *f, char *msg)
--{
-- g_free(f->msg);
--
-- f->msg = msg;
--}
--
--const char *yahoo_friend_get_status_message(YahooFriend *f)
--{
-- return f->msg;
--}
--
--void yahoo_friend_set_buddy_icon_need_request(YahooFriend *f, gboolean needs)
--{
-- f->bicon_sent_request = !needs;
--}
--
--gboolean yahoo_friend_get_buddy_icon_need_request(YahooFriend *f)
--{
-- return !f->bicon_sent_request;
--}
--
--void yahoo_friend_set_alias_id(YahooFriend *f, const char *alias_id)
--{
-- g_free(f->ypd.id);
-- f->ypd.id = g_strdup(alias_id);
--}
--
--const char *yahoo_friend_get_alias_id(YahooFriend *f)
--{
-- return f->ypd.id;
--}
--
--void yahoo_friend_free(gpointer p)
--{
-- YahooFriend *f = p;
-- g_free(f->msg);
-- g_free(f->game);
-- g_free(f->ip);
-- yahoo_personal_details_reset(&f->ypd, TRUE);
-- g_free(f);
--}
--
--void yahoo_process_presence(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- GSList *l = pkt->hash;
-- YahooFriend *f;
-- char *temp = NULL;
-- char *who = NULL;
-- int value = 0;
-- YahooFederation fed = YAHOO_FEDERATION_NONE;
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 7:
-- temp = pair->value;
-- break;
-- case 31:
-- value = strtol(pair->value, NULL, 10);
-- break;
-- case 241:
-- fed = strtol(pair->value, NULL, 10);
-- break;
-- }
--
-- l = l->next;
-- }
--
-- if (value != 1 && value != 2) {
-- purple_debug_error("yahoo", "Received unknown value for presence key: %d\n", value);
-- return;
-- }
--
-- switch (fed) {
-- case YAHOO_FEDERATION_MSN:
-- who = g_strconcat("msn/", temp, NULL);
-- break;
-- case YAHOO_FEDERATION_OCS:
-- who = g_strconcat("ocs/", temp, NULL);
-- break;
-- case YAHOO_FEDERATION_IBM:
-- who = g_strconcat("ibm/", temp, NULL);
-- break;
-- case YAHOO_FEDERATION_PBX:
-- who = g_strconcat("pbx/", temp, NULL);
-- break;
-- case YAHOO_FEDERATION_NONE:
-- who = g_strdup(temp);
-- break;
-- }
-- g_return_if_fail(who != NULL);
--
-- f = yahoo_friend_find(gc, who);
-- if (!f) {
-- g_free(who);
-- return;
-- }
--
-- if (pkt->service == YAHOO_SERVICE_PRESENCE_PERM) {
-- purple_debug_info("yahoo", "Setting permanent presence for %s to %d.\n", who, (value == 1));
-- /* If setting from perm offline to online when in invisible status,
-- * this has already been taken care of (when the temp status changed) */
-- if (value == 2 && f->presence == YAHOO_PRESENCE_ONLINE) {
-- } else {
-- if (value == 1) /* Setting Perm offline */
-- f->presence = YAHOO_PRESENCE_PERM_OFFLINE;
-- else
-- f->presence = YAHOO_PRESENCE_DEFAULT;
-- }
-- } else {
-- purple_debug_info("yahoo", "Setting session presence for %s to %d.\n", who, (value == 1));
-- if (value == 1)
-- f->presence = YAHOO_PRESENCE_ONLINE;
-- else
-- f->presence = YAHOO_PRESENCE_DEFAULT;
-- }
-- g_free(who);
--}
--
--void yahoo_friend_update_presence(PurpleConnection *gc, const char *name,
-- YahooPresenceVisibility presence)
--{
-- YahooData *yd = gc->proto_data;
-- struct yahoo_packet *pkt = NULL;
-- YahooFriend *f;
-- const char *thirtyone, *thirteen;
-- int service = -1;
-- const char *temp = NULL;
--
-- if (!yd->logged_in)
-- return;
--
-- f = yahoo_friend_find(gc, name);
-- if (!f)
-- return;
--
-- if(f->fed != YAHOO_FEDERATION_NONE)
-- temp = name+4;
-- else
-- temp = name;
--
-- /* No need to change the value if it is already correct */
-- if (f->presence == presence) {
-- purple_debug_info("yahoo", "Not setting presence because there are no changes.\n");
-- return;
-- }
--
-- if (presence == YAHOO_PRESENCE_PERM_OFFLINE) {
-- service = YAHOO_SERVICE_PRESENCE_PERM;
-- thirtyone = "1";
-- thirteen = "2";
-- } else if (presence == YAHOO_PRESENCE_DEFAULT) {
-- if (f->presence == YAHOO_PRESENCE_PERM_OFFLINE) {
-- service = YAHOO_SERVICE_PRESENCE_PERM;
-- thirtyone = "2";
-- thirteen = "2";
-- } else if (yd->current_status == YAHOO_STATUS_INVISIBLE) {
-- service = YAHOO_SERVICE_PRESENCE_SESSION;
-- thirtyone = "2";
-- thirteen = "1";
-- }
-- } else if (presence == YAHOO_PRESENCE_ONLINE) {
-- if (f->presence == YAHOO_PRESENCE_PERM_OFFLINE) {
-- pkt = yahoo_packet_new(YAHOO_SERVICE_PRESENCE_PERM,
-- YAHOO_STATUS_AVAILABLE, yd->session_id);
-- if(f->fed)
-- yahoo_packet_hash(pkt, "ssssssiss",
-- 1, purple_connection_get_display_name(gc),
-- 31, "2", 13, "2",
-- 302, "319", 300, "319",
-- 7, temp, 241, f->fed,
-- 301, "319", 303, "319");
-- else
-- yahoo_packet_hash(pkt, "ssssssss",
-- 1, purple_connection_get_display_name(gc),
-- 31, "2", 13, "2",
-- 302, "319", 300, "319",
-- 7, temp,
-- 301, "319", 303, "319");
--
-- yahoo_packet_send_and_free(pkt, yd);
-- }
--
-- service = YAHOO_SERVICE_PRESENCE_SESSION;
-- thirtyone = "1";
-- thirteen = "1";
-- }
--
-- if (service > 0) {
-- pkt = yahoo_packet_new(service,
-- YAHOO_STATUS_AVAILABLE, yd->session_id);
--
-- if(f->fed)
-- yahoo_packet_hash(pkt, "ssssssiss",
-- 1, purple_connection_get_display_name(gc),
-- 31, thirtyone, 13, thirteen,
-- 302, "319", 300, "319",
-- 7, temp, 241, f->fed,
-- 301, "319", 303, "319");
-- else
-- yahoo_packet_hash(pkt, "ssssssss",
-- 1, purple_connection_get_display_name(gc),
-- 31, thirtyone, 13, thirteen,
-- 302, "319", 300, "319",
-- 7, temp,
-- 301, "319", 303, "319");
--
-- yahoo_packet_send_and_free(pkt, yd);
-- }
--}
--
--void yahoo_friend_set_p2p_status(YahooFriend *f, YahooP2PStatus p2p_status)
--{
-- f->p2p_status = p2p_status;
--}
--
--YahooP2PStatus yahoo_friend_get_p2p_status(YahooFriend *f)
--{
-- return f->p2p_status;
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_friend.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_friend.h
---- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_friend.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_friend.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,93 +0,0 @@
--/**
-- * @file yahoo_friend.h The Yahoo! protocol plugin YahooFriend object
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _YAHOO_FRIEND_H_
--#define _YAHOO_FRIEND_H_
--
--#include "libymsg.h"
--#include "yahoo_packet.h"
--
--typedef enum {
-- YAHOO_PRESENCE_DEFAULT = 0,
-- YAHOO_PRESENCE_ONLINE,
-- YAHOO_PRESENCE_PERM_OFFLINE
--} YahooPresenceVisibility;
--
--typedef enum {
-- YAHOO_P2PSTATUS_NOT_CONNECTED = 0,
-- YAHOO_P2PSTATUS_DO_NOT_CONNECT,
-- YAHOO_P2PSTATUS_WE_ARE_SERVER,
-- YAHOO_P2PSTATUS_WE_ARE_CLIENT
--} YahooP2PStatus;
--
--
--/* these are called friends instead of buddies mainly so I can use variables
-- * named f and not confuse them with variables named b
-- */
--typedef struct _YahooFriend {
-- enum yahoo_status status;
-- gchar *msg;
-- gchar *game;
-- int idle;
-- int away;
-- gboolean sms;
-- gchar *ip;
-- gboolean bicon_sent_request;
-- YahooPresenceVisibility presence;
-- YahooFederation fed;
-- long int version_id;
-- YahooPersonalDetails ypd;
-- YahooP2PStatus p2p_status;
-- gboolean p2p_packet_sent; /* 0:not sent, 1=sent */
-- gint session_id; /* session id of friend */
--} YahooFriend;
--
--YahooFriend *yahoo_friend_find(PurpleConnection *gc, const char *name);
--YahooFriend *yahoo_friend_find_or_new(PurpleConnection *gc, const char *name);
--
--void yahoo_friend_set_ip(YahooFriend *f, const char *ip);
--const char *yahoo_friend_get_ip(YahooFriend *f);
--
--void yahoo_friend_set_game(YahooFriend *f, const char *game);
--const char *yahoo_friend_get_game(YahooFriend *f);
--
--void yahoo_friend_set_status_message(YahooFriend *f, char *msg);
--const char *yahoo_friend_get_status_message(YahooFriend *f);
--
--void yahoo_friend_set_alias_id(YahooFriend *f, const char *alias_id);
--const char *yahoo_friend_get_alias_id(YahooFriend *f);
--
--void yahoo_friend_set_buddy_icon_need_request(YahooFriend *f, gboolean needs);
--gboolean yahoo_friend_get_buddy_icon_need_request(YahooFriend *f);
--
--void yahoo_friend_free(gpointer p);
--
--void yahoo_process_presence(PurpleConnection *gc, struct yahoo_packet *pkt);
--void yahoo_friend_update_presence(PurpleConnection *gc, const char *name,
-- YahooPresenceVisibility presence);
--
--void yahoo_friend_set_p2p_status(YahooFriend *f, YahooP2PStatus p2p_status);
--YahooP2PStatus yahoo_friend_get_p2p_status(YahooFriend *f);
--
--#endif /* _YAHOO_FRIEND_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_packet.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_packet.c
---- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_packet.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_packet.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,403 +0,0 @@
--/*
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include "internal.h"
--#include "debug.h"
--
--#include "libymsg.h"
--#include "yahoo_packet.h"
--
--struct yahoo_packet *yahoo_packet_new(enum yahoo_service service, enum yahoo_status status, int id)
--{
-- struct yahoo_packet *pkt = g_new0(struct yahoo_packet, 1);
--
-- pkt->service = service;
-- pkt->status = status;
-- pkt->id = id;
--
-- return pkt;
--}
--
--void yahoo_packet_hash_str(struct yahoo_packet *pkt, int key, const char *value)
--{
-- struct yahoo_pair *pair;
--
-- g_return_if_fail(value != NULL);
--
-- pair = g_new0(struct yahoo_pair, 1);
-- pair->key = key;
-- pair->value = g_strdup(value);
-- pkt->hash = g_slist_prepend(pkt->hash, pair);
--}
--
--void yahoo_packet_hash_int(struct yahoo_packet *pkt, int key, int value)
--{
-- struct yahoo_pair *pair;
--
-- pair = g_new0(struct yahoo_pair, 1);
-- pair->key = key;
-- pair->value = g_strdup_printf("%d", value);
-- pkt->hash = g_slist_prepend(pkt->hash, pair);
--}
--
--void yahoo_packet_hash(struct yahoo_packet *pkt, const char *fmt, ...)
--{
-- char *strval;
-- int key, intval;
-- const char *cur;
-- va_list ap;
--
-- va_start(ap, fmt);
-- for (cur = fmt; *cur; cur++) {
-- key = va_arg(ap, int);
-- switch (*cur) {
-- case 'i':
-- intval = va_arg(ap, int);
-- yahoo_packet_hash_int(pkt, key, intval);
-- break;
-- case 's':
-- strval = va_arg(ap, char *);
-- yahoo_packet_hash_str(pkt, key, strval);
-- break;
-- default:
-- purple_debug_error("yahoo", "Invalid format character '%c'\n", *cur);
-- break;
-- }
-- }
-- va_end(ap);
--}
--
--size_t yahoo_packet_length(struct yahoo_packet *pkt)
--{
-- GSList *l;
--
-- size_t len = 0;
--
-- l = pkt->hash;
-- while (l) {
-- struct yahoo_pair *pair = l->data;
-- int tmp = pair->key;
-- do {
-- tmp /= 10;
-- len++;
-- } while (tmp);
-- len += 2;
-- len += strlen(pair->value);
-- len += 2;
-- l = l->next;
-- }
--
-- return len;
--}
--
--/*
-- * 'len' is the value given to us by the server that is supposed to
-- * be the length of 'data'. But apparently there's a time when this
-- * length is incorrect. Christopher Layne thinks it might be a bug
-- * in their server code.
-- *
-- * The following information is from Christopher:
-- *
-- * It sometimes happens when Yahoo! sends a packet continuation within
-- * chat. Sometimes when joining a large chatroom the initial
-- * SERVICE_CHATJOIN packet will be so large that it will need to be
-- * split into multiple packets. That's fine, except that the length
-- * of the second packet is wrong. The packet has the same length as
-- * the first packet, and the length given in the header is the same,
-- * however the actual data in the packet is shorter than this length.
-- * So half of the packet contains good, valid data, and then the rest
-- * of the packet is junk. Luckily there is a null terminator after
-- * the valid data and before the invalid data.
-- *
-- * What does all this mean? It means that we parse through the data
-- * pulling out key/value pairs until we've parsed 'len' bytes, or until
-- * we run into a null terminator, whichever comes first.
-- */
--void yahoo_packet_read(struct yahoo_packet *pkt, const guchar *data, int len)
--{
-- int pos = 0;
-- char key[64];
-- const guchar *delimiter;
-- gboolean accept;
-- int x;
-- struct yahoo_pair *pair;
--
-- while (pos + 1 < len)
-- {
-- if (data[pos] == '\0')
-- break;
--
-- pair = g_new0(struct yahoo_pair, 1);
--
-- x = 0;
-- while (pos + 1 < len) {
-- if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
-- break;
-- if (x >= sizeof(key)-1) {
-- x++;
-- pos++;
-- continue;
-- }
-- key[x++] = data[pos++];
-- }
-- if (x >= sizeof(key)-1) {
-- x = 0;
-- }
-- key[x] = 0;
-- pos += 2;
-- pair->key = strtol(key, NULL, 10);
-- accept = x; /* if x is 0 there was no key, so don't accept it */
--
-- if (pos + 1 > len) {
-- /* Malformed packet! (Truncated--garbage or something) */
-- accept = FALSE;
-- }
--
-- if (accept) {
-- delimiter = (const guchar *)g_strstr_len((const char *)&data[pos], len - pos, "\xc0\x80");
-- if (delimiter == NULL)
-- {
-- /* Malformed packet! (It doesn't end in 0xc0 0x80) */
-- g_free(pair);
-- pos = len;
-- continue;
-- }
-- x = delimiter - data;
-- pair->value = g_strndup((const gchar *)&data[pos], x - pos);
-- pos = x;
-- pkt->hash = g_slist_prepend(pkt->hash, pair);
--
-- if (purple_debug_is_verbose() || g_getenv("PURPLE_YAHOO_DEBUG")) {
-- char *esc;
-- esc = g_strescape(pair->value, NULL);
-- purple_debug_misc("yahoo", "Key: %d \tValue: %s\n", pair->key, esc);
-- g_free(esc);
-- }
-- } else {
-- g_free(pair);
-- }
-- pos += 2;
--
-- if (pos + 1 > len) break;
--
-- /* Skip over garbage we've noticed in the mail notifications */
-- if (data[0] == '9' && data[pos] == 0x01)
-- pos++;
-- }
--
-- /*
-- * Originally this function used g_slist_append(). I changed
-- * it to use g_slist_prepend() for improved performance.
-- * Ideally the Yahoo! PRPL code would be indifferent to the
-- * order of the key/value pairs, but I don't know if this is
-- * the case for all incoming messages. To be on the safe side
-- * we reverse the list.
-- */
-- pkt->hash = g_slist_reverse(pkt->hash);
--}
--
--void yahoo_packet_write(struct yahoo_packet *pkt, guchar *data)
--{
-- GSList *l;
-- int pos = 0;
--
-- /* This is only called from one place, and the list is
-- * always backwards */
--
-- l = pkt->hash = g_slist_reverse(pkt->hash);
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
-- gchar buf[100];
--
-- g_snprintf(buf, sizeof(buf), "%d", pair->key);
-- strcpy((char *)&data[pos], buf);
-- pos += strlen(buf);
-- data[pos++] = 0xc0;
-- data[pos++] = 0x80;
--
-- strcpy((char *)&data[pos], pair->value);
-- pos += strlen(pair->value);
-- data[pos++] = 0xc0;
-- data[pos++] = 0x80;
--
-- l = l->next;
-- }
--}
--
--void yahoo_packet_dump(guchar *data, int len)
--{
--#ifdef YAHOO_DEBUG
-- int i;
--
-- purple_debug_misc("yahoo", "");
--
-- for (i = 0; i + 1 < len; i += 2) {
-- if ((i % 16 == 0) && i) {
-- purple_debug_misc(NULL, "\n");
-- purple_debug_misc("yahoo", "");
-- }
--
-- purple_debug_misc(NULL, "%02x%02x ", data[i], data[i + 1]);
-- }
-- if (i < len)
-- purple_debug_misc(NULL, "%02x", data[i]);
--
-- purple_debug_misc(NULL, "\n");
-- purple_debug_misc("yahoo", "");
--
-- for (i = 0; i < len; i++) {
-- if ((i % 16 == 0) && i) {
-- purple_debug_misc(NULL, "\n");
-- purple_debug_misc("yahoo", "");
-- }
--
-- if (g_ascii_isprint(data[i]))
-- purple_debug_misc(NULL, "%c ", data[i]);
-- else
-- purple_debug_misc(NULL, ". ");
-- }
--
-- purple_debug_misc(NULL, "\n");
--#endif /* YAHOO_DEBUG */
--}
--
--static void
--yahoo_packet_send_can_write(gpointer data, gint source, PurpleInputCondition cond)
--{
-- YahooData *yd = data;
-- int ret, writelen;
--
-- writelen = purple_circ_buffer_get_max_read(yd->txbuf);
--
-- if (writelen == 0) {
-- purple_input_remove(yd->txhandler);
-- yd->txhandler = 0;
-- return;
-- }
--
-- ret = write(yd->fd, yd->txbuf->outptr, writelen);
--
-- if (ret < 0 && errno == EAGAIN)
-- return;
-- else if (ret < 0) {
-- /* TODO: what to do here - do we really have to disconnect? */
-- purple_connection_error_reason(yd->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-- _("Write Error"));
-- return;
-- }
--
-- purple_circ_buffer_mark_read(yd->txbuf, ret);
--}
--
--
--size_t yahoo_packet_build(struct yahoo_packet *pkt, int pad, gboolean wm,
-- gboolean jp, guchar **buf)
--{
-- size_t pktlen = yahoo_packet_length(pkt);
-- size_t len = YAHOO_PACKET_HDRLEN + pktlen;
-- guchar *data;
-- int pos = 0;
--
-- data = g_malloc0(len + 1);
--
-- memcpy(data + pos, "YMSG", 4); pos += 4;
--
-- if (wm)
-- pos += yahoo_put16(data + pos, YAHOO_WEBMESSENGER_PROTO_VER);
-- else if (jp)
-- pos += yahoo_put16(data + pos, YAHOO_PROTO_VER_JAPAN);
-- else
-- pos += yahoo_put16(data + pos, YAHOO_PROTO_VER);
-- pos += yahoo_put16(data + pos, 0x0000);
-- pos += yahoo_put16(data + pos, pktlen + pad);
-- pos += yahoo_put16(data + pos, pkt->service);
-- pos += yahoo_put32(data + pos, pkt->status);
-- pos += yahoo_put32(data + pos, pkt->id);
--
-- yahoo_packet_write(pkt, data + pos);
--
-- *buf = data;
--
-- return len;
--}
--
--int yahoo_packet_send(struct yahoo_packet *pkt, YahooData *yd)
--{
-- size_t len;
-- gssize ret;
-- guchar *data;
--
-- if (yd->fd < 0)
-- return -1;
--
-- len = yahoo_packet_build(pkt, 0, yd->wm, yd->jp, &data);
--
-- yahoo_packet_dump(data, len);
-- if (yd->txhandler == 0)
-- ret = write(yd->fd, data, len);
-- else {
-- ret = -1;
-- errno = EAGAIN;
-- }
--
-- if (ret < 0 && errno == EAGAIN)
-- ret = 0;
-- else if (ret <= 0) {
-- purple_debug_warning("yahoo", "Only wrote %" G_GSSIZE_FORMAT
-- " of %" G_GSIZE_FORMAT " bytes!\n", ret, len);
-- g_free(data);
-- return ret;
-- }
--
-- if (ret < len) {
-- if (yd->txhandler == 0)
-- yd->txhandler = purple_input_add(yd->fd, PURPLE_INPUT_WRITE,
-- yahoo_packet_send_can_write, yd);
-- purple_circ_buffer_append(yd->txbuf, data + ret, len - ret);
-- }
--
-- g_free(data);
--
-- return ret;
--}
--
--int yahoo_packet_send_and_free(struct yahoo_packet *pkt, YahooData *yd)
--{
-- int ret;
--
-- ret = yahoo_packet_send(pkt, yd);
-- yahoo_packet_free(pkt);
-- return ret;
--}
--
--void yahoo_packet_free(struct yahoo_packet *pkt)
--{
-- while (pkt->hash) {
-- struct yahoo_pair *pair = pkt->hash->data;
-- g_free(pair->value);
-- g_free(pair);
-- pkt->hash = g_slist_delete_link(pkt->hash, pkt->hash);
-- }
-- g_free(pkt);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_packet.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_packet.h
---- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_packet.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_packet.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,150 +0,0 @@
--/**
-- * @file yahoo_packet.h The Yahoo! protocol plugin
-- *
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _YAHOO_PACKET_H_
--#define _YAHOO_PACKET_H_
--
--enum yahoo_service { /* these are easier to see in hex */
-- YAHOO_SERVICE_LOGON = 1,
-- YAHOO_SERVICE_LOGOFF,
-- YAHOO_SERVICE_ISAWAY,
-- YAHOO_SERVICE_ISBACK,
-- YAHOO_SERVICE_IDLE, /* 5 (placemarker) */
-- YAHOO_SERVICE_MESSAGE,
-- YAHOO_SERVICE_IDACT,
-- YAHOO_SERVICE_IDDEACT,
-- YAHOO_SERVICE_MAILSTAT,
-- YAHOO_SERVICE_USERSTAT, /* 0xa */
-- YAHOO_SERVICE_NEWMAIL,
-- YAHOO_SERVICE_CHATINVITE,
-- YAHOO_SERVICE_CALENDAR,
-- YAHOO_SERVICE_NEWPERSONALMAIL,
-- YAHOO_SERVICE_NEWCONTACT,
-- YAHOO_SERVICE_ADDIDENT, /* 0x10 */
-- YAHOO_SERVICE_ADDIGNORE,
-- YAHOO_SERVICE_PING,
-- YAHOO_SERVICE_GOTGROUPRENAME,
-- YAHOO_SERVICE_SYSMESSAGE = 0x14,
-- YAHOO_SERVICE_SKINNAME = 0x15,
-- YAHOO_SERVICE_PASSTHROUGH2 = 0x16,
-- YAHOO_SERVICE_CONFINVITE = 0x18,
-- YAHOO_SERVICE_CONFLOGON,
-- YAHOO_SERVICE_CONFDECLINE,
-- YAHOO_SERVICE_CONFLOGOFF,
-- YAHOO_SERVICE_CONFADDINVITE,
-- YAHOO_SERVICE_CONFMSG,
-- YAHOO_SERVICE_CHATLOGON,
-- YAHOO_SERVICE_CHATLOGOFF,
-- YAHOO_SERVICE_CHATMSG = 0x20,
-- YAHOO_SERVICE_GAMELOGON = 0x28,
-- YAHOO_SERVICE_GAMELOGOFF,
-- YAHOO_SERVICE_GAMEMSG = 0x2a,
-- YAHOO_SERVICE_FILETRANSFER = 0x46,
-- YAHOO_SERVICE_VOICECHAT = 0x4A,
-- YAHOO_SERVICE_NOTIFY = 0x4B,
-- YAHOO_SERVICE_VERIFY,
-- YAHOO_SERVICE_P2PFILEXFER,
-- YAHOO_SERVICE_PEERTOPEER = 0x4F,
-- YAHOO_SERVICE_WEBCAM,
-- YAHOO_SERVICE_AUTHRESP = 0x54,
-- YAHOO_SERVICE_LIST = 0x55,
-- YAHOO_SERVICE_AUTH = 0x57,
-- YAHOO_SERVICE_AUTHBUDDY = 0x6d,
-- YAHOO_SERVICE_ADDBUDDY = 0x83,
-- YAHOO_SERVICE_REMBUDDY = 0x84,
-- YAHOO_SERVICE_IGNORECONTACT, /* > 1, 7, 13 < 1, 66, 13, 0*/
-- YAHOO_SERVICE_REJECTCONTACT,
-- YAHOO_SERVICE_GROUPRENAME = 0x89, /* > 1, 65(new), 66(0), 67(old) */
-- YAHOO_SERVICE_KEEPALIVE = 0x8A,
-- YAHOO_SERVICE_CHATONLINE = 0x96, /* > 109(id), 1, 6(abcde) < 0,1*/
-- YAHOO_SERVICE_CHATGOTO,
-- YAHOO_SERVICE_CHATJOIN, /* > 1 104-room 129-1600326591 62-2 */
-- YAHOO_SERVICE_CHATLEAVE,
-- YAHOO_SERVICE_CHATEXIT = 0x9b,
-- YAHOO_SERVICE_CHATADDINVITE = 0x9d,
-- YAHOO_SERVICE_CHATLOGOUT = 0xa0,
-- YAHOO_SERVICE_CHATPING,
-- YAHOO_SERVICE_COMMENT = 0xa8,
-- YAHOO_SERVICE_PRESENCE_PERM = 0xb9,
-- YAHOO_SERVICE_PRESENCE_SESSION = 0xba,
-- YAHOO_SERVICE_AVATAR = 0xbc,
-- YAHOO_SERVICE_PICTURE_CHECKSUM = 0xbd,
-- YAHOO_SERVICE_PICTURE = 0xbe,
-- YAHOO_SERVICE_PICTURE_UPDATE = 0xc1,
-- YAHOO_SERVICE_PICTURE_UPLOAD = 0xc2,
-- YAHOO_SERVICE_Y6_VISIBLE_TOGGLE = 0xc5,
-- YAHOO_SERVICE_Y6_STATUS_UPDATE = 0xc6,
-- YAHOO_SERVICE_AVATAR_UPDATE = 0xc7,
-- YAHOO_SERVICE_VERIFY_ID_EXISTS = 0xc8,
-- YAHOO_SERVICE_AUDIBLE = 0xd0,
-- YAHOO_SERVICE_CONTACT_DETAILS = 0xd3,
-- /* YAHOO_SERVICE_CHAT_SESSION = 0xd4,?? Reports start of chat session, gets an id from server */
-- YAHOO_SERVICE_AUTH_REQ_15 = 0xd6,
-- YAHOO_SERVICE_FILETRANS_15 = 0xdc,
-- YAHOO_SERVICE_FILETRANS_INFO_15 = 0xdd,
-- YAHOO_SERVICE_FILETRANS_ACC_15 = 0xde,
-- /* photo sharing services ?? - 0xd2, 0xd7, 0xd8, 0xda */
-- YAHOO_SERVICE_CHGRP_15 = 0xe7,
-- YAHOO_SERVICE_STATUS_15 = 0xf0,
-- YAHOO_SERVICE_LIST_15 = 0xf1,
-- YAHOO_SERVICE_MESSAGE_ACK = 0xfb,
-- YAHOO_SERVICE_WEBLOGIN = 0x0226,
-- YAHOO_SERVICE_SMS_MSG = 0x02ea
-- /* YAHOO_SERVICE_DISCONNECT = 0x07d1 Server forces us to disconnect. Is sent with TCP FIN flag set */
--};
--
--struct yahoo_pair {
-- int key;
-- char *value;
--};
--
--struct yahoo_packet {
-- guint16 service;
-- guint32 status;
-- guint32 id;
-- GSList *hash;
--};
--
--#define YAHOO_WEBMESSENGER_PROTO_VER 0x0065
--#define YAHOO_PROTO_VER 0x0010
--#define YAHOO_PROTO_VER_JAPAN 0x0010
--
--#define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4)
--
--struct yahoo_packet *yahoo_packet_new(enum yahoo_service service,
-- enum yahoo_status status, int id);
--void yahoo_packet_hash(struct yahoo_packet *pkt, const char *fmt, ...);
--void yahoo_packet_hash_str(struct yahoo_packet *pkt, int key, const char *value);
--void yahoo_packet_hash_int(struct yahoo_packet *pkt, int key, int value);
--int yahoo_packet_send(struct yahoo_packet *pkt, YahooData *yd);
--int yahoo_packet_send_and_free(struct yahoo_packet *pkt, YahooData *yd);
--size_t yahoo_packet_build(struct yahoo_packet *pkt, int pad, gboolean wm, gboolean jp,
--guchar **buf);
--void yahoo_packet_read(struct yahoo_packet *pkt, const guchar *data, int len);
--void yahoo_packet_write(struct yahoo_packet *pkt, guchar *data);
--void yahoo_packet_dump(guchar *data, int len);
--size_t yahoo_packet_length(struct yahoo_packet *pkt);
--void yahoo_packet_free(struct yahoo_packet *pkt);
--
--#endif /* _YAHOO_PACKET_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_picture.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_picture.c
---- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_picture.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_picture.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,587 +0,0 @@
--/*
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#include "internal.h"
--
--#include "account.h"
--#include "accountopt.h"
--#include "blist.h"
--#include "debug.h"
--#include "privacy.h"
--#include "prpl.h"
--#include "proxy.h"
--#include "util.h"
--
--#include "libymsg.h"
--#include "yahoo_packet.h"
--#include "yahoo_friend.h"
--#include "yahoo_picture.h"
--
--
--struct yahoo_fetch_picture_data {
-- PurpleConnection *gc;
-- char *who;
-- int checksum;
--};
--
--static void
--yahoo_fetch_picture_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
-- const gchar *pic_data, size_t len, const gchar *error_message)
--{
-- struct yahoo_fetch_picture_data *d;
-- YahooData *yd;
--
-- d = user_data;
-- yd = d->gc->proto_data;
-- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
--
-- if (error_message != NULL) {
-- purple_debug_error("yahoo", "Fetching buddy icon failed: %s\n", error_message);
-- } else if (len == 0) {
-- purple_debug_error("yahoo", "Fetched an icon with length 0. Strange.\n");
-- } else {
-- char *checksum = g_strdup_printf("%i", d->checksum);
-- purple_buddy_icons_set_for_user(purple_connection_get_account(d->gc), d->who, g_memdup(pic_data, len), len, checksum);
-- g_free(checksum);
-- }
--
-- g_free(d->who);
-- g_free(d);
--}
--
--void yahoo_process_picture(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- YahooData *yd;
-- GSList *l = pkt->hash;
-- char *who = NULL, *us = NULL;
-- gboolean got_icon_info = FALSE, send_icon_info = FALSE;
-- char *url = NULL;
-- int checksum = 0;
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 1:
-- case 4:
-- who = pair->value;
-- break;
-- case 5:
-- us = pair->value;
-- break;
-- case 13: {
-- int tmp;
-- tmp = strtol(pair->value, NULL, 10);
-- if (tmp == 1) {
-- send_icon_info = TRUE;
-- } else if (tmp == 2) {
-- got_icon_info = TRUE;
-- }
-- break;
-- }
-- case 20:
-- url = pair->value;
-- break;
-- case 192:
-- checksum = strtol(pair->value, NULL, 10);
-- break;
-- }
--
-- l = l->next;
-- }
--
-- if (!who)
-- return;
--
-- if (!purple_privacy_check(purple_connection_get_account(gc), who)) {
-- purple_debug_info("yahoo", "Picture packet from %s dropped.\n", who);
-- return;
-- }
--
-- /* Yahoo IM 6 spits out 0.png as the URL if the buddy icon is not set */
-- if (who && got_icon_info && url && !g_ascii_strncasecmp(url, "http://", 7)) {
-- /* TODO: make this work p2p, try p2p before the url */
-- PurpleUtilFetchUrlData *url_data;
-- struct yahoo_fetch_picture_data *data;
-- /* use whole URL if using HTTP Proxy */
-- gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
--
-- data = g_new0(struct yahoo_fetch_picture_data, 1);
-- data->gc = gc;
-- data->who = g_strdup(who);
-- data->checksum = checksum;
-- /* TODO: Does this need to be MSIE 5.0? */
-- url_data = purple_util_fetch_url(url, use_whole_url,
-- "Mozilla/4.0 (compatible; MSIE 5.5)", FALSE,
-- yahoo_fetch_picture_cb, data);
-- if (url_data != NULL) {
-- yd = gc->proto_data;
-- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-- }
-- } else if (who && send_icon_info) {
-- yahoo_send_picture_info(gc, who);
-- }
--}
--
--void yahoo_process_picture_checksum(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- GSList *l = pkt->hash;
-- char *who = NULL;
-- int checksum = 0;
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 4:
-- who = pair->value;
-- break;
-- case 5:
-- /* us */
-- break;
-- case 192:
-- checksum = strtol(pair->value, NULL, 10);
-- break;
-- }
-- l = l->next;
-- }
--
-- if (who) {
-- PurpleBuddy *b = purple_find_buddy(gc->account, who);
-- const char *locksum = NULL;
--
-- /* FIXME: Cleanup this strtol() stuff if possible. */
-- if (b) {
-- locksum = purple_buddy_icons_get_checksum_for_user(b);
-- if (!locksum || (checksum != strtol(locksum, NULL, 10)))
-- yahoo_send_picture_request(gc, who);
-- }
-- }
--}
--
--void yahoo_process_picture_upload(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- PurpleAccount *account = purple_connection_get_account(gc);
-- YahooData *yd = gc->proto_data;
-- GSList *l = pkt->hash;
-- char *url = NULL;
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 5:
-- /* us */
-- break;
-- case 27:
-- /* filename on our computer. */
-- break;
-- case 20: /* url at yahoo */
-- url = pair->value;
-- case 38: /* timestamp */
-- break;
-- }
-- l = l->next;
-- }
--
-- if (url) {
-- g_free(yd->picture_url);
-- yd->picture_url = g_strdup(url);
-- purple_account_set_string(account, YAHOO_PICURL_SETTING, url);
-- purple_account_set_int(account, YAHOO_PICCKSUM_SETTING, yd->picture_checksum);
-- yahoo_send_picture_checksum(gc);
-- yahoo_send_picture_update(gc, 2);
-- }
--}
--
--void yahoo_process_avatar_update(PurpleConnection *gc, struct yahoo_packet *pkt)
--{
-- GSList *l = pkt->hash;
-- char *who = NULL;
-- int avatar = 0;
--
-- while (l) {
-- struct yahoo_pair *pair = l->data;
--
-- switch (pair->key) {
-- case 4:
-- who = pair->value;
-- break;
-- case 5:
-- /* us */
-- break;
-- case 206: /* Older versions. Still needed? */
-- case 213: /* Newer versions */
-- /*
-- * 0 - No icon or avatar
-- * 1 - Using an avatar
-- * 2 - Using an icon
-- */
-- avatar = strtol(pair->value, NULL, 10);
-- break;
-- }
-- l = l->next;
-- }
--
-- if (who) {
-- if (avatar == 2)
-- yahoo_send_picture_request(gc, who);
-- else if ((avatar == 0) || (avatar == 1)) {
-- YahooFriend *f;
-- purple_buddy_icons_set_for_user(gc->account, who, NULL, 0, NULL);
-- if ((f = yahoo_friend_find(gc, who)))
-- yahoo_friend_set_buddy_icon_need_request(f, TRUE);
-- purple_debug_misc("yahoo", "Setting user %s's icon to NULL.\n", who);
-- }
-- }
--}
--
--void yahoo_send_picture_info(PurpleConnection *gc, const char *who)
--{
-- YahooData *yd = gc->proto_data;
-- struct yahoo_packet *pkt;
--
-- if (!yd->picture_url) {
-- purple_debug_warning("yahoo", "Attempted to send picture info without a picture\n");
-- return;
-- }
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash(pkt, "ssssi", 1, purple_connection_get_display_name(gc),
-- 5, who,
-- 13, "2", 20, yd->picture_url, 192, yd->picture_checksum);
-- yahoo_packet_send_and_free(pkt, yd);
--}
--
--void yahoo_send_picture_request(PurpleConnection *gc, const char *who)
--{
-- YahooData *yd = gc->proto_data;
-- struct yahoo_packet *pkt;
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash_str(pkt, 1, purple_connection_get_display_name(gc)); /* me */
-- yahoo_packet_hash_str(pkt, 5, who); /* the other guy */
-- yahoo_packet_hash_str(pkt, 13, "1"); /* 1 = request, 2 = reply */
-- yahoo_packet_send_and_free(pkt, yd);
--}
--
--void yahoo_send_picture_checksum(PurpleConnection *gc)
--{
-- YahooData *yd = gc->proto_data;
-- struct yahoo_packet *pkt;
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash(pkt, "ssi", 1, purple_connection_get_display_name(gc),
-- 212, "1", 192, yd->picture_checksum);
-- yahoo_packet_send_and_free(pkt, yd);
--}
--
--void yahoo_send_picture_update_to_user(PurpleConnection *gc, const char *who, int type)
--{
-- YahooData *yd = gc->proto_data;
-- struct yahoo_packet *pkt;
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_AVATAR_UPDATE, YAHOO_STATUS_AVAILABLE, yd->session_id);
-- yahoo_packet_hash(pkt, "si", 3, who, 213, type);
-- yahoo_packet_send_and_free(pkt, yd);
--}
--
--struct yspufe {
-- PurpleConnection *gc;
-- int type;
--};
--
--static void yahoo_send_picture_update_foreach(gpointer key, gpointer value, gpointer data)
--{
-- const char *who = key;
-- YahooFriend *f = value;
-- struct yspufe *d = data;
--
-- if (f->status != YAHOO_STATUS_OFFLINE)
-- yahoo_send_picture_update_to_user(d->gc, who, d->type);
--}
--
--void yahoo_send_picture_update(PurpleConnection *gc, int type)
--{
-- YahooData *yd = gc->proto_data;
-- struct yspufe data;
--
-- data.gc = gc;
-- data.type = type;
--
-- g_hash_table_foreach(yd->friends, yahoo_send_picture_update_foreach, &data);
--}
--
--void yahoo_buddy_icon_upload_data_free(struct yahoo_buddy_icon_upload_data *d)
--{
-- purple_debug_misc("yahoo", "In yahoo_buddy_icon_upload_data_free()\n");
--
-- if (d->str)
-- g_string_free(d->str, TRUE);
-- g_free(d->filename);
-- if (d->watcher)
-- purple_input_remove(d->watcher);
-- if (d->fd != -1)
-- close(d->fd);
-- g_free(d);
--}
--
--/* we couldn't care less about the server's response, but yahoo gets grumpy if we close before it sends it */
--static void yahoo_buddy_icon_upload_reading(gpointer data, gint source, PurpleInputCondition condition)
--{
-- struct yahoo_buddy_icon_upload_data *d = data;
-- PurpleConnection *gc = d->gc;
-- char buf[1024];
-- int ret;
--
-- if (!PURPLE_CONNECTION_IS_VALID(gc)) {
-- yahoo_buddy_icon_upload_data_free(d);
-- return;
-- }
--
-- ret = read(d->fd, buf, sizeof(buf));
--
-- if (ret < 0 && errno == EAGAIN)
-- return;
-- else if (ret <= 0) {
-- /* There are other problems if d->str->len overflows, so shut up the
-- * warning on 64-bit. */
-- purple_debug_info("yahoo", "Buddy icon upload response (%" G_GSIZE_FORMAT ") bytes (> ~400 indicates failure):\n%.*s\n",
-- d->str->len, (guint)d->str->len, d->str->str);
--
-- yahoo_buddy_icon_upload_data_free(d);
-- return;
-- }
--
-- g_string_append_len(d->str, buf, ret);
--}
--
--static void yahoo_buddy_icon_upload_pending(gpointer data, gint source, PurpleInputCondition condition)
--{
-- struct yahoo_buddy_icon_upload_data *d = data;
-- PurpleConnection *gc = d->gc;
-- gssize wrote;
--
-- if (!PURPLE_CONNECTION_IS_VALID(gc)) {
-- yahoo_buddy_icon_upload_data_free(d);
-- return;
-- }
--
-- wrote = write(d->fd, d->str->str + d->pos, d->str->len - d->pos);
-- if (wrote < 0 && errno == EAGAIN)
-- return;
-- if (wrote <= 0) {
-- purple_debug_info("yahoo", "Error uploading buddy icon.\n");
-- yahoo_buddy_icon_upload_data_free(d);
-- return;
-- }
-- d->pos += wrote;
-- if (d->pos >= d->str->len) {
-- purple_debug_misc("yahoo", "Finished uploading buddy icon.\n");
-- purple_input_remove(d->watcher);
-- /* Clean out the sent buffer and reuse it to read the result */
-- g_string_free(d->str, TRUE);
-- d->str = g_string_new("");
-- d->watcher = purple_input_add(d->fd, PURPLE_INPUT_READ, yahoo_buddy_icon_upload_reading, d);
-- }
--}
--
--static void yahoo_buddy_icon_upload_connected(gpointer data, gint source, const gchar *error_message)
--{
-- struct yahoo_buddy_icon_upload_data *d = data;
-- struct yahoo_packet *pkt;
-- gchar *tmp, *header;
-- guchar *pkt_buf;
-- const char *host;
-- int port;
-- gsize pkt_buf_len;
-- PurpleConnection *gc = d->gc;
-- PurpleAccount *account;
-- YahooData *yd;
-- /* use whole URL if using HTTP Proxy */
-- gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
--
-- account = purple_connection_get_account(gc);
-- yd = gc->proto_data;
--
-- /* Buddy icon connect is now complete; clear the PurpleProxyConnectData */
-- yd->buddy_icon_connect_data = NULL;
--
-- if (source < 0) {
-- purple_debug_error("yahoo", "Buddy icon upload failed: %s\n", error_message);
-- yahoo_buddy_icon_upload_data_free(d);
-- return;
-- }
--
-- pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPLOAD, YAHOO_STATUS_AVAILABLE, yd->session_id);
--
-- tmp = g_strdup_printf("%" G_GSIZE_FORMAT, d->str->len);
-- /* 1 = me, 38 = expire time(?), 0 = me, 28 = size, 27 = filename, 14 = NULL, 29 = data */
-- yahoo_packet_hash_str(pkt, 1, purple_connection_get_display_name(gc));
-- yahoo_packet_hash_str(pkt, 38, "604800"); /* time til expire */
-- purple_account_set_int(account, YAHOO_PICEXPIRE_SETTING, time(NULL) + 604800);
-- yahoo_packet_hash_str(pkt, 0, purple_connection_get_display_name(gc));
-- yahoo_packet_hash_str(pkt, 28, tmp);
-- g_free(tmp);
-- yahoo_packet_hash_str(pkt, 27, d->filename);
-- yahoo_packet_hash_str(pkt, 14, "");
-- /* 4 padding for the 29 key name */
-- pkt_buf_len = yahoo_packet_build(pkt, 4, FALSE, yd->jp, &pkt_buf);
-- yahoo_packet_free(pkt);
--
-- /* header + packet + "29" + 0xc0 + 0x80) + pictureblob */
--
-- host = purple_account_get_string(account, "xfer_host", yd->jp? YAHOOJP_XFER_HOST : YAHOO_XFER_HOST);
-- port = purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT);
-- tmp = g_strdup_printf("%s:%d", host, port);
-- header = g_strdup_printf("POST %s%s/notifyft HTTP/1.1\r\n"
-- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
-- "Cookie: T=%s; Y=%s\r\n"
-- "Host: %s\r\n"
-- "Content-Length: %" G_GSIZE_FORMAT "\r\n"
-- "Cache-Control: no-cache\r\n\r\n",
-- use_whole_url ? "http://" : "", use_whole_url ? tmp : "",
-- yd->cookie_t, yd->cookie_y,
-- tmp,
-- pkt_buf_len + 4 + d->str->len);
-- g_free(tmp);
--
-- /* There's no magic here, we just need to prepend in reverse order */
-- g_string_prepend(d->str, "29\xc0\x80");
--
-- g_string_prepend_len(d->str, (char *)pkt_buf, pkt_buf_len);
-- g_free(pkt_buf);
--
-- g_string_prepend(d->str, header);
-- g_free(header);
--
-- /* There are other problems if we're uploading over 4GB of data */
-- purple_debug_info("yahoo", "Buddy icon upload data:\n%.*s\n", (guint)d->str->len, d->str->str);
--
-- d->fd = source;
-- d->watcher = purple_input_add(d->fd, PURPLE_INPUT_WRITE, yahoo_buddy_icon_upload_pending, d);
--
-- yahoo_buddy_icon_upload_pending(d, d->fd, PURPLE_INPUT_WRITE);
--}
--
--void yahoo_buddy_icon_upload(PurpleConnection *gc, struct yahoo_buddy_icon_upload_data *d)
--{
-- PurpleAccount *account = purple_connection_get_account(gc);
-- YahooData *yd = gc->proto_data;
--
-- if (yd->buddy_icon_connect_data != NULL) {
-- /* Cancel any in-progress buddy icon upload */
-- purple_proxy_connect_cancel(yd->buddy_icon_connect_data);
-- yd->buddy_icon_connect_data = NULL;
-- }
--
-- yd->buddy_icon_connect_data = purple_proxy_connect(NULL, account,
-- purple_account_get_string(account, "xfer_host",
-- yd->jp? YAHOOJP_XFER_HOST : YAHOO_XFER_HOST),
-- purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT),
-- yahoo_buddy_icon_upload_connected, d);
--
-- if (yd->buddy_icon_connect_data == NULL)
-- {
-- purple_debug_error("yahoo", "Uploading our buddy icon failed to connect.\n");
-- yahoo_buddy_icon_upload_data_free(d);
-- }
--}
--
--static int yahoo_buddy_icon_calculate_checksum(const guchar *data, gsize len)
--{
-- /* This code is borrowed from Kopete, which seems to be managing to calculate
-- checksums in such a manner that Yahoo!'s servers are happy */
--
-- const guchar *p = data;
-- int checksum = 0, g, i = len;
--
-- while(i--) {
-- checksum = (checksum << 4) + *p++;
--
-- if((g = (checksum & 0xf0000000)) != 0)
-- checksum ^= g >> 23;
--
-- checksum &= ~g;
-- }
--
-- purple_debug_misc("yahoo", "Calculated buddy icon checksum: %d\n", checksum);
--
-- return checksum;
--}
--
--void yahoo_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img)
--{
-- YahooData *yd = gc->proto_data;
-- PurpleAccount *account = gc->account;
--
-- if (img == NULL) {
-- g_free(yd->picture_url);
-- yd->picture_url = NULL;
--
-- /* TODO: don't we have to clear it on the server too?! */
--
-- purple_account_set_string(account, YAHOO_PICURL_SETTING, NULL);
-- purple_account_set_int(account, YAHOO_PICCKSUM_SETTING, 0);
-- purple_account_set_int(account, YAHOO_PICEXPIRE_SETTING, 0);
-- if (yd->logged_in)
-- /* Tell everyone we ain't got one no more */
-- yahoo_send_picture_update(gc, 0);
--
-- } else {
-- gconstpointer data = purple_imgstore_get_data(img);
-- size_t len = purple_imgstore_get_size(img);
-- GString *s = g_string_new_len(data, len);
-- struct yahoo_buddy_icon_upload_data *d;
-- int oldcksum = purple_account_get_int(account, YAHOO_PICCKSUM_SETTING, 0);
-- int expire = purple_account_get_int(account, YAHOO_PICEXPIRE_SETTING, 0);
-- const char *oldurl = purple_account_get_string(account, YAHOO_PICURL_SETTING, NULL);
--
-- yd->picture_checksum = yahoo_buddy_icon_calculate_checksum(data, len);
--
-- if ((yd->picture_checksum == oldcksum) &&
-- (expire > (time(NULL) + 60*60*24)) && oldurl)
-- {
-- purple_debug_misc("yahoo", "buddy icon is up to date. Not reuploading.\n");
-- g_string_free(s, TRUE);
-- g_free(yd->picture_url);
-- yd->picture_url = g_strdup(oldurl);
-- return;
-- }
--
-- /* We use this solely for sending a filename to the server */
-- d = g_new0(struct yahoo_buddy_icon_upload_data, 1);
-- d->gc = gc;
-- d->str = s;
-- d->fd = -1;
-- d->filename = g_strdup(purple_imgstore_get_filename(img));
--
-- if (!yd->logged_in) {
-- yd->picture_upload_todo = d;
-- return;
-- }
--
-- yahoo_buddy_icon_upload(gc, d);
--
-- }
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_picture.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_picture.h
---- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_picture.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_picture.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,43 +0,0 @@
--/*
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#ifndef _YAHOO_PICTURE_H_
--#define _YAHOO_PICTURE_H_
--
--void yahoo_send_picture_request(PurpleConnection *gc, const char *who);
--void yahoo_send_picture_info(PurpleConnection *gc, const char *who);
--void yahoo_send_picture_checksum(PurpleConnection *gc);
--void yahoo_send_picture_update(PurpleConnection *gc, int type);
--void yahoo_send_picture_update_to_user(PurpleConnection *gc, const char *who, int type);
--
--void yahoo_process_picture(PurpleConnection *gc, struct yahoo_packet *pkt);
--void yahoo_process_picture_checksum(PurpleConnection *gc, struct yahoo_packet *pkt);
--void yahoo_process_picture_upload(PurpleConnection *gc, struct yahoo_packet *pkt);
--
--void yahoo_process_avatar_update(PurpleConnection *gc, struct yahoo_packet *pkt);
--
--void yahoo_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img);
--void yahoo_buddy_icon_upload(PurpleConnection *gc, struct yahoo_buddy_icon_upload_data *d);
--void yahoo_buddy_icon_upload_data_free(struct yahoo_buddy_icon_upload_data *d);
--
--#endif /* _YAHOO_PICTURE_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_profile.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_profile.c
---- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_profile.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_profile.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1282 +0,0 @@
--/*
-- * purple
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#define PHOTO_SUPPORT 1
--
--#include "internal.h"
--#include "debug.h"
--#include "notify.h"
--#include "util.h"
--#if PHOTO_SUPPORT
--#include "imgstore.h"
--#endif /* PHOTO_SUPPORT */
--
--#include "libymsg.h"
--#include "yahoo_friend.h"
--
--typedef struct {
-- PurpleConnection *gc;
-- char *name;
--} YahooGetInfoData;
--
--typedef enum profile_lang_id {
-- XX, DA, DE, EL,
-- EN, EN_GB,
-- ES_AR, ES_ES, ES_MX, ES_US,
-- FR_CA, FR_FR,
-- IT, JA, KO, NO, PT, SV,
-- ZH_CN, ZH_HK, ZH_TW, ZH_US, PT_BR
--} profile_lang_id_t;
--
--typedef struct profile_lang_node {
-- profile_lang_id_t lang;
-- char *last_updated_string;
-- char *det;
--} profile_lang_node_t;
--
--typedef struct profile_strings_node {
-- profile_lang_id_t lang;
-- char *lang_string; /* Only to make debugging output saner */
-- char *charset;
-- char *yahoo_id_string;
-- char *private_string;
-- char *no_answer_string;
-- char *my_email_string;
-- char *realname_string;
-- char *location_string;
-- char *age_string;
-- char *maritalstatus_string;
-- char *gender_string;
-- char *occupation_string;
-- char *hobbies_string;
-- char *latest_news_string;
-- char *favorite_quote_string;
-- char *links_string;
-- char *no_home_page_specified_string;
-- char *home_page_string;
-- char *no_cool_link_specified_string;
-- char *cool_link_1_string;
-- char *cool_link_2_string;
-- char *cool_link_3_string;
-- char *dummy;
--} profile_strings_node_t;
--
--typedef enum profile_state {
-- PROFILE_STATE_DEFAULT,
-- PROFILE_STATE_NOT_FOUND,
-- PROFILE_STATE_UNKNOWN_LANGUAGE
--} profile_state_t;
--
--typedef struct {
-- YahooGetInfoData *info_data;
-- PurpleNotifyUserInfo *user_info;
-- char *url_buffer;
-- char *photo_url_text;
-- char *profile_url_text;
-- const profile_strings_node_t *strings;
-- const char *last_updated_string;
-- const char *title;
-- profile_state_t profile_state;
--} YahooGetInfoStepTwoData;
--
--/* Strings to determine the profile "language" (more accurately "locale").
-- * Strings in this list must be in the original charset in the profile.
-- * The "Last Updated" string is used, but sometimes is not sufficient to
-- * distinguish 2 locales with this (e.g., ES_ES from ES_US, or FR_CA from
-- * FR_FR, or EL from EN_GB), in which case a second string is added and
-- * such special cases must be placed before the more general case.
-- */
--static const profile_lang_node_t profile_langs[] = {
-- { DA, "Opdateret sidste gang&nbsp;", NULL },
-- { DE, "Letzter Update&nbsp;", NULL },
-- { EL, "Last Updated:", "http://gr.profiles.yahoo.com" },
-- { EN_GB, "Last Update&nbsp;", "Favourite Quote" },
-- { EN, "Last Update:", NULL },
-- { EN, "Last Update&nbsp;", NULL },
-- { ES_AR, "\332ltima actualizaci\363n&nbsp;", NULL },
-- { ES_ES, "Actualizada el&nbsp;", "http://es.profiles.yahoo.com" },
-- { ES_MX, "Actualizada el &nbsp;", "http://mx.profiles.yahoo.com" },
-- { ES_US, "Actualizada el &nbsp;", NULL },
-- { FR_CA, "Derni\xe8re mise \xe0 jour", "http://cf.profiles.yahoo.com" },
-- { FR_FR, "Derni\xe8re mise \xe0 jour", NULL },
-- { IT, "Ultimo aggiornamento:", NULL },
-- { JA, "\xba\xc7\xbd\xaa\xb9\xb9\xbf\xb7\xc6\xfc\xa1\xa7", NULL },
-- { KO, "\xb0\xbb\xbd\xc5\x20\xb3\xaf\xc2\xa5&nbsp;", NULL },
-- { NO, "Sist oppdatert&nbsp;", NULL },
-- { PT, "\332ltima atualiza\347\343o&nbsp;", NULL },
-- { PT_BR, "\332ltima atualiza\347\343o:", NULL },
-- { SV, "Senast uppdaterad&nbsp;", NULL },
-- { ZH_CN, "\xd7\xee\xba\xf3\xd0\xde\xb8\xc4\xc8\xd5\xc6\xda", NULL },
-- { ZH_HK, "\xb3\xcc\xaa\xf1\xa7\xf3\xb7\x73\xae\xc9\xb6\xa1", NULL },
-- { ZH_US, "\xb3\xcc\xab\xe1\xad\xd7\xa7\xef\xa4\xe9\xb4\xc1", "http://chinese.profiles.yahoo.com" },
-- { ZH_TW, "\xb3\xcc\xab\xe1\xad\xd7\xa7\xef\xa4\xe9\xb4\xc1", NULL },
-- { XX, NULL, NULL }
--};
--
--/* Strings in this list must be in UTF-8; &nbsp;'s should be specified as spaces. */
--static const profile_strings_node_t profile_strings[] = {
-- { DA, "da", "ISO-8859-1",
-- "Yahoo! ID:",
-- "Privat",
-- "Intet svar",
-- "Min Email",
-- "Rigtige navn:",
-- "Opholdssted:",
-- "Alder:",
-- "Ægteskabelig status:",
-- "Køn:",
-- "Erhverv:",
-- "Hobbyer:",
-- "Sidste nyt:",
-- "Favoritcitat",
-- "Links",
-- "Ingen hjemmeside specificeret",
-- "Forside:",
-- "Intet cool link specificeret",
-- "Cool link 1:",
-- "Cool link 2:",
-- "Cool link 3:",
-- NULL
-- },
-- { DE, "de", "ISO-8859-1",
-- "Yahoo!-ID:",
-- "Privat",
-- "Keine Antwort",
-- "Meine E-Mail",
-- "Realer Name:",
-- "Ort:",
-- "Alter:",
-- "Familienstand:",
-- "Geschlecht:",
-- "Beruf:",
-- "Hobbys:",
-- "Neuste Nachrichten:",
-- "Mein Lieblingsspruch",
-- "Links",
-- "Keine Homepage angegeben",
-- "Homepage:",
-- "Keinen coolen Link angegeben",
-- "Cooler Link 1:",
-- "Cooler Link 2:",
-- "Cooler Link 3:",
-- NULL
-- },
-- { EL, "el", "ISO-8859-7", /* EL is identical to EN, except no_answer_string */
-- "Yahoo! ID:",
-- "Private",
-- "Καμία απάντηση",
-- "My Email",
-- "Real Name:",
-- "Location:",
-- "Age:",
-- "Marital Status:",
-- "Gender:",
-- "Occupation:",
-- "Hobbies:",
-- "Latest News",
-- "Favorite Quote",
-- "Links",
-- "No home page specified",
-- "Home Page:",
-- "No cool link specified",
-- "Cool Link 1:",
-- "Cool Link 2:",
-- "Cool Link 3:",
-- NULL
-- },
-- { EN, "en", "ISO-8859-1",
-- "Yahoo! ID:",
-- "Private",
-- "No Answer",
-- "My Email:",
-- "Real Name:",
-- "Location:",
-- "Age:",
-- "Marital Status:",
-- "Sex:",
-- "Occupation:",
-- "Hobbies",
-- "Latest News",
-- "Favorite Quote",
-- "Links",
-- "No home page specified",
-- "Home Page:",
-- "No cool link specified",
-- "Cool Link 1",
-- "Cool Link 2",
-- "Cool Link 3",
-- NULL
-- },
-- { EN_GB, "en_GB", "ISO-8859-1", /* Same as EN except spelling of "Favourite" */
-- "Yahoo! ID:",
-- "Private",
-- "No Answer",
-- "My Email:",
-- "Real Name:",
-- "Location:",
-- "Age:",
-- "Marital Status:",
-- "Sex:",
-- "Occupation:",
-- "Hobbies",
-- "Latest News",
-- "Favourite Quote",
-- "Links",
-- "No home page specified",
-- "Home Page:",
-- "No cool link specified",
-- "Cool Link 1",
-- "Cool Link 2",
-- "Cool Link 3",
-- NULL
-- },
-- { ES_AR, "es_AR", "ISO-8859-1",
-- "Usuario de Yahoo!:",
-- "Privado",
-- "No introdujiste una respuesta",
-- "Mi dirección de correo electrónico",
-- "Nombre real:",
-- "Ubicación:",
-- "Edad:",
-- "Estado civil:",
-- "Sexo:",
-- "Ocupación:",
-- "Pasatiempos:",
-- "Últimas noticias:",
-- "Tu cita favorita",
-- "Enlaces",
-- "Ninguna página de inicio especificada",
-- "Página de inicio:",
-- "Ningún enlace preferido",
-- "Enlace genial 1:",
-- "Enlace genial 2:",
-- "Enlace genial 3:",
-- NULL
-- },
-- { ES_ES, "es_ES", "ISO-8859-1",
-- "ID de Yahoo!:",
-- "Privado",
-- "Sin respuesta",
-- "Mi correo-e",
-- "Nombre verdadero:",
-- "Lugar:",
-- "Edad:",
-- "Estado civil:",
-- "Sexo:",
-- "Ocupación:",
-- "Aficiones:",
-- "Ultimas Noticias:",
-- "Tu cita Favorita",
-- "Enlace",
-- "Ninguna página personal especificada",
-- "Página de Inicio:",
-- "Ningún enlace preferido",
-- "Enlaces Preferidos 1:",
-- "Enlaces Preferidos 2:",
-- "Enlaces Preferidos 3:",
-- NULL
-- },
-- { ES_MX, "es_MX", "ISO-8859-1",
-- "ID de Yahoo!:",
-- "Privado",
-- "Sin responder",
-- "Mi Dirección de correo-e",
-- "Nombre real:",
-- "Ubicación:",
-- "Edad:",
-- "Estado civil:",
-- "Sexo:",
-- "Ocupación:",
-- "Pasatiempos:",
-- "Ultimas Noticias:",
-- "Su cita favorita",
-- "Enlaces",
-- "Ninguna Página predefinida",
-- "Página web:",
-- "Ningún Enlace preferido",
-- "Enlaces Preferidos 1:",
-- "Enlaces Preferidos 2:",
-- "Enlaces Preferidos 3:",
-- NULL
-- },
-- { ES_US, "es_US", "ISO-8859-1",
-- "ID de Yahoo!:",
-- "Privado",
-- "No introdujo una respuesta",
-- "Mi Dirección de correo-e",
-- "Nombre real:",
-- "Localidad:",
-- "Edad:",
-- "Estado civil:",
-- "Sexo:",
-- "Ocupación:",
-- "Pasatiempos:",
-- "Ultimas Noticias:",
-- "Su cita Favorita",
-- "Enlaces",
-- "Ninguna Página de inicio predefinida",
-- "Página de inicio:",
-- "Ningún Enlace preferido",
-- "Enlaces Preferidos 1:",
-- "Enlaces Preferidos 2:",
-- "Enlaces Preferidos 3:",
-- NULL
-- },
-- { FR_CA, "fr_CA", "ISO-8859-1",
-- "Compte Yahoo!:",
-- "Privé",
-- "Sans réponse",
-- "Mon courriel",
-- "Nom réel:",
-- "Lieu:",
-- "Âge:",
-- "État civil:",
-- "Sexe:",
-- "Profession:",
-- "Passe-temps:",
-- "Actualités:",
-- "Citation préférée",
-- "Liens",
-- "Pas de mention d'une page personnelle",
-- "Page personnelle:",
-- "Pas de mention d'un lien favori",
-- "Lien préféré 1:",
-- "Lien préféré 2:",
-- "Lien préféré 3:",
-- NULL
-- },
-- { FR_FR, "fr_FR", "ISO-8859-1",
-- "Compte Yahoo!:",
-- "Privé",
-- "Sans réponse",
-- "Mon E-mail",
-- "Nom réel:",
-- "Lieu:",
-- "Âge:",
-- "Situation de famille:",
-- "Sexe:",
-- "Profession:",
-- "Centres d'intérêts:",
-- "Actualités:",
-- "Citation préférée",
-- "Liens",
-- "Pas de mention d'une page perso",
-- "Page perso:",
-- "Pas de mention d'un lien favori",
-- "Lien préféré 1:",
-- "Lien préféré 2:",
-- "Lien préféré 3:",
-- NULL
-- },
-- { IT, "it", "ISO-8859-1",
-- "Yahoo! ID:",
-- "Non pubblica",
-- "Nessuna risposta",
-- "La mia e-mail:",
-- "Nome vero:",
-- "Località:",
-- "Età:",
-- "Stato civile:",
-- "Sesso:",
-- "Occupazione:",
-- "Hobby",
-- "Ultime notizie",
-- "Citazione preferita",
-- "Link",
-- "Nessuna home page specificata",
-- "Inizio:",
-- "Nessun link specificato",
-- "Cool Link 1",
-- "Cool Link 2",
-- "Cool Link 3",
-- NULL
-- },
-- { JA, "ja", "EUC-JP",
-- "Yahoo! JAPAN ID:",
-- "éžå…¬é–‹",
-- "無回答",
-- "メール:",
-- "åå‰ï¼š",
-- "ä½æ‰€ï¼š",
-- "年齢:",
-- "未婚/既婚:",
-- "性別:",
-- "è·æ¥­ï¼š",
-- "趣味:",
-- "最近ã®å‡ºæ¥äº‹ï¼š",
-- NULL,
--#if 0
-- "ãŠã™ã™ã‚サイト",
--#else
-- "自己PR", /* "Self description" comes before "Links" for yahoo.co.jp */
--#endif
-- NULL,
-- NULL,
-- NULL,
-- "ãŠã™ã™ã‚サイト1:",
-- "ãŠã™ã™ã‚サイト2:",
-- "ãŠã™ã™ã‚サイト3:",
-- NULL
-- },
-- { KO, "ko", "EUC-KR",
-- "야후! ID:",
-- "비공개",
-- "비공개",
-- "My Email",
-- "실명:",
-- "거주지:",
-- "나ì´:",
-- "결혼 여부:",
-- "성별:",
-- "ì§ì—…:",
-- "취미:",
-- "ìžê¸° 소개:",
-- "좋아하는 명언",
-- "ë§í¬",
-- "홈페ì´ì§€ë¥¼ 지정하지 않았습니다.",
-- "홈페ì´ì§€:",
-- "추천 사ì´íŠ¸ê°€ 없습니다.",
-- "추천 사ì´íŠ¸ 1:",
-- "추천 사ì´íŠ¸ 2:",
-- "추천 사ì´íŠ¸ 3:",
-- NULL
-- },
-- { NO, "no", "ISO-8859-1",
-- "Yahoo! ID:",
-- "Privat",
-- "Ikke noe svar",
-- "Min e-post",
-- "Virkelig navn:",
-- "Sted:",
-- "Alder:",
-- "Sivilstatus:",
-- "Kjønn:",
-- "Yrke:",
-- "Hobbyer:",
-- "Siste nytt:",
-- "Yndlingssitat",
-- "Lenker",
-- "Ingen hjemmeside angitt",
-- "Hjemmeside:",
-- "No cool link specified",
-- "Bra lenke 1:",
-- "Bra lenke 2:",
-- "Bra lenke 3:",
-- NULL
-- },
-- { PT, "pt", "ISO-8859-1",
-- "ID Yahoo!:",
-- "Particular",
-- "Sem resposta",
-- "Meu e-mail",
-- "Nome verdadeiro:",
-- "Local:",
-- "Idade:",
-- "Estado civil:",
-- "Sexo:",
-- "Ocupação:",
-- "Hobbies:",
-- "Últimas notícias:",
-- "Frase favorita",
-- "Links",
-- "Nenhuma página pessoal especificada",
-- "Página pessoal:",
-- "Nenhum site legal especificado",
-- "Site legal 1:",
-- "Site legal 2:",
-- "Site legal 3:",
-- NULL
-- },
-- { PT_BR, "pt_br", "ISO-8859-1",
-- "ID Yahoo!:",
-- "Particular",
-- "Sem resposta",
-- "Meu e-mail",
-- "Nome verdadeiro:",
-- "Localização:",
-- "Idade:",
-- "Estado civil:",
-- "Sexo:",
-- "Ocupação:",
-- "Pasatiempos:",
-- "Últimas novidades:",
-- "Frase preferida:",
-- "Links",
-- "Nenhuma home page especificada",
-- "Página Web:",
-- "Nenhum site legal especificado",
-- "Link legal 1",
-- "Link legal 2",
-- "Link legal 3",
-- NULL
-- },
-- { SV, "sv", "ISO-8859-1",
-- "Yahoo!-ID:",
-- "Privat",
-- "Inget svar",
-- "Min mail",
-- "Riktigt namn:",
-- "Plats:",
-- "Ã…lder:",
-- "Civilstånd:",
-- "Kön:",
-- "Yrke:",
-- "Hobby:",
-- "Senaste nytt:",
-- "Favoritcitat",
-- "Länkar",
-- "Ingen hemsida specificerad",
-- "Hemsida:",
-- "Ingen cool länk specificerad",
-- "Coola länkar 1:",
-- "Coola länkar 2:",
-- "Coola länkar 3:",
-- NULL
-- },
-- { ZH_CN, "zh_CN", "GB2312",
-- "Yahoo! ID:",
-- "没有æä¾›",
-- "没有回答",
-- "个人电邮地å€",
-- "真实姓å:",
-- "所在地点:",
-- "年龄:",
-- "婚姻状况:",
-- "性别:",
-- "èŒä¸š:",
-- "业余爱好:",
-- "个人近况:",
-- "喜欢的引言",
-- "链接",
-- "没有个人主页",
-- "个人主页:",
-- "没有推è网站链接",
-- "推è网站链接 1:",
-- "推è网站链接 2:",
-- "推è网站链接 3:",
-- NULL
-- },
-- { ZH_HK, "zh_HK", "Big5",
-- "Yahoo! ID:",
-- "ç§äººçš„",
-- "沒有回答",
-- "é›»å­ä¿¡ç®±",
-- "真實姓å:",
-- "地點:",
-- "年齡:",
-- "婚姻狀æ³:",
-- "性別:",
-- "è·æ¥­:",
-- "嗜好:",
-- "最新消æ¯:",
-- "最喜愛的股票å«åƒ¹", /* [sic] Yahoo!'s translators don't check context */
-- "連çµ",
-- "沒有注明個人網é ", /* [sic] */
-- "個人網é :",
-- "沒有注明 Cool 連çµ", /* [sic] */
-- "Cool é€£çµ 1:", /* TODO */
-- "Cool é€£çµ 2:", /* TODO */
-- "Cool é€£çµ 3:", /* TODO */
-- NULL
-- },
-- { ZH_TW, "zh_TW", "Big5",
-- "帳 號:",
-- "沒有æä¾›",
-- "沒有回應",
-- "é›»å­ä¿¡ç®±",
-- "姓å:",
-- "地點:",
-- "年齡:",
-- "婚姻狀態:",
-- "性別:",
-- "è·æ¥­:",
-- "興趣:",
-- "個人近æ³:",
-- "喜歡的åå¥",
-- "連çµ",
-- "沒有個人網é ",
-- "個人網é :",
-- "沒有推薦網站連çµ",
-- "æŽ¨è–¦ç¶²ç«™é€£çµ 1:",
-- "æŽ¨è–¦ç¶²ç«™é€£çµ 2:",
-- "æŽ¨è–¦ç¶²ç«™é€£çµ 3:",
-- NULL
-- },
-- { ZH_US, "zh_US", "Big5", /* ZH_US is like ZH_TW, but also a bit like ZH_HK */
-- "Yahoo! ID:",
-- "沒有æä¾›",
-- "沒有回答",
-- "個人Email地å€",
-- "真實姓å:",
-- "地點:",
-- "年齡:",
-- "婚姻狀態:",
-- "性別:",
-- "è·æ¥­:",
-- "嗜好:",
-- "個人近æ³:",
-- "喜歡的åå¥",
-- "連çµ",
-- "沒有個人網é ",
-- "個人網é :",
-- "沒有推薦網站連çµ",
-- "æŽ¨è–¦ç¶²ç«™é€£çµ 1:", /* TODO */
-- "æŽ¨è–¦ç¶²ç«™é€£çµ 2:", /* TODO */
-- "æŽ¨è–¦ç¶²ç«™é€£çµ 3:", /* TODO */
-- NULL
-- },
-- { XX, NULL, NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL,
-- NULL
-- },
--};
--
--static char *yahoo_info_date_reformat(const char *field, size_t len)
--{
-- char *tmp = g_strndup(field, len);
-- time_t t = purple_str_to_time(tmp, FALSE, NULL, NULL, NULL);
--
-- g_free(tmp);
-- return g_strdup(purple_date_format_short(localtime(&t)));
--}
--
--static char *yahoo_remove_nonbreaking_spaces(char *str)
--{
-- char *p;
-- while ((p = strstr(str, "&nbsp;")) != NULL) {
-- *p = ' '; /* Turn &nbsp;'s into ordinary blanks */
-- p += 1;
-- memmove(p, p + 5, strlen(p + 5));
-- str[strlen(str) - 5] = '\0';
-- }
-- return str;
--}
--
--static void yahoo_extract_user_info_text(PurpleNotifyUserInfo *user_info, YahooGetInfoData *info_data) {
-- PurpleBuddy *b;
-- YahooFriend *f;
--
-- b = purple_find_buddy(purple_connection_get_account(info_data->gc),
-- info_data->name);
--
-- if (b) {
-- const char *balias = purple_buddy_get_local_buddy_alias(b);
-- if(balias && balias[0]) {
-- purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), balias);
-- }
-- #if 0
-- if (b->idle > 0) {
-- char *idletime = purple_str_seconds_to_string(time(NULL) - b->idle);
-- purple_notify_user_info_add_pair_plaintext(user_info, _("Idle"), idletime);
-- g_free(idletime);
-- }
-- #endif
--
-- /* Add the normal tooltip pairs */
-- yahoo_tooltip_text(b, user_info, TRUE);
--
-- if ((f = yahoo_friend_find(info_data->gc, purple_buddy_get_name(b)))) {
-- const char *ip;
-- if ((ip = yahoo_friend_get_ip(f)))
-- purple_notify_user_info_add_pair_plaintext(user_info, _("IP Address"), ip);
-- }
-- }
--}
--
--#if PHOTO_SUPPORT
--
--static char *yahoo_get_photo_url(const char *url_text, const char *name) {
-- GString *s = g_string_sized_new(strlen(name) + 8);
-- char *p;
-- char *it = NULL;
--
-- /*g_string_printf(s, " alt=\"%s\">", name);*/
-- /* Y! newformat */
-- g_string_printf(s, " alt=%s>", name);
-- p = strstr(url_text, s->str);
--
-- if (p) {
-- /* Search backwards for "http://". This is stupid, but it works. */
-- for (; !it && p > url_text; p -= 1) {
-- /*if (strncmp(p, "\"http://", 8) == 0) {*/
-- /* Y! newformat*/
-- if (strncmp(p, "=http://", 8) == 0) {
-- char *q;
-- p += 1; /* skip only the ' ' */
-- q = strchr(p, ' ');
-- if (q) {
-- g_free(it);
-- it = g_strndup(p, q - p);
-- }
-- }
-- }
-- }
--
-- g_string_free(s, TRUE);
-- return it;
--}
--
--static void
--yahoo_got_photo(PurpleUtilFetchUrlData *url_data, gpointer data,
-- const gchar *url_text, size_t len, const gchar *error_message);
--
--#endif /* PHOTO_SUPPORT */
--
--static void yahoo_got_info(PurpleUtilFetchUrlData *url_data, gpointer user_data,
-- const gchar *url_text, size_t len, const gchar *error_message)
--{
-- YahooGetInfoData *info_data = (YahooGetInfoData *)user_data;
-- PurpleNotifyUserInfo *user_info;
-- char *p;
--#if PHOTO_SUPPORT
-- YahooGetInfoStepTwoData *info2_data;
-- char *photo_url_text = NULL;
--#else
-- gboolean found = FALSE;
-- char *stripped;
-- int stripped_len;
-- char *last_updated_utf8_string = NULL;
--#endif /* !PHOTO_SUPPORT */
-- const char *last_updated_string = NULL;
-- char *url_buffer;
-- GString *s;
-- char *tmp;
-- char *profile_url_text = NULL;
-- int lang, strid;
-- YahooData *yd;
-- const profile_strings_node_t *strings = NULL;
-- const char *title;
-- profile_state_t profile_state = PROFILE_STATE_DEFAULT;
--
-- purple_debug_info("yahoo", "In yahoo_got_info\n");
--
-- yd = info_data->gc->proto_data;
-- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
--
-- user_info = purple_notify_user_info_new();
--
-- title = yd->jp ? _("Yahoo! Japan Profile") :
-- _("Yahoo! Profile");
--
-- /* Get the tooltip info string */
-- yahoo_extract_user_info_text(user_info, info_data);
--
-- /* We failed to grab the profile URL. This is not expected to actually
-- * happen except under unusual error conditions, as Yahoo is observed
-- * to send back HTML, with a 200 status code.
-- */
-- if (error_message != NULL || url_text == NULL || strcmp(url_text, "") == 0) {
-- purple_notify_user_info_add_pair(user_info, _("Error retrieving profile"), NULL);
-- purple_notify_userinfo(info_data->gc, info_data->name,
-- user_info, NULL, NULL);
-- purple_notify_user_info_destroy(user_info);
-- g_free(profile_url_text);
-- g_free(info_data->name);
-- g_free(info_data);
-- return;
-- }
--
-- /* Construct the correct profile URL */
-- s = g_string_sized_new(80); /* wild guess */
-- g_string_printf(s, "%s%s", (yd->jp? YAHOOJP_PROFILE_URL: YAHOO_PROFILE_URL),
-- info_data->name);
-- profile_url_text = g_string_free(s, FALSE);
-- s = NULL;
--
-- /* We don't yet support the multiple link level of the warning page for
-- * 'adult' profiles, not to mention the fact that yahoo wants you to be
-- * logged in (on the website) to be able to view an 'adult' profile. For
-- * now, just tell them that we can't help them, and provide a link to the
-- * profile if they want to do the web browser thing.
-- */
-- p = strstr(url_text, "Adult Profiles Warning Message");
-- if (!p) {
-- p = strstr(url_text, "Adult Content Warning"); /* TITLE element */
-- }
-- if (p) {
-- tmp = g_strdup_printf("<b>%s</b><br><br>"
-- "%s<br><a href=\"%s\">%s</a>",
-- _("Sorry, profiles marked as containing adult content "
-- "are not supported at this time."),
-- _("If you wish to view this profile, "
-- "you will need to visit this link in your web browser:"),
-- profile_url_text, profile_url_text);
-- purple_notify_user_info_add_pair(user_info, NULL, tmp);
-- g_free(tmp);
--
-- purple_notify_userinfo(info_data->gc, info_data->name,
-- user_info, NULL, NULL);
--
-- g_free(profile_url_text);
-- purple_notify_user_info_destroy(user_info);
-- g_free(info_data->name);
-- g_free(info_data);
-- return;
-- }
--
-- /* Check whether the profile is written in a supported language */
-- for (lang = 0;; lang += 1) {
-- last_updated_string = profile_langs[lang].last_updated_string;
-- if (!last_updated_string)
-- break;
--
-- p = strstr(url_text, last_updated_string);
--
-- if (p) {
-- if (profile_langs[lang].det && !strstr(url_text, profile_langs[lang].det))
-- p = NULL;
-- else
-- break;
-- }
-- }
--
-- if (p) {
-- for (strid = 0; profile_strings[strid].lang != XX; strid += 1) {
-- if (profile_strings[strid].lang == profile_langs[lang].lang) break;
-- }
-- strings = profile_strings + strid;
-- purple_debug_info("yahoo", "detected profile lang = %s (%d)\n", profile_strings[strid].lang_string, lang);
-- }
--
-- /* Every user may choose his/her own profile language, and this language
-- * has nothing to do with the preferences of the user which looks at the
-- * profile. We try to support all languages, but nothing is guaranteed.
-- * If we cannot determine the language, it means either (1) the profile
-- * is written in an unsupported language, (2) our language support is
-- * out of date, or (3) the user is not found, or (4) Y! have changed their
-- * webpage layout
-- */
-- if (!p || strings->lang == XX) {
-- if (!strstr(url_text, "Yahoo! Member Directory - User not found")
-- && !strstr(url_text, "was not found on this server.")
-- && !strstr(url_text, "\xb8\xf8\xb3\xab\xa5\xd7\xa5\xed\xa5\xd5\xa5\xa3\xa1\xbc\xa5\xeb\xa4\xac\xb8\xab\xa4\xc4\xa4\xab\xa4\xea\xa4\xde\xa4\xbb\xa4\xf3")) {
-- profile_state = PROFILE_STATE_UNKNOWN_LANGUAGE;
-- } else {
-- profile_state = PROFILE_STATE_NOT_FOUND;
-- }
-- }
--
--#if PHOTO_SUPPORT
-- photo_url_text = yahoo_get_photo_url(url_text, info_data->name);
--#endif /* PHOTO_SUPPORT */
--
-- url_buffer = g_strdup(url_text);
--
-- /*
-- * purple_markup_strip_html() doesn't strip out character entities like &nbsp;
-- * and &#183;
-- */
-- yahoo_remove_nonbreaking_spaces(url_buffer);
--#if 1
-- while ((p = strstr(url_buffer, "&#183;")) != NULL) {
-- memmove(p, p + 6, strlen(p + 6));
-- url_buffer[strlen(url_buffer) - 6] = '\0';
-- }
--#endif
--
-- /* nuke the nasty \r's */
-- purple_str_strip_char(url_buffer, '\r');
--
--#if PHOTO_SUPPORT
-- /* Marshall the existing state */
-- info2_data = g_malloc(sizeof(YahooGetInfoStepTwoData));
-- info2_data->info_data = info_data;
-- info2_data->url_buffer = url_buffer;
-- info2_data->photo_url_text = photo_url_text;
-- info2_data->profile_url_text = profile_url_text;
-- info2_data->strings = strings;
-- info2_data->last_updated_string = last_updated_string;
-- info2_data->title = title;
-- info2_data->profile_state = profile_state;
-- info2_data->user_info = user_info;
--
-- /* Try to put the photo in there too, if there's one */
-- if (photo_url_text) {
-- PurpleUtilFetchUrlData *url_data;
-- /* use whole URL if using HTTP Proxy */
-- gboolean use_whole_url = yahoo_account_use_http_proxy(info_data->gc);
--
-- /* User-uploaded photos use a different server that requires the Host
-- * header, but Yahoo Japan will use the "chunked" content encoding if
-- * we specify HTTP 1.1. So we have to specify 1.0 & fix purple_util_fetch_url
-- */
-- url_data = purple_util_fetch_url(photo_url_text, use_whole_url, NULL,
-- FALSE, yahoo_got_photo, info2_data);
-- if (url_data != NULL)
-- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
-- } else {
-- /* Emulate a callback */
-- yahoo_got_photo(NULL, info2_data, NULL, 0, NULL);
-- }
--}
--
--static void
--yahoo_got_photo(PurpleUtilFetchUrlData *url_data, gpointer data,
-- const gchar *url_text, size_t len, const gchar *error_message)
--{
-- YahooGetInfoStepTwoData *info2_data = (YahooGetInfoStepTwoData *)data;
-- YahooData *yd;
-- gboolean found = FALSE;
-- int id = -1;
--
-- /* Temporary variables */
-- char *p = NULL;
-- char *stripped;
-- int stripped_len;
-- char *last_updated_utf8_string = NULL;
-- char *tmp;
--
-- /* Unmarshall the saved state */
-- YahooGetInfoData *info_data = info2_data->info_data;
-- char *url_buffer = info2_data->url_buffer;
-- PurpleNotifyUserInfo *user_info = info2_data->user_info;
-- char *photo_url_text = info2_data->photo_url_text;
-- char *profile_url_text = info2_data->profile_url_text;
-- const profile_strings_node_t *strings = info2_data->strings;
-- const char *last_updated_string = info2_data->last_updated_string;
-- profile_state_t profile_state = info2_data->profile_state;
--
-- /* We continue here from yahoo_got_info, as if nothing has happened */
--#endif /* PHOTO_SUPPORT */
--
-- /* Jun 29 05 Bleeter: Y! changed their profile pages. Terminators now seem to be */
-- /* </dd> and not \n. The prpl's need to be audited before it can be moved */
-- /* in to purple_markup_strip_html*/
-- char *fudged_buffer;
--
-- yd = info_data->gc->proto_data;
-- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
--
-- fudged_buffer = purple_strcasereplace(url_buffer, "</dd>", "</dd><br>");
-- /* nuke the html, it's easier than trying to parse the horrid stuff */
-- stripped = purple_markup_strip_html(fudged_buffer);
-- stripped_len = strlen(stripped);
--
-- purple_debug_misc("yahoo", "stripped = %p\n", stripped);
-- purple_debug_misc("yahoo", "url_buffer = %p\n", url_buffer);
--
-- /* convert to utf8 */
-- if (strings && strings->charset) {
-- p = g_convert(stripped, -1, "utf-8", strings->charset,
-- NULL, NULL, NULL);
-- if (!p) {
-- p = g_locale_to_utf8(stripped, -1, NULL, NULL, NULL);
-- if (!p) {
-- p = g_convert(stripped, -1, "utf-8", "windows-1252",
-- NULL, NULL, NULL);
-- }
-- }
-- if (p) {
-- g_free(stripped);
-- stripped = purple_utf8_ncr_decode(p);
-- stripped_len = strlen(stripped);
-- g_free(p);
-- }
-- }
-- p = NULL;
--
-- /* "Last updated" should also be converted to utf8 and with &nbsp; killed */
-- if (strings && strings->charset) {
-- last_updated_utf8_string = g_convert(last_updated_string, -1, "utf-8",
-- strings->charset, NULL, NULL, NULL);
-- yahoo_remove_nonbreaking_spaces(last_updated_utf8_string);
--
-- purple_debug_misc("yahoo", "after utf8 conversion: stripped = (%s)\n", stripped);
-- }
--
-- if (profile_state == PROFILE_STATE_DEFAULT) {
--#if 0
-- /* extract their Yahoo! ID and put it in. Don't bother marking has_info as
-- * true, since the Yahoo! ID will always be there */
-- if (!purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->yahoo_id_string, (yd->jp ? 2 : 10), "\n", 0,
-- NULL, _("Yahoo! ID"), 0, NULL, NULL))
-- ;
--#endif
--
--#if PHOTO_SUPPORT
-- /* Try to put the photo in there too, if there's one and is readable */
-- if (data && url_text && len != 0) {
-- if (strstr(url_text, "400 Bad Request")
-- || strstr(url_text, "403 Forbidden")
-- || strstr(url_text, "404 Not Found")) {
--
-- purple_debug_info("yahoo", "Error getting %s: %s\n",
-- photo_url_text, url_text);
-- } else {
-- purple_debug_info("yahoo", "%s is %" G_GSIZE_FORMAT
-- " bytes\n", photo_url_text, len);
-- id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL);
--
-- tmp = g_strdup_printf("<img id=\"%d\"><br>", id);
-- purple_notify_user_info_add_pair(user_info, NULL, tmp);
-- g_free(tmp);
-- }
-- }
--#endif /* PHOTO_SUPPORT */
--
-- /* extract their Email address and put it in */
-- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->my_email_string, (yd->jp ? 4 : 1), " ", 0,
-- strings->private_string, _("Email"), 0, NULL, NULL);
--
-- /* extract the Nickname if it exists */
-- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- "Nickname:", 1, "\n", '\n',
-- NULL, _("Nickname"), 0, NULL, NULL);
--
-- /* extract their RealName and put it in */
-- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->realname_string, (yd->jp ? 3 : 1), "\n", '\n',
-- NULL, _("Real Name"), 0, NULL, NULL);
--
-- /* extract their Location and put it in */
-- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->location_string, (yd->jp ? 4 : 2), "\n", '\n',
-- NULL, _("Location"), 0, NULL, NULL);
--
-- /* extract their Age and put it in */
-- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->age_string, (yd->jp ? 2 : 3), "\n", '\n',
-- NULL, _("Age"), 0, NULL, NULL);
--
-- /* extract their MaritalStatus and put it in */
-- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->maritalstatus_string, (yd->jp ? 2 : 3), "\n", '\n',
-- strings->no_answer_string, _("Marital Status"), 0, NULL, NULL);
--
-- /* extract their Gender and put it in */
-- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->gender_string, (yd->jp ? 2 : 3), "\n", '\n',
-- strings->no_answer_string, _("Gender"), 0, NULL, NULL);
--
-- /* extract their Occupation and put it in */
-- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->occupation_string, 2, "\n", '\n',
-- NULL, _("Occupation"), 0, NULL, NULL);
--
-- /* Hobbies, Latest News, and Favorite Quote are a bit different, since
-- * the values can contain embedded newlines... but any or all of them
-- * can also not appear. The way we delimit them is to successively
-- * look for the next one that _could_ appear, and if all else fails,
-- * we end the section by looking for the 'Links' heading, which is the
-- * next thing to follow this bunch. (For Yahoo Japan, we check for
-- * the "Description" ("Self PR") heading instead of "Links".)
-- */
--
-- if (!purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->hobbies_string, (yd->jp ? 3 : 1), strings->latest_news_string,
-- '\n', "\n", _("Hobbies"), 0, NULL, NULL))
-- {
-- if (!purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->hobbies_string, 1, strings->favorite_quote_string,
-- '\n', "\n", _("Hobbies"), 0, NULL, NULL))
-- {
-- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->hobbies_string, 1, strings->links_string,
-- '\n', "\n", _("Hobbies"), 0, NULL, NULL);
-- }
-- else
-- found = TRUE;
-- }
-- else
-- found = TRUE;
--
-- if (!purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->latest_news_string, 1, strings->favorite_quote_string,
-- '\n', "\n", _("Latest News"), 0, NULL, NULL))
-- {
-- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->latest_news_string, (yd->jp ? 2 : 1), strings->links_string,
-- '\n', "\n", _("Latest News"), 0, NULL, NULL);
-- }
-- else
-- found = TRUE;
--
-- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->favorite_quote_string, 1, strings->links_string,
-- '\n', "\n", _("Favorite Quote"), 0, NULL, NULL);
--
-- /* Home Page will either be "No home page specified",
-- * or "Home Page: " and a link.
-- * For Yahoo! Japan, if there is no home page specified,
-- * neither "No home page specified" nor "Home Page:" is shown.
-- */
-- if (strings->home_page_string) {
-- p = !strings->no_home_page_specified_string? NULL:
-- strstr(stripped, strings->no_home_page_specified_string);
-- if(!p)
-- {
-- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->home_page_string, 1, "\n", 0, NULL,
-- _("Home Page"), 1, NULL, NULL);
-- }
-- }
--
-- /* Cool Link {1,2,3} is also different. If "No cool link specified"
-- * exists, then we have none. If we have one however, we'll need to
-- * check and see if we have a second one. If we have a second one,
-- * we have to check to see if we have a third one.
-- */
-- p = !strings->no_cool_link_specified_string? NULL:
-- strstr(stripped,strings->no_cool_link_specified_string);
-- if (!p)
-- {
-- if (purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->cool_link_1_string, 1, "\n", 0, NULL,
-- _("Cool Link 1"), 1, NULL, NULL))
-- {
-- found = TRUE;
-- if (purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->cool_link_2_string, 1, "\n", 0, NULL,
-- _("Cool Link 2"), 1, NULL, NULL))
-- {
-- purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- strings->cool_link_3_string, 1, "\n", 0, NULL,
-- _("Cool Link 3"), 1, NULL, NULL);
-- }
-- }
-- }
--
-- if (last_updated_utf8_string != NULL) {
-- /* see if Member Since is there, and if so, extract it. */
-- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- "Member Since:", 1, last_updated_utf8_string,
-- '\n', NULL, _("Member Since"), 0, NULL, yahoo_info_date_reformat);
--
-- /* extract the Last Updated date and put it in */
-- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
-- last_updated_utf8_string, (yd->jp ? 2 : 1), (yd->jp ? "\n" : " "), (yd->jp ? 0 : '\n'), NULL,
-- _("Last Update"), 0, NULL, (yd->jp ? NULL : yahoo_info_date_reformat));
-- }
-- } /* if (profile_state == PROFILE_STATE_DEFAULT) */
--
-- if(!found)
-- {
-- const gchar *str;
--
-- purple_notify_user_info_add_section_break(user_info);
-- purple_notify_user_info_add_pair(user_info,
-- _("Error retrieving profile"), NULL);
--
-- if (profile_state == PROFILE_STATE_UNKNOWN_LANGUAGE) {
-- str = _("This profile is in a language "
-- "or format that is not supported at this time.");
--
-- } else if (profile_state == PROFILE_STATE_NOT_FOUND) {
-- PurpleBuddy *b = purple_find_buddy
-- (purple_connection_get_account(info_data->gc),
-- info_data->name);
-- YahooFriend *f = NULL;
-- if (b) {
-- /* Someone on the buddy list can be "not on server list",
-- * in which case the user may or may not actually exist.
-- * Hence this extra step.
-- */
-- PurpleAccount *account = purple_buddy_get_account(b);
-- f = yahoo_friend_find(purple_account_get_connection(account),
-- purple_buddy_get_name(b));
-- }
-- str = f ? _("Could not retrieve the user's profile. "
-- "This most likely is a temporary server-side problem. "
-- "Please try again later.") :
-- _("Could not retrieve the user's profile. "
-- "This most likely means that the user does not exist; "
-- "however, Yahoo! sometimes does fail to find a user's "
-- "profile. If you know that the user exists, "
-- "please try again later.");
-- } else {
-- str = _("The user's profile is empty.");
-- }
--
-- purple_notify_user_info_add_pair(user_info, NULL, str);
-- }
--
-- /* put a link to the actual profile URL */
-- purple_notify_user_info_add_section_break(user_info);
-- tmp = g_strdup_printf("<a href=\"%s\">%s</a>",
-- profile_url_text, _("View web profile"));
-- purple_notify_user_info_add_pair(user_info, NULL, tmp);
-- g_free(tmp);
--
-- g_free(stripped);
--
-- /* show it to the user */
-- purple_notify_userinfo(info_data->gc, info_data->name,
-- user_info, NULL, NULL);
-- purple_notify_user_info_destroy(user_info);
--
-- g_free(last_updated_utf8_string);
-- g_free(url_buffer);
-- g_free(fudged_buffer);
-- g_free(profile_url_text);
-- g_free(info_data->name);
-- g_free(info_data);
--
--#if PHOTO_SUPPORT
-- g_free(photo_url_text);
-- g_free(info2_data);
-- if (id != -1)
-- purple_imgstore_unref_by_id(id);
--#endif /* PHOTO_SUPPORT */
--}
--
--void yahoo_get_info(PurpleConnection *gc, const char *name)
--{
-- YahooData *yd = gc->proto_data;
-- YahooGetInfoData *data;
-- char *url;
-- PurpleUtilFetchUrlData *url_data;
--
-- data = g_new0(YahooGetInfoData, 1);
-- data->gc = gc;
-- data->name = g_strdup(name);
--
-- url = g_strdup_printf("%s%s",
-- (yd->jp ? YAHOOJP_PROFILE_URL : YAHOO_PROFILE_URL), name);
--
-- url_data = purple_util_fetch_url(url, TRUE, NULL, FALSE, yahoo_got_info, data);
-- if (url_data != NULL)
-- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
--
-- g_free(url);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/ycht.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/ycht.c
---- pidgin-2.10.7/libpurple/protocols/yahoo/ycht.c 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/ycht.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,658 +0,0 @@
--/**
-- * @file ycht.c The Yahoo! protocol plugin, YCHT protocol stuff.
-- *
-- * purple
-- *
-- * Copyright (C) 2004 Timothy Ringenbach <omarvo@hotmail.com>
-- * Liberal amounts of code borrowed from the rest of the Yahoo! prpl.
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#include "internal.h"
--#include "prpl.h"
--#include "notify.h"
--#include "account.h"
--#include "proxy.h"
--#include "debug.h"
--#include "conversation.h"
--#include "util.h"
--
--#include "libymsg.h"
--#include "yahoo_packet.h"
--#include "ycht.h"
--#include "yahoochat.h"
--
--/*
-- * dword: YCHT
-- * dword: 0x000000AE
-- * dword: service
-- * word: status
-- * word: size
-- */
--#define YAHOO_CHAT_ID (1)
--/************************************************************************************
-- * Functions to process various kinds of packets.
-- ************************************************************************************/
--static void ycht_process_login(YchtConn *ycht, YchtPkt *pkt)
--{
-- PurpleConnection *gc = ycht->gc;
-- YahooData *yd = gc->proto_data;
--
-- if (ycht->logged_in)
-- return;
--
-- yd->chat_online = TRUE;
-- ycht->logged_in = TRUE;
--
-- if (ycht->room)
-- ycht_chat_join(ycht, ycht->room);
--}
--
--static void ycht_process_logout(YchtConn *ycht, YchtPkt *pkt)
--{
-- PurpleConnection *gc = ycht->gc;
-- YahooData *yd = gc->proto_data;
--
-- yd->chat_online = FALSE;
-- ycht->logged_in = FALSE;
--}
--
--static void ycht_process_chatjoin(YchtConn *ycht, YchtPkt *pkt)
--{
-- char *room, *topic;
-- PurpleConnection *gc = ycht->gc;
-- PurpleConversation *c = NULL;
-- gboolean new_room = FALSE;
-- char **members;
-- int i;
--
-- room = g_list_nth_data(pkt->data, 0);
-- topic = g_list_nth_data(pkt->data, 1);
-- if (!g_list_nth_data(pkt->data, 4))
-- return;
-- if (!room)
-- return;
--
-- members = g_strsplit(g_list_nth_data(pkt->data, 4), "\001", 0);
-- for (i = 0; members[i]; i++) {
-- char *tmp = strchr(members[i], '\002');
-- if (tmp)
-- *tmp = '\0';
-- }
--
-- if (g_list_length(pkt->data) > 5)
-- new_room = TRUE;
--
-- if (new_room && ycht->changing_rooms) {
-- serv_got_chat_left(gc, YAHOO_CHAT_ID);
-- ycht->changing_rooms = FALSE;
-- c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room);
-- } else {
-- c = purple_find_chat(gc, YAHOO_CHAT_ID);
-- }
--
-- if (topic)
-- purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic);
--
-- for (i = 0; members[i]; i++) {
-- if (new_room) {
-- /*if (!strcmp(members[i], purple_connection_get_display_name(ycht->gc)))
-- continue;*/
-- purple_conv_chat_add_user(PURPLE_CONV_CHAT(c), members[i], NULL, PURPLE_CBFLAGS_NONE, TRUE);
-- } else {
-- yahoo_chat_add_user(PURPLE_CONV_CHAT(c), members[i], NULL);
-- }
-- }
--
-- g_strfreev(members);
--}
--
--static void ycht_process_chatpart(YchtConn *ycht, YchtPkt *pkt)
--{
-- char *room, *who;
--
-- room = g_list_nth_data(pkt->data, 0);
-- who = g_list_nth_data(pkt->data, 1);
--
-- if (who && room) {
-- PurpleConversation *c = purple_find_chat(ycht->gc, YAHOO_CHAT_ID);
-- if (c && !purple_utf8_strcasecmp(purple_conversation_get_name(c), room))
-- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(c), who, NULL);
--
-- }
--}
--
--static void ycht_progress_chatmsg(YchtConn *ycht, YchtPkt *pkt)
--{
-- char *who, *what, *msg;
-- PurpleConversation *c;
-- PurpleConnection *gc = ycht->gc;
--
-- who = g_list_nth_data(pkt->data, 1);
-- what = g_list_nth_data(pkt->data, 2);
--
-- if (!who || !what)
-- return;
--
-- c = purple_find_chat(gc, YAHOO_CHAT_ID);
-- if (!c)
-- return;
--
-- msg = yahoo_string_decode(gc, what, 1);
-- what = yahoo_codes_to_html(msg);
-- g_free(msg);
--
-- if (pkt->service == YCHT_SERVICE_CHATMSG_EMOTE) {
-- char *tmp = g_strdup_printf("/me %s", what);
-- g_free(what);
-- what = tmp;
-- }
--
-- serv_got_chat_in(gc, YAHOO_CHAT_ID, who, 0, what, time(NULL));
-- g_free(what);
--}
--
--static void ycht_progress_online_friends(YchtConn *ycht, YchtPkt *pkt)
--{
--#if 0
-- PurpleConnection *gc = ycht->gc;
-- YahooData *yd = gc->proto_data;
--
-- if (ycht->logged_in)
-- return;
--
-- yd->chat_online = TRUE;
-- ycht->logged_in = TRUE;
--
-- if (ycht->room)
-- ycht_chat_join(ycht, ycht->room);
--#endif
--}
--
--/*****************************************************************************
-- * Functions dealing with YCHT packets and their contents directly.
-- *****************************************************************************/
--static void ycht_packet_dump(const guchar *data, int len)
--{
--#ifdef YAHOO_YCHT_DEBUG
-- int i;
--
-- purple_debug_misc("yahoo", "");
--
-- for (i = 0; i + 1 < len; i += 2) {
-- if ((i % 16 == 0) && i) {
-- purple_debug_misc(NULL, "\n");
-- purple_debug_misc("yahoo", "");
-- }
--
-- purple_debug_misc(NULL, "%02hhx%02hhx ", data[i], data[i + 1]);
-- }
-- if (i < len)
-- purple_debug_misc(NULL, "%02hhx", data[i]);
--
-- purple_debug_misc(NULL, "\n");
-- purple_debug_misc("yahoo", "");
--
-- for (i = 0; i < len; i++) {
-- if ((i % 16 == 0) && i) {
-- purple_debug_misc(NULL, "\n");
-- purple_debug_misc("yahoo", "");
-- }
--
-- if (g_ascii_isprint(data[i]))
-- purple_debug_misc(NULL, "%c ", data[i]);
-- else
-- purple_debug_misc(NULL, ". ");
-- }
--
-- purple_debug_misc(NULL, "\n");
--#endif /* YAHOO_YCHT_DEBUG */
--}
--
--static YchtPkt *ycht_packet_new(guint version, guint service, int status)
--{
-- YchtPkt *ret;
--
-- ret = g_new0(YchtPkt, 1);
--
-- ret->version = version;
-- ret->service = service;
-- ret->status = status;
--
-- return ret;
--}
--
--static void ycht_packet_append(YchtPkt *pkt, const char *str)
--{
-- g_return_if_fail(pkt != NULL);
-- g_return_if_fail(str != NULL);
--
-- pkt->data = g_list_append(pkt->data, g_strdup(str));
--}
--
--static int ycht_packet_length(YchtPkt *pkt)
--{
-- int ret;
-- GList *l;
--
-- ret = YCHT_HEADER_LEN;
--
-- for (l = pkt->data; l; l = l->next) {
-- ret += strlen(l->data);
-- if (l->next)
-- ret += strlen(YCHT_SEP);
-- }
--
-- return ret;
--}
--
--static void ycht_packet_send_write_cb(gpointer data, gint source, PurpleInputCondition cond)
--{
-- YchtConn *ycht = data;
-- int ret, writelen;
--
-- writelen = purple_circ_buffer_get_max_read(ycht->txbuf);
--
-- if (writelen == 0) {
-- purple_input_remove(ycht->tx_handler);
-- ycht->tx_handler = 0;
-- return;
-- }
--
-- ret = write(ycht->fd, ycht->txbuf->outptr, writelen);
--
-- if (ret < 0 && errno == EAGAIN)
-- return;
-- else if (ret <= 0) {
-- /* TODO: error handling */
--/*
-- gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
-- g_strerror(errno));
-- purple_connection_error_reason(purple_account_get_connection(irc->account),
-- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-- g_free(tmp);
--*/
-- return;
-- }
--
-- purple_circ_buffer_mark_read(ycht->txbuf, ret);
--
--}
--
--static void ycht_packet_send(YchtConn *ycht, YchtPkt *pkt)
--{
-- int len, pos, written;
-- char *buf;
-- GList *l;
--
-- g_return_if_fail(ycht != NULL);
-- g_return_if_fail(pkt != NULL);
-- g_return_if_fail(ycht->fd != -1);
--
-- pos = 0;
-- len = ycht_packet_length(pkt);
-- buf = g_malloc(len);
--
-- memcpy(buf + pos, "YCHT", 4); pos += 4;
-- pos += yahoo_put32(buf + pos, pkt->version);
-- pos += yahoo_put32(buf + pos, pkt->service);
-- pos += yahoo_put16(buf + pos, pkt->status);
-- pos += yahoo_put16(buf + pos, len - YCHT_HEADER_LEN);
--
-- for (l = pkt->data; l; l = l->next) {
-- int slen = strlen(l->data);
-- memcpy(buf + pos, l->data, slen); pos += slen;
--
-- if (l->next) {
-- memcpy(buf + pos, YCHT_SEP, strlen(YCHT_SEP));
-- pos += strlen(YCHT_SEP);
-- }
-- }
--
-- if (!ycht->tx_handler)
-- written = write(ycht->fd, buf, len);
-- else {
-- written = -1;
-- errno = EAGAIN;
-- }
--
-- if (written < 0 && errno == EAGAIN)
-- written = 0;
-- else if (written <= 0) {
-- /* TODO: Error handling (was none before NBIO changes) */
-- written = 0;
-- }
--
-- if (written < len) {
-- if (!ycht->tx_handler)
-- ycht->tx_handler = purple_input_add(ycht->fd,
-- PURPLE_INPUT_WRITE, ycht_packet_send_write_cb,
-- ycht);
-- purple_circ_buffer_append(ycht->txbuf, buf + written,
-- len - written);
-- }
--
-- g_free(buf);
--}
--
--static void ycht_packet_read(YchtPkt *pkt, const char *buf, int len)
--{
-- const char *pos = buf;
-- const char *needle;
-- char *tmp, *tmp2;
-- int i = 0;
--
-- while (len > 0 && (needle = g_strstr_len(pos, len, YCHT_SEP))) {
-- tmp = g_strndup(pos, needle - pos);
-- pkt->data = g_list_append(pkt->data, tmp);
-- len -= needle - pos + strlen(YCHT_SEP);
-- pos = needle + strlen(YCHT_SEP);
-- tmp2 = g_strescape(tmp, NULL);
-- purple_debug_misc("yahoo", "Data[%d]:\t%s\n", i++, tmp2);
-- g_free(tmp2);
-- }
--
-- if (len) {
-- tmp = g_strndup(pos, len);
-- pkt->data = g_list_append(pkt->data, tmp);
-- tmp2 = g_strescape(tmp, NULL);
-- purple_debug_misc("yahoo", "Data[%d]:\t%s\n", i, tmp2);
-- g_free(tmp2);
-- };
--
-- purple_debug_misc("yahoo", "--==End of incoming YCHT packet==--\n");
--}
--
--static void ycht_packet_process(YchtConn *ycht, YchtPkt *pkt)
--{
-- if (pkt->data && !strncmp(pkt->data->data, "*** Danger Will Robinson!!!", strlen("*** Danger Will Robinson!!!")))
-- return;
--
-- switch (pkt->service) {
-- case YCHT_SERVICE_LOGIN:
-- ycht_process_login(ycht, pkt);
-- break;
-- case YCHT_SERVICE_LOGOUT:
-- ycht_process_logout(ycht, pkt);
-- break;
-- case YCHT_SERVICE_CHATJOIN:
-- ycht_process_chatjoin(ycht, pkt);
-- break;
-- case YCHT_SERVICE_CHATPART:
-- ycht_process_chatpart(ycht, pkt);
-- break;
-- case YCHT_SERVICE_CHATMSG:
-- case YCHT_SERVICE_CHATMSG_EMOTE:
-- ycht_progress_chatmsg(ycht, pkt);
-- break;
-- case YCHT_SERVICE_ONLINE_FRIENDS:
-- ycht_progress_online_friends(ycht, pkt);
-- break;
-- default:
-- purple_debug_warning("yahoo", "YCHT: warning, unhandled service 0x%02x\n", pkt->service);
-- }
--}
--
--static void ycht_packet_free(YchtPkt *pkt)
--{
-- GList *l;
--
-- g_return_if_fail(pkt != NULL);
--
-- for (l = pkt->data; l; l = l->next)
-- g_free(l->data);
-- g_list_free(pkt->data);
-- g_free(pkt);
--}
--
--/************************************************************************************
-- * Functions dealing with connecting and disconnecting and reading data into YchtPkt
-- * structs, and all that stuff.
-- ************************************************************************************/
--
--void ycht_connection_close(YchtConn *ycht)
--{
-- YahooData *yd = ycht->gc->proto_data;
--
-- if (yd) {
-- yd->ycht = NULL;
-- yd->chat_online = FALSE;
-- }
--
-- if (ycht->fd > 0)
-- close(ycht->fd);
-- if (ycht->inpa)
-- purple_input_remove(ycht->inpa);
--
-- if (ycht->tx_handler)
-- purple_input_remove(ycht->tx_handler);
--
-- purple_circ_buffer_destroy(ycht->txbuf);
--
-- g_free(ycht->rxqueue);
--
-- g_free(ycht);
--}
--
--static void ycht_connection_error(YchtConn *ycht, const gchar *error)
--{
--
-- purple_notify_info(ycht->gc, NULL, _("Connection problem with the YCHT server"), error);
-- ycht_connection_close(ycht);
--}
--
--static void ycht_pending(gpointer data, gint source, PurpleInputCondition cond)
--{
-- YchtConn *ycht = data;
-- char buf[1024];
-- int len;
--
-- len = read(ycht->fd, buf, sizeof(buf));
--
-- if (len < 0) {
-- gchar *tmp;
--
-- if (errno == EAGAIN)
-- /* No worries */
-- return;
--
-- tmp = g_strdup_printf(_("Lost connection with server: %s"),
-- g_strerror(errno));
-- ycht_connection_error(ycht, tmp);
-- g_free(tmp);
-- return;
-- } else if (len == 0) {
-- ycht_connection_error(ycht, _("Server closed the connection"));
-- return;
-- }
--
-- ycht->rxqueue = g_realloc(ycht->rxqueue, len + ycht->rxlen);
-- memcpy(ycht->rxqueue + ycht->rxlen, buf, len);
-- ycht->rxlen += len;
--
-- while (1) {
-- YchtPkt *pkt;
-- int pos = 0;
-- int pktlen;
-- guint service;
-- guint version;
-- gint status;
--
-- if (ycht->rxlen < YCHT_HEADER_LEN)
-- return;
--
-- if (strncmp("YCHT", (char *)ycht->rxqueue, 4) != 0)
-- purple_debug_error("yahoo", "YCHT: protocol error.\n");
--
-- pos += 4; /* YCHT */
--
-- version = yahoo_get32(ycht->rxqueue + pos); pos += 4;
-- service = yahoo_get32(ycht->rxqueue + pos); pos += 4;
-- status = yahoo_get16(ycht->rxqueue + pos); pos += 2;
-- pktlen = yahoo_get16(ycht->rxqueue + pos); pos += 2;
-- purple_debug_misc("yahoo", "ycht: %d bytes to read, rxlen is %d\n",
-- pktlen, ycht->rxlen);
--
-- if (ycht->rxlen < (YCHT_HEADER_LEN + pktlen))
-- return;
--
-- purple_debug_misc("yahoo", "--==Incoming YCHT packet==--\n");
-- purple_debug_misc("yahoo", "YCHT Service: 0x%02x Version: 0x%02x Status: 0x%02x\n",
-- service, version, status);
-- ycht_packet_dump(ycht->rxqueue, YCHT_HEADER_LEN + pktlen);
--
-- pkt = ycht_packet_new(version, service, status);
-- ycht_packet_read(pkt, (char *)ycht->rxqueue + pos, pktlen);
--
-- ycht->rxlen -= YCHT_HEADER_LEN + pktlen;
-- if (ycht->rxlen) {
-- guchar *tmp = g_memdup(ycht->rxqueue + YCHT_HEADER_LEN + pktlen, ycht->rxlen);
-- g_free(ycht->rxqueue);
-- ycht->rxqueue = tmp;
-- } else {
-- g_free(ycht->rxqueue);
-- ycht->rxqueue = NULL;
-- }
--
-- ycht_packet_process(ycht, pkt);
--
-- ycht_packet_free(pkt);
-- }
--}
--
--static void ycht_got_connected(gpointer data, gint source, const gchar *error_message)
--{
-- YchtConn *ycht = data;
-- PurpleConnection *gc = ycht->gc;
-- YahooData *yd = gc->proto_data;
-- YchtPkt *pkt;
-- char *buf;
--
-- if (source < 0) {
-- ycht_connection_error(ycht, _("Unable to connect"));
-- return;
-- }
--
-- ycht->fd = source;
--
-- pkt = ycht_packet_new(YCHT_VERSION, YCHT_SERVICE_LOGIN, 0);
--
-- buf = g_strdup_printf("%s\001Y=%s; T=%s", purple_connection_get_display_name(gc), yd->cookie_y, yd->cookie_t);
-- ycht_packet_append(pkt, buf);
-- g_free(buf);
--
-- ycht_packet_send(ycht, pkt);
--
-- ycht_packet_free(pkt);
--
-- ycht->inpa = purple_input_add(ycht->fd, PURPLE_INPUT_READ, ycht_pending, ycht);
--}
--
--void ycht_connection_open(PurpleConnection *gc)
--{
-- YchtConn *ycht;
-- YahooData *yd = gc->proto_data;
-- PurpleAccount *account = purple_connection_get_account(gc);
--
-- ycht = g_new0(YchtConn, 1);
-- ycht->gc = gc;
-- ycht->fd = -1;
--
-- yd->ycht = ycht;
--
-- if (purple_proxy_connect(gc, account,
-- purple_account_get_string(account, "ycht-server", YAHOO_YCHT_HOST),
-- purple_account_get_int(account, "ycht-port", YAHOO_YCHT_PORT),
-- ycht_got_connected, ycht) == NULL)
-- {
-- ycht_connection_error(ycht, _("Unable to connect"));
-- return;
-- }
--}
--
--/*******************************************************************************************
-- * These are functions called because the user did something.
-- *******************************************************************************************/
--
--void ycht_chat_join(YchtConn *ycht, const char *room)
--{
-- YchtPkt *pkt;
-- char *tmp;
--
-- tmp = g_strdup(room);
-- g_free(ycht->room);
-- ycht->room = tmp;
--
-- if (!ycht->logged_in)
-- return;
--
-- ycht->changing_rooms = TRUE;
-- pkt = ycht_packet_new(YCHT_VERSION, YCHT_SERVICE_CHATJOIN, 0);
-- ycht_packet_append(pkt, ycht->room);
-- ycht_packet_send(ycht, pkt);
-- ycht_packet_free(pkt);
--}
--
--int ycht_chat_send(YchtConn *ycht, const char *room, const char *what)
--{
-- YchtPkt *pkt;
-- char *msg1, *msg2, *buf;
--
-- if (strcmp(room, ycht->room))
-- purple_debug_warning("yahoo", "uhoh, sending to the wrong room!\n");
--
-- pkt = ycht_packet_new(YCHT_VERSION, YCHT_SERVICE_CHATMSG, 0);
--
-- msg1 = yahoo_html_to_codes(what);
-- msg2 = yahoo_string_encode(ycht->gc, msg1, NULL);
-- g_free(msg1);
--
-- buf = g_strdup_printf("%s\001%s", ycht->room, msg2);
-- ycht_packet_append(pkt, buf);
-- g_free(msg2);
-- g_free(buf);
--
-- ycht_packet_send(ycht, pkt);
-- ycht_packet_free(pkt);
-- return 1;
--}
--
--void ycht_chat_leave(YchtConn *ycht, const char *room, gboolean logout)
--{
-- if (logout)
-- ycht_connection_close(ycht);
--}
--
--void ycht_chat_send_invite(YchtConn *ycht, const char *room, const char *buddy, const char *msg)
--{
--}
--
--void ycht_chat_goto_user(YchtConn *ycht, const char *name)
--{
--}
--
--void ycht_chat_send_keepalive(YchtConn *ycht)
--{
-- YchtPkt *pkt;
--
-- pkt = ycht_packet_new(YCHT_VERSION, YCHT_SERVICE_PING, 0);
-- ycht_packet_send(ycht, pkt);
-- ycht_packet_free(pkt);
--}
-diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/ycht.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/ycht.h
---- pidgin-2.10.7/libpurple/protocols/yahoo/ycht.h 2013-02-11 07:16:52.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/ycht.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,97 +0,0 @@
--/**
-- * @file ycht.h The Yahoo! protocol plugin, YCHT protocol stuff.
-- *
-- * purple
-- *
-- * Copyright (C) 2004 Timothy Ringenbach <omarvo@hotmail.com>
-- *
-- * Purple is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--
--#ifndef _PURPLE_YCHT_H_
--#define _PURPLE_YCHT_H_
--
--/* #define YAHOO_YCHT_DEBUG */
--
--#define YAHOO_YCHT_HOST "jcs3.chat.dcn.yahoo.com"
--#define YAHOO_YCHT_PORT 8002
--
--#define YCHT_VERSION (0xae)
--#define YCHT_HEADER_LEN (0x10)
--
--typedef enum {
-- YCHT_SERVICE_LOGIN = 0x01,
-- YCHT_SERVICE_LOGOUT = 0x02,
-- YCHT_SERVICE_CHATJOIN = 0x11,
-- YCHT_SERVICE_CHATPART = 0x12,
-- YCHT_SERVICE_CHATMSG = 0x41,
-- YCHT_SERVICE_CHATMSG_EMOTE = 0x43,
-- YCHT_SERVICE_PING = 0x62,
-- YCHT_SERVICE_ONLINE_FRIENDS = 0x68
--} ycht_service;
--/*
--yahoo: YCHT Service: 0x11 Version: 0x100
--yahoo: Data[0]: Linux, FreeBSD, Solaris:1
--yahoo: Data[1]: Questions, problems and discussions about all flavors of Unix.
--yahoo: Data[2]:
--yahoo: Data[3]: 0
--yahoo: Data[4]: sgooki888\0020\002 \0022769036\00258936\002
--yahoo: --==End of incoming YCHT packet==--
--
--yahoo: --==Incoming YCHT packet==--
--yahoo: YCHT Service: 0x12 Version: 0x100
--yahoo: Data[0]: Linux, FreeBSD, Solaris:1
--yahoo: Data[1]: cccc4cccc
--yahoo: --==End of incoming YCHT packet==--
--
--*/
--#define YCHT_SEP "\xc0\x80"
--
--typedef struct _YchtConn {
-- PurpleConnection *gc;
-- gchar *room;
-- int room_id;
-- gint fd;
-- gint inpa;
-- gboolean logged_in;
-- gboolean changing_rooms;
-- guchar *rxqueue;
-- guint rxlen;
-- PurpleCircBuffer *txbuf;
-- guint tx_handler;
--} YchtConn;
--
--typedef struct {
-- guint version;
-- guint service;
-- gint status;
-- GList *data;
--} YchtPkt;
--
--void ycht_connection_open(PurpleConnection *gc);
--void ycht_connection_close(YchtConn *ycht);
--
--void ycht_chat_join(YchtConn *ycht, const char *room);
--int ycht_chat_send(YchtConn *ycht, const char *room, const char *what);
--void ycht_chat_leave(YchtConn *ycht, const char *room, gboolean logout);
--void ycht_chat_send_invite(YchtConn *ycht, const char *room, const char *buddy, const char *msg);
--void ycht_chat_goto_user(YchtConn *ycht, const char *name);
--void ycht_chat_send_keepalive(YchtConn *ycht);
--
--#endif /* _PURPLE_YCHT_H_ */
-diff -Nur pidgin-2.10.7/libpurple/protocols/zephyr/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/zephyr/Makefile.in
---- pidgin-2.10.7/libpurple/protocols/zephyr/Makefile.in 2013-02-11 07:17:23.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/protocols/zephyr/Makefile.in 2013-08-16 23:51:52.870438890 -0300
-@@ -233,8 +233,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -296,8 +294,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
diff -Nur pidgin-2.10.7/libpurple/prpl.h pidgin-2.10.7-nonprism/libpurple/prpl.h
--- pidgin-2.10.7/libpurple/prpl.h 2013-02-11 07:16:53.000000000 -0200
+++ pidgin-2.10.7-nonprism/libpurple/prpl.h 2013-08-16 22:29:46.145754932 -0300
@@ -150632,57 +1895,6 @@ diff -Nur pidgin-2.10.7/libpurple/tests/test_jabber_jutil.c pidgin-2.10.7-nonpri
assert_invalid_jid("paul@[::1]124");
assert_invalid_jid("paul@2[::1]124/as");
assert_invalid_jid("paul@ã¾ã¤.ãŠãŠã‹ã¿/\x01");
-diff -Nur pidgin-2.10.7/libpurple/tests/test_oscar_util.c pidgin-2.10.7-nonprism/libpurple/tests/test_oscar_util.c
---- pidgin-2.10.7/libpurple/tests/test_oscar_util.c 2013-02-11 07:16:53.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/tests/test_oscar_util.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,47 +0,0 @@
--#include <string.h>
--
--#include "tests.h"
--#include "../protocols/oscar/oscar.h"
--
--START_TEST(test_oscar_util_name_compare)
--{
-- int i;
-- const char *good[] = {
-- "test",
-- "TEST",
-- "Test",
-- "teSt",
-- " TesT",
-- "test ",
-- " T E s T "
-- };
-- const char *bad[] = {
-- "toast",
-- "test@example.com",
-- "test@aim.com"
-- };
--
-- for (i = 0; i < G_N_ELEMENTS(good); i++) {
-- ck_assert_int_eq(0, oscar_util_name_compare("test", good[i]));
-- ck_assert_int_eq(0, oscar_util_name_compare(good[i], "test"));
-- }
-- for (i = 0; i < G_N_ELEMENTS(bad); i++) {
-- ck_assert_int_ne(0, oscar_util_name_compare("test", bad[i]));
-- ck_assert_int_ne(0, oscar_util_name_compare(bad[i], "test"));
-- }
--}
--END_TEST
--
--Suite *oscar_util_suite(void)
--{
-- Suite *s;
-- TCase *tc;
--
-- s = suite_create("OSCAR Utility Functions");
--
-- tc = tcase_create("Convert IM from network format to HTML");
-- tcase_add_test(tc, test_oscar_util_name_compare);
-- suite_add_tcase(s, tc);
--
-- return s;
--}
diff -Nur pidgin-2.10.7/libpurple/tests/tests.h pidgin-2.10.7-nonprism/libpurple/tests/tests.h
--- pidgin-2.10.7/libpurple/tests/tests.h 2013-02-11 07:16:53.000000000 -0200
+++ pidgin-2.10.7-nonprism/libpurple/tests/tests.h 2013-08-16 22:56:18.999567027 -0300
@@ -150695,224 +1907,6 @@ diff -Nur pidgin-2.10.7/libpurple/tests/tests.h pidgin-2.10.7-nonprism/libpurple
Suite * util_suite(void);
Suite * xmlnode_suite(void);
-diff -Nur pidgin-2.10.7/libpurple/tests/test_yahoo_util.c pidgin-2.10.7-nonprism/libpurple/tests/test_yahoo_util.c
---- pidgin-2.10.7/libpurple/tests/test_yahoo_util.c 2013-02-11 07:16:53.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/tests/test_yahoo_util.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,214 +0,0 @@
--#include <string.h>
--
--#include "tests.h"
--#include "../protocols/yahoo/libymsg.h"
--
--static void setup_codes_to_html(void)
--{
-- yahoo_init_colorht();
--}
--
--static void teardown_codes_to_html(void)
--{
-- yahoo_dest_colorht();
--}
--
--START_TEST(test_codes_to_html)
--{
-- assert_string_equal_free("",
-- yahoo_codes_to_html(""));
-- assert_string_equal_free("",
-- yahoo_codes_to_html("\x1B[12345m"));
-- assert_string_equal_free("plain",
-- yahoo_codes_to_html("plain"));
-- assert_string_equal_free("unknown ansi code",
-- yahoo_codes_to_html("unknown \x1B[12345m ansi code"));
-- assert_string_equal_free("plain &lt;peanut&gt;",
-- yahoo_codes_to_html("plain <peanut>"));
-- assert_string_equal_free("plain &lt;peanut",
-- yahoo_codes_to_html("plain <peanut"));
-- assert_string_equal_free("plain&gt; peanut",
-- yahoo_codes_to_html("plain> peanut"));
-- assert_string_equal_free("<font face='inva&gt;lid'>test</font>",
-- yahoo_codes_to_html("<font face='inva>lid'>test"));
-- assert_string_equal_free("&lt;font face=&apos;inva&gt;lid",
-- yahoo_codes_to_html("<font face='inva>lid"));
--
-- /* bold/italic/underline */
-- assert_string_equal_free("<b>bold</b>",
-- yahoo_codes_to_html("\x1B[1mbold"));
-- assert_string_equal_free("<i>italic</i>",
-- yahoo_codes_to_html("\x1B[2mitalic"));
-- assert_string_equal_free("<u>underline</u>",
-- yahoo_codes_to_html("\x1B[4munderline"));
-- assert_string_equal_free("no markup",
-- yahoo_codes_to_html("no\x1B[x4m markup"));
-- assert_string_equal_free("<b>bold</b> <i>italic</i> <u>underline</u>",
-- yahoo_codes_to_html("\x1B[1mbold\x1B[x1m \x1B[2mitalic\x1B[x2m \x1B[4munderline"));
-- assert_string_equal_free("<b>bold <i>bolditalic</i></b><i> italic</i>",
-- yahoo_codes_to_html("\x1B[1mbold \x1B[2mbolditalic\x1B[x1m italic"));
-- assert_string_equal_free("<b>bold <i>bolditalic</i></b><i> <u>italicunderline</u></i>",
-- yahoo_codes_to_html("\x1B[1mbold \x1B[2mbolditalic\x1B[x1m \x1B[4mitalicunderline"));
-- assert_string_equal_free("<b>bold <i>bolditalic <u>bolditalicunderline</u></i><u> boldunderline</u></b>",
-- yahoo_codes_to_html("\x1B[1mbold \x1B[2mbolditalic \x1B[4mbolditalicunderline\x1B[x2m boldunderline"));
-- assert_string_equal_free("<b>bold <i>bolditalic <u>bolditalicunderline</u></i></b><i><u> italicunderline</u></i>",
-- yahoo_codes_to_html("\x1B[1mbold \x1B[2mbolditalic \x1B[4mbolditalicunderline\x1B[x1m italicunderline"));
--
-- /* link */
-- assert_string_equal_free("http://pidgin.im/",
-- yahoo_codes_to_html("\x1B[lmhttp://pidgin.im/\x1B[xlm"));
--
--#ifdef USE_CSS_FORMATTING
-- /* font color */
-- assert_string_equal_free("<span style='color: #0000FF'>blue</span>",
-- yahoo_codes_to_html("\x1B[31mblue"));
-- assert_string_equal_free("<span style='color: #70ea15'>custom color</span>",
-- yahoo_codes_to_html("\x1B[#70ea15mcustom color"));
--
-- /* font face */
-- assert_string_equal_free("<font face='Georgia'>test</font>",
-- yahoo_codes_to_html("<font face='Georgia'>test</font>"));
--
-- /* font size */
-- assert_string_equal_free("<font><span style='font-size: 15pt'>test</span></font>",
-- yahoo_codes_to_html("<font size='15'>test"));
-- assert_string_equal_free("<font><span style='font-size: 32pt'>size 32</span></font>",
-- yahoo_codes_to_html("<font size='32'>size 32"));
--
-- /* combinations */
-- assert_string_equal_free("<font face='Georgia'><span style='font-size: 32pt'>test</span></font>",
-- yahoo_codes_to_html("<font face='Georgia' size='32'>test"));
-- assert_string_equal_free("<span style='color: #FF0080'><font><span style='font-size: 15pt'>test</span></font></span>",
-- yahoo_codes_to_html("\x1B[35m<font size='15'>test"));
--#else
-- /* font color */
-- assert_string_equal_free("<font color='#0000FF'>blue</font>",
-- yahoo_codes_to_html("\x1B[31mblue"));
-- assert_string_equal_free("<font color='#70ea15'>custom color</font>",
-- yahoo_codes_to_html("\x1B[#70ea15mcustom color"));
-- assert_string_equal_free("test",
-- yahoo_codes_to_html("<ALT #ff0000,#00ff00,#0000ff>test</ALT>"));
--
-- /* font face */
-- assert_string_equal_free("<font face='Georgia'>test</font>",
-- yahoo_codes_to_html("<font face='Georgia'>test"));
--
-- /* font size */
-- assert_string_equal_free("<font size='4' absz='15'>test</font>",
-- yahoo_codes_to_html("<font size='15'>test"));
-- assert_string_equal_free("<font size='6' absz='32'>size 32</font>",
-- yahoo_codes_to_html("<font size='32'>size 32"));
--
-- /* combinations */
-- assert_string_equal_free("<font face='Georgia' size='6' absz='32'>test</font>",
-- yahoo_codes_to_html("<font face='Georgia' size='32'>test"));
-- assert_string_equal_free("<font color='#FF0080'><font size='4' absz='15'>test</font></font>",
-- yahoo_codes_to_html("\x1B[35m<font size='15'>test"));
-- assert_string_equal_free(":&lt;",
-- yahoo_codes_to_html("<FADE #ff0000,#00ff00,#0000ff>:<</FADE>"));
--#endif /* !USE_CSS_FORMATTING */
--}
--END_TEST
--
--START_TEST(test_html_to_codes)
--{
-- assert_string_equal_free("plain",
-- yahoo_html_to_codes("plain"));
-- assert_string_equal_free("plain <peanut>",
-- yahoo_html_to_codes("plain &lt;peanut&gt;"));
-- assert_string_equal_free("plain <peanut",
-- yahoo_html_to_codes("plain &lt;peanut"));
-- assert_string_equal_free("plain> peanut",
-- yahoo_html_to_codes("plain&gt; peanut"));
-- assert_string_equal_free("plain >",
-- yahoo_html_to_codes("plain &gt;"));
-- assert_string_equal_free("plain > ",
-- yahoo_html_to_codes("plain &gt; "));
-- assert_string_equal_free("plain <",
-- yahoo_html_to_codes("plain &lt;"));
-- assert_string_equal_free("plain < ",
-- yahoo_html_to_codes("plain &lt; "));
-- assert_string_equal_free("plain &lt",
-- yahoo_html_to_codes("plain &lt"));
-- assert_string_equal_free("plain &",
-- yahoo_html_to_codes("plain &amp;"));
--
-- /* bold/italic/underline */
-- assert_string_equal_free("\x1B[1mbold\x1B[x1m",
-- yahoo_html_to_codes("<b>bold</b>"));
-- assert_string_equal_free("\x1B[2mitalic\x1B[x2m",
-- yahoo_html_to_codes("<i>italic</i>"));
-- assert_string_equal_free("\x1B[4munderline\x1B[x4m",
-- yahoo_html_to_codes("<u>underline</u>"));
-- assert_string_equal_free("no markup",
-- yahoo_html_to_codes("no</u> markup"));
-- assert_string_equal_free("\x1B[1mbold\x1B[x1m \x1B[2mitalic\x1B[x2m \x1B[4munderline\x1B[x4m",
-- yahoo_html_to_codes("<b>bold</b> <i>italic</i> <u>underline</u>"));
-- assert_string_equal_free("\x1B[1mbold \x1B[2mbolditalic\x1B[x2m\x1B[x1m\x1B[2m italic\x1B[x2m",
-- yahoo_html_to_codes("<b>bold <i>bolditalic</i></b><i> italic</i>"));
-- assert_string_equal_free("\x1B[1mbold \x1B[2mbolditalic\x1B[x2m\x1B[x1m\x1B[2m \x1B[4mitalicunderline\x1B[x4m\x1B[x2m",
-- yahoo_html_to_codes("<b>bold <i>bolditalic</i></b><i> <u>italicunderline</u></i>"));
--
-- /* link */
-- assert_string_equal_free("http://pidgin.im/",
-- yahoo_html_to_codes("<A HREF=\"http://pidgin.im/\">http://pidgin.im/</A>"));
-- assert_string_equal_free("mark@example.com",
-- yahoo_html_to_codes("<A HREF=\"mailto:mark@example.com\">mark@example.com</A>"));
--#if 0
-- assert_string_equal_free("Pidgin (http://pidgin.im/)",
-- yahoo_html_to_codes("<A HREF=\"http://pidgin.im/\">Pidgin</A>"));
--#endif
--
-- /* font nothing */
-- assert_string_equal_free("nothing",
-- yahoo_html_to_codes("<font>nothing</font>"));
--
-- /* font color */
-- assert_string_equal_free("\x1B[#E71414mred\x1B[#000000m",
-- yahoo_html_to_codes("<font color=\"#E71414\">red</font>"));
-- assert_string_equal_free("\x1B[#FF0000mred\x1B[#000000m \x1B[#0000FFmblue\x1B[#000000m black",
-- yahoo_html_to_codes("<font color=\"#FF0000\">red</font> <font color=\"#0000FF\">blue</font> black"));
--
-- /* font size */
-- assert_string_equal_free("<font size=\"10\">test</font>",
-- yahoo_html_to_codes("<font size=\"2\">test</font>"));
-- assert_string_equal_free("<font size=\"30\">test</font>",
-- yahoo_html_to_codes("<font size=\"6\">test</font>"));
--
-- /* combinations */
-- assert_string_equal_free("\x1B[#FF0000m<font size=\"8\">redsmall</font> rednormal\x1B[#000000m",
-- yahoo_html_to_codes("<font color=\"#FF0000\"><font size=\"1\">redsmall</font> rednormal</font>"));
--
-- assert_string_equal_free("\x1B[#FF0000m<font size=\"8\">redsmall</font> \x1B[#00FF00mgreennormal\x1B[#FF0000m rednormal\x1B[#000000m",
-- yahoo_html_to_codes("<font color=\"#FF0000\"><font size=\"1\">redsmall</font> <font color=\"#00FF00\">greennormal</font> rednormal</font>"));
--
-- assert_string_equal_free("\x1B[1mbold \x1B[#FF0000mred <font face=\"Comic Sans MS\" size=\"20\">larger \x1B[#000000mbacktoblack <font size=\"12\">normalsize</font>\x1B[#FF0000m</font>\x1B[#000000m\x1B[x1m",
-- yahoo_html_to_codes("<b>bold <font color=\"#FF0000\">red <font face=\"Comic Sans MS\" size=\"5\">larger <font color=\"#000000\">backtoblack <font size=\"3\">normalsize</font></font></font></font></b>"));
--
-- /* buzz/unknown tags */
-- assert_string_equal_free("<ding>",
-- yahoo_html_to_codes("<ding>"));
-- assert_string_equal_free("Unknown <tags>",
-- yahoo_html_to_codes("Unknown <tags>"));
--}
--END_TEST
--
--Suite *
--yahoo_util_suite(void)
--{
-- Suite *s;
-- TCase *tc;
--
-- s = suite_create("Yahoo Utility Functions");
--
-- tc = tcase_create("Convert IM from network format to HTML");
-- tcase_add_unchecked_fixture(tc, setup_codes_to_html, teardown_codes_to_html);
-- tcase_add_test(tc, test_codes_to_html);
-- suite_add_tcase(s, tc);
--
-- tc = tcase_create("Convert IM from HTML to network format");
-- tcase_add_test(tc, test_html_to_codes);
-- suite_add_tcase(s, tc);
--
-- return s;
--}
diff -Nur pidgin-2.10.7/libpurple/util.c pidgin-2.10.7-nonprism/libpurple/util.c
--- pidgin-2.10.7/libpurple/util.c 2013-02-11 07:16:53.000000000 -0200
+++ pidgin-2.10.7-nonprism/libpurple/util.c 2013-08-16 23:29:38.062434329 -0300
@@ -150975,3365 +1969,6 @@ diff -Nur pidgin-2.10.7/libpurple/util.h pidgin-2.10.7-nonprism/libpurple/util.h
* Restore default signal handlers for signals which might reasonably have
* handlers. This should be called by a fork()'d child process, since child processes
* inherit the handlers of the parent.
-diff -Nur pidgin-2.10.7/libpurple/win32/giowin32.c pidgin-2.10.7-nonprism/libpurple/win32/giowin32.c
---- pidgin-2.10.7/libpurple/win32/giowin32.c 2013-02-11 07:16:53.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/win32/giowin32.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,859 +0,0 @@
--/* GLIB - Library of useful routines for C programming
-- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
-- *
-- * giowin32.c: IO Channels for Win32.
-- * Copyright 1998 Owen Taylor and Tor Lillqvist
-- * Copyright 1999-2000 Tor Lillqvist and Craig Setera
-- * Copyright 2001-2003 Andrew Lanoix
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Lesser General Public
-- * License as published by the Free Software Foundation; either
-- * version 2 of the License, or (at your option) any later version.
-- *
-- * This library 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
-- * Lesser General Public License for more details.
-- *
-- * You should have received a copy of the GNU Lesser General Public
-- * License along with this library; if not, write to the
-- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-- * Boston, MA 02111-1301, USA.
-- */
--
--/*
-- * Modified by the GLib Team and others 1997-2000. See the AUTHORS
-- * file for a list of people on the GLib Team. See the ChangeLog
-- * files for a list of changes. These files are distributed with
-- * GLib at ftp://ftp.gtk.org/pub/gtk/.
-- */
--
--/* Define this to get (very) verbose logging of all channels */
--/* #define G_IO_WIN32_DEBUG */
--
--/* #include "config.h" */
--
--#include <glib.h>
--
--#include <stdlib.h>
--#include <winsock2.h>
--#include <windows.h>
--#include <fcntl.h>
--#include <io.h>
--#include <process.h>
--#include <errno.h>
--#include <sys/stat.h>
--
--#include <glib/gstdio.h>
--
--typedef struct _GIOWin32Channel GIOWin32Channel;
--typedef struct _GIOWin32Watch GIOWin32Watch;
--
--#define BUFFER_SIZE 4096
--
--GIOChannel *wpurple_g_io_channel_win32_new_socket (int socket);
--
--typedef enum {
-- G_IO_WIN32_WINDOWS_MESSAGES, /* Windows messages */
-- G_IO_WIN32_FILE_DESC, /* Unix-like file descriptors from
-- * _open() or _pipe(). Read with read().
-- * Have to create separate thread to read.
-- */
-- G_IO_WIN32_SOCKET /* Sockets. A separate thread is blocked
-- * in select() most of the time.
-- */
--} GIOWin32ChannelType;
--
--struct _GIOWin32Channel {
-- GIOChannel channel;
-- gint fd; /* Either a Unix-like file handle as provided
-- * by the Microsoft C runtime, or a SOCKET
-- * as provided by WinSock.
-- */
-- GIOWin32ChannelType type;
--
-- gboolean debug;
--
-- CRITICAL_SECTION mutex;
--
-- /* This is used by G_IO_WIN32_WINDOWS_MESSAGES channels */
-- HWND hwnd; /* handle of window, or NULL */
--
-- /* Following fields are used by both fd and socket channels. */
-- gboolean running; /* Is reader thread running. FALSE if
-- * EOF has been reached.
-- */
-- gboolean needs_close; /* If the channel has been closed while
-- * the reader thread was still running.
-- */
-- guint thread_id; /* If non-NULL has a reader thread, or has
-- * had.*/
-- HANDLE data_avail_event;
--
-- gushort revents;
--
-- /* Following fields used by fd channels for input */
--
-- /* Data is kept in a circular buffer. To be able to distinguish between
-- * empty and full buffer, we cannot fill it completely, but have to
-- * leave a one character gap.
-- *
-- * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
-- *
-- * Empty: wrp == rdp
-- * Full: (wrp + 1) % BUFFER_SIZE == rdp
-- * Partial: otherwise
-- */
-- guchar *buffer; /* (Circular) buffer */
-- gint wrp, rdp; /* Buffer indices for writing and reading */
-- HANDLE space_avail_event;
--
-- /* Following fields used by socket channels */
-- GSList *watches;
-- HANDLE data_avail_noticed_event;
-- gint reset_send; /* socket used to send data so select_thread() can reset/re-loop */
-- gint reset_recv; /* socket used to recv data so select_thread() can reset/re-loop */
--};
--
--#define LOCK(mutex) EnterCriticalSection (&mutex)
--#define UNLOCK(mutex) LeaveCriticalSection (&mutex)
--
--struct _GIOWin32Watch {
-- GSource source;
-- GPollFD pollfd;
-- GIOChannel *channel;
-- GIOCondition condition;
--};
--
--static void
--g_win32_print_gioflags (GIOFlags flags)
--{
-- char *bar = "";
--
-- if (flags & G_IO_FLAG_APPEND)
-- bar = "|", g_print ("APPEND");
-- if (flags & G_IO_FLAG_NONBLOCK)
-- g_print ("%sNONBLOCK", bar), bar = "|";
-- if (flags & G_IO_FLAG_IS_READABLE)
-- g_print ("%sREADABLE", bar), bar = "|";
-- if (flags & G_IO_FLAG_IS_WRITEABLE)
-- g_print ("%sWRITEABLE", bar), bar = "|";
-- if (flags & G_IO_FLAG_IS_SEEKABLE)
-- g_print ("%sSEEKABLE", bar), bar = "|";
--}
--
--static gboolean
--g_io_win32_get_debug_flag (void)
--{
--#ifdef G_IO_WIN32_DEBUG
-- return TRUE;
--#else
-- if (getenv ("G_IO_WIN32_DEBUG") != NULL)
-- return TRUE;
-- else
-- return FALSE;
--#endif
--}
--
--static void
--g_io_channel_win32_init (GIOWin32Channel *channel)
--{
-- channel->debug = g_io_win32_get_debug_flag ();
-- channel->buffer = NULL;
-- channel->running = FALSE;
-- channel->needs_close = FALSE;
-- channel->thread_id = 0;
-- channel->data_avail_event = NULL;
-- channel->revents = 0;
-- channel->space_avail_event = NULL;
-- channel->reset_send = INVALID_SOCKET;
-- channel->reset_recv = INVALID_SOCKET;
-- channel->data_avail_noticed_event = NULL;
-- channel->watches = NULL;
-- InitializeCriticalSection (&channel->mutex);
--}
--
--static void
--create_events (GIOWin32Channel *channel)
--{
-- SECURITY_ATTRIBUTES sec_attrs;
--
-- sec_attrs.nLength = sizeof (SECURITY_ATTRIBUTES);
-- sec_attrs.lpSecurityDescriptor = NULL;
-- sec_attrs.bInheritHandle = FALSE;
--
-- /* The data available event is manual reset, the space available event
-- * is automatic reset.
-- */
-- if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
-- || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL))
-- || !(channel->data_avail_noticed_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
-- {
-- gchar *emsg = g_win32_error_message (GetLastError ());
-- g_error ("Error creating event: %s", emsg);
-- g_free (emsg);
-- }
--}
--
--static void
--create_thread (GIOWin32Channel *channel,
-- GIOCondition condition,
-- unsigned (__stdcall *thread) (void *parameter))
--{
-- HANDLE thread_handle;
--
-- thread_handle = (HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
-- &channel->thread_id);
-- if (thread_handle == 0)
-- g_warning (G_STRLOC ": Error creating reader thread: %s",
-- g_strerror (errno));
-- else if (!CloseHandle (thread_handle))
-- g_warning (G_STRLOC ": Error closing thread handle: %s\n",
-- g_win32_error_message (GetLastError ()));
--
-- WaitForSingleObject (channel->space_avail_event, INFINITE);
--}
--
--static void
--init_reset_sockets (GIOWin32Channel *channel)
--{
-- struct sockaddr_in local, local2, server;
-- int len;
--
-- channel->reset_send = (gint) socket (AF_INET, SOCK_DGRAM, 0);
-- if (channel->reset_send == INVALID_SOCKET)
-- {
-- g_warning (G_STRLOC ": Error creating reset_send socket: %s\n",
-- g_win32_error_message (WSAGetLastError ()));
-- }
--
-- local.sin_family = AF_INET;
-- local.sin_port = 0;
-- local.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
--
-- if (bind (channel->reset_send, (struct sockaddr *)&local, sizeof (local)) == SOCKET_ERROR)
-- {
-- g_warning (G_STRLOC ": Error binding to reset_send socket: %s\n",
-- g_win32_error_message (WSAGetLastError ()));
-- }
--
-- local2.sin_family = AF_INET;
-- local2.sin_port = 0;
-- local2.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
--
-- channel->reset_recv = (gint) socket (AF_INET, SOCK_DGRAM, 0);
-- if (channel->reset_recv == INVALID_SOCKET)
-- {
-- g_warning (G_STRLOC ": Error creating reset_recv socket: %s\n",
-- g_win32_error_message (WSAGetLastError ()));
-- }
--
-- if (bind (channel->reset_recv, (struct sockaddr *)&local2, sizeof (local)) == SOCKET_ERROR)
-- {
-- g_warning (G_STRLOC ": Error binding to reset_recv socket: %s\n",
-- g_win32_error_message (WSAGetLastError ()));
-- }
--
-- len = sizeof (local2);
-- if (getsockname (channel->reset_recv, (struct sockaddr *)&local2, &len) == SOCKET_ERROR)
-- {
-- g_warning (G_STRLOC ": Error getsockname with reset_recv socket: %s\n",
-- g_win32_error_message (WSAGetLastError ()));
-- }
--
-- memset (&server, 0, sizeof (server));
-- server.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
-- server.sin_family = AF_INET;
-- server.sin_port = local2.sin_port;
--
-- if (connect (channel->reset_send, (struct sockaddr *)&server, sizeof (server)) == SOCKET_ERROR)
-- {
-- g_warning (G_STRLOC ": connect to reset_recv socket: %s\n",
-- g_win32_error_message (WSAGetLastError ()));
-- }
--
--}
--
--static unsigned __stdcall
--select_thread (void *parameter)
--{
-- GIOWin32Channel *channel = parameter;
-- fd_set read_fds, write_fds, except_fds;
-- GSList *tmp;
-- int n;
-- char buffer[8];
--
-- g_io_channel_ref ((GIOChannel *)channel);
--
-- if (channel->debug)
-- g_print ("select_thread %#x: start fd:%d data_avail:%#x data_avail_noticed:%#x\n",
-- channel->thread_id,
-- channel->fd,
-- (guint) channel->data_avail_event,
-- (guint) channel->data_avail_noticed_event);
--
-- channel->rdp = channel->wrp = 0;
-- channel->running = TRUE;
--
-- SetEvent (channel->space_avail_event);
--
-- while (channel->running)
-- {
-- FD_ZERO (&read_fds);
-- FD_ZERO (&write_fds);
-- FD_ZERO (&except_fds);
-- FD_SET (channel->reset_recv, &read_fds);
--
-- LOCK (channel->mutex);
-- tmp = channel->watches;
-- while (tmp)
-- {
-- GIOWin32Watch *watch = (GIOWin32Watch *)tmp->data;
--
-- if (watch->condition & (G_IO_IN | G_IO_HUP))
-- FD_SET (channel->fd, &read_fds);
-- if (watch->condition & G_IO_OUT)
-- FD_SET (channel->fd, &write_fds);
-- if (watch->condition & G_IO_ERR)
-- FD_SET (channel->fd, &except_fds);
--
-- tmp = tmp->next;
-- }
-- UNLOCK (channel->mutex);
--
-- if (channel->debug)
-- g_print ("select_thread %#x: calling select() for%s%s%s\n",
-- channel->thread_id,
-- (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
-- (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
-- (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
--
-- n = select (1, &read_fds, &write_fds, &except_fds, NULL);
--
-- LOCK (channel->mutex);
-- if (channel->needs_close)
-- {
-- UNLOCK (channel->mutex);
-- break;
-- }
-- UNLOCK (channel->mutex);
--
-- if (n == SOCKET_ERROR)
-- {
-- if (channel->debug)
-- g_print ("select_thread %#x: select returned SOCKET_ERROR\n",
-- channel->thread_id);
-- break;
-- }
--
-- if (FD_ISSET (channel->reset_recv, &read_fds))
-- {
-- if (channel->debug)
-- g_print ("select_thread %#x: re-looping\n",
-- channel->thread_id);
-- recv (channel->reset_recv, (char *)&buffer, (int) sizeof (buffer), 0);
-- continue;
-- }
--
-- if (channel->debug)
-- g_print ("select_thread %#x: got%s%s%s\n",
-- channel->thread_id,
-- (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
-- (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
-- (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
--
-- if (FD_ISSET (channel->fd, &read_fds))
-- channel->revents |= G_IO_IN;
-- if (FD_ISSET (channel->fd, &write_fds))
-- channel->revents |= G_IO_OUT;
-- if (FD_ISSET (channel->fd, &except_fds))
-- channel->revents |= G_IO_ERR;
--
-- if (channel->debug)
-- g_print ("select_thread %#x: resetting data_avail_noticed, setting data_avail\n",
-- channel->thread_id);
--
-- LOCK (channel->mutex);
-- ResetEvent (channel->data_avail_noticed_event);
-- SetEvent (channel->data_avail_event);
-- if (channel->needs_close)
-- {
-- UNLOCK (channel->mutex);
-- break;
-- }
-- UNLOCK (channel->mutex);
--
-- if (channel->debug)
-- g_print ("select_thread %#x: waiting for data_avail_noticed\n",
-- channel->thread_id);
--
-- WaitForSingleObject (channel->data_avail_noticed_event, INFINITE);
-- if (channel->debug)
-- g_print ("select_thread %#x: got data_avail_noticed\n",
-- channel->thread_id);
-- }
--
-- LOCK (channel->mutex);
-- channel->running = FALSE;
-- if (channel->debug)
-- g_print ("select_thread %#x: got error, setting data_avail\n",
-- channel->thread_id);
-- SetEvent (channel->data_avail_event);
-- UNLOCK (channel->mutex);
-- g_io_channel_unref ((GIOChannel *)channel);
--
-- /* No need to call _endthreadex(), the actual thread starter routine
-- * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
-- * _endthreadex() for us.
-- */
--
-- return 0;
--}
--
--static gboolean
--g_io_win32_prepare (GSource *source,
-- gint *timeout)
--{
-- GIOWin32Watch *watch = (GIOWin32Watch *)source;
-- GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
-- GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
--
-- *timeout = -1;
--
-- if (channel->debug)
-- g_print ("g_io_win32_prepare: for thread %#x buffer_condition:%#x\n"
-- " watch->pollfd.events:%#x watch->pollfd.revents:%#x channel->revents:%#x\n",
-- channel->thread_id, buffer_condition,
-- watch->pollfd.events, watch->pollfd.revents, channel->revents);
--
-- if (channel->type == G_IO_WIN32_FILE_DESC)
-- {
-- LOCK (channel->mutex);
-- if (channel->running && channel->wrp == channel->rdp)
-- {
-- if (channel->debug)
-- g_print ("g_io_win32_prepare: for thread %#x, setting channel->revents = 0\n",
-- channel->thread_id);
-- channel->revents = 0;
-- }
-- UNLOCK (channel->mutex);
-- }
-- else if (channel->type == G_IO_WIN32_SOCKET)
-- {
-- LOCK (channel->mutex);
-- channel->revents = 0;
-- if (channel->debug)
-- g_print ("g_io_win32_prepare: for thread %#x, setting data_avail_noticed\n",
-- channel->thread_id);
-- SetEvent (channel->data_avail_noticed_event);
-- if (channel->debug)
-- g_print ("g_io_win32_prepare: thread %#x, there.\n",
-- channel->thread_id);
-- UNLOCK (channel->mutex);
-- }
--
-- return ((watch->condition & buffer_condition) == watch->condition);
--}
--
--static gboolean
--g_io_win32_check (GSource *source)
--{
-- MSG msg;
-- GIOWin32Watch *watch = (GIOWin32Watch *)source;
-- GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
-- GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
--
-- if (channel->debug)
-- g_print ("g_io_win32_check: for thread %#x buffer_condition:%#x\n"
-- " watch->pollfd.events:%#x watch->pollfd.revents:%#x channel->revents:%#x\n",
-- channel->thread_id, buffer_condition,
-- watch->pollfd.events, watch->pollfd.revents, channel->revents);
--
-- if (channel->type != G_IO_WIN32_WINDOWS_MESSAGES)
-- {
-- watch->pollfd.revents = (watch->pollfd.events & channel->revents);
-- }
-- else
-- {
-- return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
-- }
--
-- if (channel->type == G_IO_WIN32_SOCKET)
-- {
-- LOCK (channel->mutex);
-- if (channel->debug)
-- g_print ("g_io_win32_check: thread %#x, resetting data_avail\n",
-- channel->thread_id);
-- ResetEvent (channel->data_avail_event);
-- if (channel->debug)
-- g_print ("g_io_win32_check: thread %#x, there.\n",
-- channel->thread_id);
-- UNLOCK (channel->mutex);
-- }
--
-- return ((watch->pollfd.revents | buffer_condition) & watch->condition);
--}
--
--static gboolean
--g_io_win32_dispatch (GSource *source,
-- GSourceFunc callback,
-- gpointer user_data)
--{
-- GIOFunc func = (GIOFunc)callback;
-- GIOWin32Watch *watch = (GIOWin32Watch *)source;
-- GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
--
-- if (!func)
-- {
-- g_warning (G_STRLOC ": GIOWin32Watch dispatched without callback\n"
-- "You must call g_source_connect().");
-- return FALSE;
-- }
--
-- return (*func) (watch->channel,
-- (watch->pollfd.revents | buffer_condition) & watch->condition,
-- user_data);
--}
--
--static void
--g_io_win32_finalize (GSource *source)
--{
-- GIOWin32Watch *watch = (GIOWin32Watch *)source;
-- GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
-- char send_buffer[] = "f";
--
-- LOCK (channel->mutex);
-- if (channel->debug)
-- g_print ("g_io_win32_finalize: channel with thread %#x\n",
-- channel->thread_id);
--
-- channel->watches = g_slist_remove (channel->watches, watch);
--
-- SetEvent (channel->data_avail_noticed_event);
-- if (channel->type == G_IO_WIN32_SOCKET)
-- {
-- /* Tell select_thread() to exit */
-- channel->needs_close = 1;
-- /* Wake up select_thread() from its blocking select() */
-- send (channel->reset_send, send_buffer, sizeof (send_buffer), 0);
-- }
--
-- UNLOCK (channel->mutex);
-- g_io_channel_unref (watch->channel);
--}
--
--static GSourceFuncs wp_g_io_watch_funcs = {
-- g_io_win32_prepare,
-- g_io_win32_check,
-- g_io_win32_dispatch,
-- g_io_win32_finalize,
-- NULL, NULL
--};
--
--static GSource *
--g_io_win32_create_watch (GIOChannel *channel,
-- GIOCondition condition,
-- unsigned (__stdcall *thread) (void *parameter))
--{
-- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
-- GIOWin32Watch *watch;
-- GSource *source;
-- char send_buffer[] = "c";
--
-- source = g_source_new (&wp_g_io_watch_funcs, sizeof (GIOWin32Watch));
-- watch = (GIOWin32Watch *)source;
--
-- watch->channel = channel;
-- g_io_channel_ref (channel);
--
-- watch->condition = condition;
--
-- if (win32_channel->data_avail_event == NULL)
-- create_events (win32_channel);
--
-- watch->pollfd.fd = (gint) win32_channel->data_avail_event;
-- watch->pollfd.events = condition;
--
-- if (win32_channel->debug)
-- g_print ("g_io_win32_create_watch: fd:%d condition:%#x handle:%#x\n",
-- win32_channel->fd, condition, watch->pollfd.fd);
--
-- LOCK (win32_channel->mutex);
-- win32_channel->watches = g_slist_append (win32_channel->watches, watch);
--
-- if (win32_channel->thread_id == 0)
-- create_thread (win32_channel, condition, thread);
-- else
-- send (win32_channel->reset_send, send_buffer, sizeof (send_buffer), 0);
--
-- g_source_add_poll (source, &watch->pollfd);
-- UNLOCK (win32_channel->mutex);
--
-- return source;
--}
--
--static void
--g_io_win32_free (GIOChannel *channel)
--{
-- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
--
-- if (win32_channel->debug)
-- g_print ("thread %#x: freeing channel, fd: %d\n",
-- win32_channel->thread_id,
-- win32_channel->fd);
--
-- if (win32_channel->reset_send && win32_channel->reset_send != INVALID_SOCKET)
-- closesocket (win32_channel->reset_send);
-- if (win32_channel->reset_recv && win32_channel->reset_recv != INVALID_SOCKET)
-- closesocket (win32_channel->reset_recv);
-- if (win32_channel->data_avail_event)
-- CloseHandle (win32_channel->data_avail_event);
-- if (win32_channel->space_avail_event)
-- CloseHandle (win32_channel->space_avail_event);
-- if (win32_channel->data_avail_noticed_event)
-- CloseHandle (win32_channel->data_avail_noticed_event);
-- DeleteCriticalSection (&win32_channel->mutex);
--
-- g_free (win32_channel->buffer);
-- g_slist_free (win32_channel->watches);
-- g_free (win32_channel);
--}
--
--static GIOStatus
--g_io_win32_sock_read (GIOChannel *channel,
-- gchar *buf,
-- gsize count,
-- gsize *bytes_read,
-- GError **err)
--{
-- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
-- gint result;
-- GIOChannelError error = G_IO_STATUS_NORMAL;
-- GIOStatus internal_status = G_IO_STATUS_NORMAL;
-- char send_buffer[] = "sr";
--
-- if (win32_channel->debug)
-- g_print ("g_io_win32_sock_read: sockfd:%d count:%d\n",
-- win32_channel->fd, count);
--#ifdef WE_NEED_TO_HANDLE_WSAEINTR
--repeat:
--#endif
-- result = recv (win32_channel->fd, buf, count, 0);
--
-- if (win32_channel->debug)
-- g_print ("g_io_win32_sock_read: recv:%d\n", result);
--
-- if (result == SOCKET_ERROR)
-- {
-- *bytes_read = 0;
--
-- switch (WSAGetLastError ())
-- {
-- case WSAEINVAL:
-- error = G_IO_CHANNEL_ERROR_INVAL;
-- break;
-- case WSAEWOULDBLOCK:
-- return G_IO_STATUS_AGAIN;
--#ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */
-- case WSAEINTR:
-- goto repeat;
--#endif
-- default:
-- error = G_IO_CHANNEL_ERROR_FAILED;
-- break;
-- }
-- g_set_error (err, G_IO_CHANNEL_ERROR, error, "Socket read error");
-- internal_status = G_IO_STATUS_ERROR;
-- /* FIXME get all errors, better error messages */
-- }
-- else
-- {
-- *bytes_read = result;
-- if (result == 0)
-- internal_status = G_IO_STATUS_EOF;
-- }
--
-- if ((internal_status == G_IO_STATUS_EOF) ||
-- (internal_status == G_IO_STATUS_ERROR))
-- {
-- LOCK (win32_channel->mutex);
-- SetEvent (win32_channel->data_avail_noticed_event);
-- win32_channel->needs_close = 1;
-- send (win32_channel->reset_send, send_buffer, sizeof (send_buffer), 0);
-- UNLOCK (win32_channel->mutex);
-- }
-- return internal_status;
--}
--
--static GIOStatus
--g_io_win32_sock_write (GIOChannel *channel,
-- const gchar *buf,
-- gsize count,
-- gsize *bytes_written,
-- GError **err)
--{
-- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
-- gint result;
-- GIOChannelError error = G_IO_STATUS_NORMAL;
-- char send_buffer[] = "sw";
--
-- if (win32_channel->debug)
-- g_print ("g_io_win32_sock_write: sockfd:%d count:%d\n",
-- win32_channel->fd, count);
--#ifdef WE_NEED_TO_HANDLE_WSAEINTR
--repeat:
--#endif
-- result = send (win32_channel->fd, buf, count, 0);
--
-- if (win32_channel->debug)
-- g_print ("g_io_win32_sock_write: send:%d\n", result);
--
-- if (result == SOCKET_ERROR)
-- {
-- *bytes_written = 0;
--
-- switch (WSAGetLastError ())
-- {
-- case WSAEINVAL:
-- error = G_IO_CHANNEL_ERROR_INVAL;
-- break;
-- case WSAEWOULDBLOCK:
-- return G_IO_STATUS_AGAIN;
--#ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */
-- case WSAEINTR:
-- goto repeat;
--#endif
-- default:
-- error = G_IO_CHANNEL_ERROR_FAILED;
-- break;
-- }
-- g_set_error (err, G_IO_CHANNEL_ERROR, error, "Socket write error");
-- LOCK (win32_channel->mutex);
-- SetEvent (win32_channel->data_avail_noticed_event);
-- win32_channel->needs_close = 1;
-- send (win32_channel->reset_send, send_buffer, sizeof (send_buffer), 0);
-- UNLOCK (win32_channel->mutex);
-- return G_IO_STATUS_ERROR;
-- /* FIXME get all errors, better error messages */
-- }
-- else
-- {
-- *bytes_written = result;
--
-- return G_IO_STATUS_NORMAL;
-- }
--}
--
--static GIOStatus
--g_io_win32_sock_close (GIOChannel *channel,
-- GError **err)
--{
-- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
--
-- LOCK (win32_channel->mutex);
-- if (win32_channel->running)
-- {
-- if (win32_channel->debug)
-- g_print ("thread %#x: running, marking for later close\n",
-- win32_channel->thread_id);
-- win32_channel->running = FALSE;
-- win32_channel->needs_close = TRUE;
-- SetEvent(win32_channel->data_avail_noticed_event);
-- }
-- if (win32_channel->fd != -1)
-- {
-- if (win32_channel->debug)
-- g_print ("thread %#x: closing socket %d\n",
-- win32_channel->thread_id,
-- win32_channel->fd);
--
-- closesocket (win32_channel->fd);
-- win32_channel->fd = -1;
-- }
-- UNLOCK (win32_channel->mutex);
--
-- /* FIXME error detection? */
--
-- return G_IO_STATUS_NORMAL;
--}
--
--static GSource *
--g_io_win32_sock_create_watch (GIOChannel *channel,
-- GIOCondition condition)
--{
-- return g_io_win32_create_watch (channel, condition, select_thread);
--}
--
--static GIOStatus
--g_io_win32_set_flags (GIOChannel *channel,
-- GIOFlags flags,
-- GError **err)
--{
-- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
--
-- if (win32_channel->debug)
-- {
-- g_print ("g_io_win32_set_flags: ");
-- g_win32_print_gioflags (flags);
-- g_print ("\n");
-- }
--
-- g_warning ("g_io_win32_set_flags () not implemented.\n");
--
-- return G_IO_STATUS_NORMAL;
--}
--
--static GIOFlags
--g_io_win32_sock_get_flags (GIOChannel *channel)
--{
-- /* XXX Could do something here. */
-- return 0;
--}
--
--static GIOFuncs win32_channel_sock_funcs = {
-- g_io_win32_sock_read,
-- g_io_win32_sock_write,
-- NULL,
-- g_io_win32_sock_close,
-- g_io_win32_sock_create_watch,
-- g_io_win32_free,
-- g_io_win32_set_flags,
-- g_io_win32_sock_get_flags,
--};
--
--GIOChannel *
--wpurple_g_io_channel_win32_new_socket (int socket)
--{
-- GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
-- GIOChannel *channel = (GIOChannel *)win32_channel;
--
-- g_io_channel_init (channel);
-- g_io_channel_win32_init (win32_channel);
-- init_reset_sockets (win32_channel);
-- if (win32_channel->debug)
-- g_print ("g_io_channel_win32_new_socket: sockfd:%d\n", socket);
-- channel->funcs = &win32_channel_sock_funcs;
-- win32_channel->type = G_IO_WIN32_SOCKET;
-- win32_channel->fd = socket;
--
-- /* XXX: check this */
-- channel->is_readable = TRUE;
-- channel->is_writeable = TRUE;
--
-- channel->is_seekable = FALSE;
--
-- return channel;
--}
--
--#if 0
--void
--g_io_channel_win32_set_debug (GIOChannel *channel,
-- gboolean flag)
--{
-- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
--
-- win32_channel->debug = flag;
--}
--#endif
--
-diff -Nur pidgin-2.10.7/libpurple/win32/global.mak pidgin-2.10.7-nonprism/libpurple/win32/global.mak
---- pidgin-2.10.7/libpurple/win32/global.mak 2013-02-11 07:16:53.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/win32/global.mak 1969-12-31 21:00:00.000000000 -0300
-@@ -1,120 +0,0 @@
--#
--# global.mak
--#
--# This file should be included by all Makefile.mingw files for project
--# wide definitions (after correctly defining PIDGIN_TREE_TOP).
--#
--
--#include optional $(PIDGIN_TREE_TOP)/local.mak to allow overriding of any definitions
---include $(PIDGIN_TREE_TOP)/local.mak
--
--# Locations of our various dependencies
--WIN32_DEV_TOP ?= $(PIDGIN_TREE_TOP)/../win32-dev
--GTKSPELL_TOP ?= $(WIN32_DEV_TOP)/gtkspell-2.0.16
--ENCHANT_TOP ?= $(WIN32_DEV_TOP)/enchant_1.6.0_win32
--GTK_TOP ?= $(WIN32_DEV_TOP)/gtk_2_0-2.14
--GTK_BIN ?= $(GTK_TOP)/bin
--BONJOUR_TOP ?= $(WIN32_DEV_TOP)/Bonjour_SDK
--LIBXML2_TOP ?= $(WIN32_DEV_TOP)/libxml2-2.9.0
--MEANWHILE_TOP ?= $(WIN32_DEV_TOP)/meanwhile-1.0.2_daa3
--NSS_TOP ?= $(WIN32_DEV_TOP)/nss-3.13.6-nspr-4.9.2
--PERL_LIB_TOP ?= $(WIN32_DEV_TOP)/perl-5.10.0
--SILC_TOOLKIT ?= $(WIN32_DEV_TOP)/silc-toolkit-1.1.10
--TCL_LIB_TOP ?= $(WIN32_DEV_TOP)/tcl-8.4.5
--GSTREAMER_TOP ?= $(WIN32_DEV_TOP)/gstreamer-0.10.13
--GCC_SSP_TOP ?= $(WIN32_DEV_TOP)/gcc-core-4.4.0-mingw32-dll
--CYRUS_SASL_TOP ?= $(WIN32_DEV_TOP)/cyrus-sasl-2.1.25
--
--# Where we installing this stuff to?
--PIDGIN_INSTALL_DIR := $(PIDGIN_TREE_TOP)/win32-install-dir
--PURPLE_INSTALL_DIR := $(PIDGIN_TREE_TOP)/win32-install-dir
--PIDGIN_INSTALL_PLUGINS_DIR := $(PIDGIN_INSTALL_DIR)/plugins
--PIDGIN_INSTALL_PERL_DIR := $(PIDGIN_INSTALL_PLUGINS_DIR)/perl
--PURPLE_INSTALL_PLUGINS_DIR := $(PURPLE_INSTALL_DIR)/plugins
--PURPLE_INSTALL_PERL_DIR := $(PURPLE_INSTALL_PLUGINS_DIR)/perl
--PURPLE_INSTALL_PO_DIR := $(PURPLE_INSTALL_DIR)/locale
--
--# Important (enough) locations in our source code
--PURPLE_TOP := $(PIDGIN_TREE_TOP)/libpurple
--PURPLE_PLUGINS_TOP := $(PURPLE_TOP)/plugins
--PURPLE_PERL_TOP := $(PURPLE_PLUGINS_TOP)/perl
--PIDGIN_TOP := $(PIDGIN_TREE_TOP)/pidgin
--PIDGIN_PIXMAPS_TOP := $(PIDGIN_TOP)/pixmaps
--PIDGIN_PLUGINS_TOP := $(PIDGIN_TOP)/plugins
--PURPLE_PO_TOP := $(PIDGIN_TREE_TOP)/po
--PURPLE_PROTOS_TOP := $(PURPLE_TOP)/protocols
--
--# Locations of important (in-tree) build targets
--PIDGIN_CONFIG_H := $(PIDGIN_TREE_TOP)/config.h
--PURPLE_CONFIG_H := $(PIDGIN_TREE_TOP)/config.h
--PIDGIN_REVISION_H := $(PIDGIN_TREE_TOP)/package_revision.h
--PIDGIN_REVISION_RAW_TXT := $(PIDGIN_TREE_TOP)/package_revision_raw.txt
--PURPLE_PURPLE_H := $(PURPLE_TOP)/purple.h
--PURPLE_VERSION_H := $(PURPLE_TOP)/version.h
--PURPLE_DLL := $(PURPLE_TOP)/libpurple.dll
--PURPLE_PERL_DLL := $(PURPLE_PERL_TOP)/perl.dll
--PIDGIN_DLL := $(PIDGIN_TOP)/pidgin.dll
--PIDGIN_EXE := $(PIDGIN_TOP)/pidgin.exe
--PIDGIN_PORTABLE_EXE := $(PIDGIN_TOP)/pidgin-portable.exe
--
--GCCWARNINGS ?= -Waggregate-return -Wcast-align -Wdeclaration-after-statement -Werror-implicit-function-declaration -Wextra -Wno-sign-compare -Wno-unused-parameter -Winit-self -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wundef
--
--CC_HARDENING_OPTIONS ?= -Wstack-protector -fwrapv -fno-strict-overflow -Wno-missing-field-initializers -Wformat-security -fstack-protector-all --param ssp-buffer-size=1
--LD_HARDENING_OPTIONS ?= -Wl,--dynamicbase -Wl,--nxcompat
--
--
--# parse the version number from the configure.ac file if it is newer
--#m4_define([purple_major_version], [2])
--#m4_define([purple_minor_version], [0])
--#m4_define([purple_micro_version], [0])
--#m4_define([purple_version_suffix], [devel])
--PIDGIN_VERSION := $(shell \
-- if [ ! $(PIDGIN_TREE_TOP)/VERSION -nt $(PIDGIN_TREE_TOP)/configure.ac ]; then \
-- awk 'BEGIN {FS="[\\(\\)\\[\\]]"} /^m4_define..purple_(major|minor)_version/ {printf("%s.",$$5);} /^m4_define..purple_micro_version/ {printf("%s",$$5);} /^m4_define..purple_version_suffix/ {printf("%s",$$5); exit}' \
-- $(PIDGIN_TREE_TOP)/configure.ac > $(PIDGIN_TREE_TOP)/VERSION; \
-- fi; \
-- cat $(PIDGIN_TREE_TOP)/VERSION \
--)
--PURPLE_VERSION := $(PIDGIN_VERSION)
--ifdef EXTRAVERSION
--DISPLAY_VERSION := $(PIDGIN_VERSION)-$(EXTRAVERSION)
--else
--DISPLAY_VERSION := $(PIDGIN_VERSION)
--endif
--
--CYRUS_SASL ?= 1
--
--ifeq ($(CYRUS_SASL), 1)
--DEFINES += -DHAVE_CYRUS_SASL
--endif
--
--DEFINES += -DHAVE_CONFIG_H -DWIN32_LEAN_AND_MEAN
--
--CFLAGS += -O2 -Wall $(GCCWARNINGS) $(CC_HARDENING_OPTIONS) -pipe -mms-bitfields -g
--
--# If not specified, dlls are built with the default base address of 0x10000000.
--# When loaded into a process address space a dll will be rebased if its base
--# address colides with the base address of an existing dll. To avoid rebasing
--# we do the following. Rebasing can slow down the load time of dlls and it
--# also renders debug info useless.
--DLL_LD_FLAGS += -Wl,--enable-auto-image-base -Wl,--enable-auto-import $(LD_HARDENING_OPTIONS) -lssp
--
--# Build programs
--ifeq "$(origin CC)" "default"
-- CC := gcc.exe
--endif
--GMSGFMT ?= $(WIN32_DEV_TOP)/gettext-0.17/bin/msgfmt
--MAKENSIS ?= makensis.exe
--PERL ?= perl
--WINDRES ?= windres
--STRIP ?= strip
--INTLTOOL_MERGE ?= $(WIN32_DEV_TOP)/intltool_0.40.4-1_win32/bin/intltool-merge
--MONO_SIGNCODE ?= signcode
--GPG_SIGN ?= gpg
--
--PIDGIN_COMMON_RULES := $(PURPLE_TOP)/win32/rules.mak
--PIDGIN_COMMON_TARGETS := $(PURPLE_TOP)/win32/targets.mak
--MINGW_MAKEFILE := Makefile.mingw
--
--INSTALL_PIXMAPS ?= 1
--INSTALL_SSL_CERTIFICATES ?= 1
-diff -Nur pidgin-2.10.7/libpurple/win32/libc_interface.c pidgin-2.10.7-nonprism/libpurple/win32/libc_interface.c
---- pidgin-2.10.7/libpurple/win32/libc_interface.c 2013-02-11 07:16:53.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/win32/libc_interface.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1105 +0,0 @@
--/*
-- * purple
-- *
-- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--#include <winsock2.h>
--#include <ws2tcpip.h>
--#include <io.h>
--#include <stdlib.h>
--#include <stdio.h>
--#include <errno.h>
--#include <sys/timeb.h>
--#include <sys/stat.h>
--#include <time.h>
--#include <glib.h>
--#include "config.h"
--#include "debug.h"
--#include "libc_internal.h"
--#include <glib/gstdio.h>
--
--/** This is redefined here because we can't include internal.h */
--#ifdef ENABLE_NLS
--# include <locale.h>
--# include <libintl.h>
--# define _(String) ((const char *)dgettext(PACKAGE, String))
--# ifdef gettext_noop
--# define N_(String) gettext_noop (String)
--# else
--# define N_(String) (String)
--# endif
--#else
--# include <locale.h>
--# define N_(String) (String)
--# ifndef _
--# define _(String) ((const char *)String)
--# endif
--# define ngettext(Singular, Plural, Number) ((Number == 1) ? ((const char *)Singular) : ((const char *)Plural))
--# define dngettext(Domain, Singular, Plural, Number) ((Number == 1) ? ((const char *)Singular) : ((const char *)Plural))
--#endif
--
--#ifndef S_ISDIR
--# define S_ISDIR(m) (((m)&S_IFDIR)==S_IFDIR)
--#endif
--
--static char errbuf[1024];
--
--/* helpers */
--static int wpurple_is_socket( int fd ) {
-- int optval;
-- int optlen = sizeof(int);
--
-- if( (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&optval, &optlen)) == SOCKET_ERROR ) {
-- int error = WSAGetLastError();
-- if( error == WSAENOTSOCK )
-- return FALSE;
-- else {
-- purple_debug(PURPLE_DEBUG_WARNING, "wpurple", "wpurple_is_socket: getsockopt returned error: %d\n", error);
-- return FALSE;
-- }
-- }
-- return TRUE;
--}
--
--/* socket.h */
--int wpurple_socket (int namespace, int style, int protocol) {
-- int ret;
--
-- ret = socket( namespace, style, protocol );
--
-- if( ret == INVALID_SOCKET ) {
-- errno = WSAGetLastError();
-- return -1;
-- }
-- return ret;
--}
--
--int wpurple_connect(int socket, struct sockaddr *addr, u_long length) {
-- int ret;
--
-- ret = connect( socket, addr, length );
--
-- if( ret == SOCKET_ERROR ) {
-- errno = WSAGetLastError();
-- if( errno == WSAEWOULDBLOCK )
-- errno = WSAEINPROGRESS;
-- return -1;
-- }
-- return 0;
--}
--
--int wpurple_getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlenptr) {
-- if(getsockopt(socket, level, optname, optval, optlenptr) == SOCKET_ERROR ) {
-- errno = WSAGetLastError();
-- return -1;
-- }
-- return 0;
--}
--
--int wpurple_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen) {
-- if(setsockopt(socket, level, optname, optval, optlen) == SOCKET_ERROR ) {
-- errno = WSAGetLastError();
-- return -1;
-- }
-- return 0;
--}
--
--int wpurple_getsockname(int socket, struct sockaddr *addr, socklen_t *lenptr) {
-- if(getsockname(socket, addr, lenptr) == SOCKET_ERROR) {
-- errno = WSAGetLastError();
-- return -1;
-- }
-- return 0;
--}
--
--int wpurple_bind(int socket, struct sockaddr *addr, socklen_t length) {
-- if(bind(socket, addr, length) == SOCKET_ERROR) {
-- errno = WSAGetLastError();
-- return -1;
-- }
-- return 0;
--}
--
--int wpurple_listen(int socket, unsigned int n) {
-- if(listen(socket, n) == SOCKET_ERROR) {
-- errno = WSAGetLastError();
-- return -1;
-- }
-- return 0;
--}
--
--int wpurple_sendto(int socket, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) {
-- int ret;
-- if ((ret = sendto(socket, buf, len, flags, to, tolen)
-- ) == SOCKET_ERROR) {
-- errno = WSAGetLastError();
-- if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
-- errno = EAGAIN;
-- return -1;
-- }
-- return ret;
--}
--
--/* fcntl.h */
--/* This is not a full implementation of fcntl. Update as needed.. */
--int wpurple_fcntl(int socket, int command, ...) {
--
-- switch( command ) {
-- case F_GETFL:
-- return 0;
--
-- case F_SETFL:
-- {
-- va_list args;
-- int val;
-- int ret=0;
--
-- va_start(args, command);
-- val = va_arg(args, int);
-- va_end(args);
--
-- switch( val ) {
-- case O_NONBLOCK:
-- {
-- u_long imode=1;
-- ret = ioctlsocket(socket, FIONBIO, &imode);
-- break;
-- }
-- case 0:
-- {
-- u_long imode=0;
-- ret = ioctlsocket(socket, FIONBIO, &imode);
-- break;
-- }
-- default:
-- errno = EINVAL;
-- return -1;
-- }/*end switch*/
-- if( ret == SOCKET_ERROR ) {
-- errno = WSAGetLastError();
-- return -1;
-- }
-- return 0;
-- }
-- default:
-- purple_debug(PURPLE_DEBUG_WARNING, "wpurple", "wpurple_fcntl: Unsupported command\n");
-- return -1;
-- }/*end switch*/
--}
--
--/* sys/ioctl.h */
--int wpurple_ioctl(int fd, int command, void* val) {
-- switch( command ) {
-- case FIONBIO:
-- {
-- if (ioctlsocket(fd, FIONBIO, (unsigned long *)val) == SOCKET_ERROR) {
-- errno = WSAGetLastError();
-- return -1;
-- }
-- return 0;
-- }
-- case SIOCGIFCONF:
-- {
-- INTERFACE_INFO InterfaceList[20];
-- unsigned long nBytesReturned;
-- if (WSAIoctl(fd, SIO_GET_INTERFACE_LIST,
-- 0, 0, &InterfaceList,
-- sizeof(InterfaceList), &nBytesReturned,
-- 0, 0) == SOCKET_ERROR) {
-- errno = WSAGetLastError();
-- return -1;
-- } else {
-- int i;
-- struct ifconf *ifc = val;
-- char *tmp = ifc->ifc_buf;
-- int nNumInterfaces =
-- nBytesReturned / sizeof(INTERFACE_INFO);
-- for (i = 0; i < nNumInterfaces; i++) {
-- INTERFACE_INFO ii = InterfaceList[i];
-- struct ifreq *ifr = (struct ifreq *) tmp;
-- struct sockaddr_in *sa = (struct sockaddr_in *) &ifr->ifr_addr;
--
-- sa->sin_family = ii.iiAddress.AddressIn.sin_family;
-- sa->sin_port = ii.iiAddress.AddressIn.sin_port;
-- sa->sin_addr.s_addr = ii.iiAddress.AddressIn.sin_addr.s_addr;
-- tmp += sizeof(struct ifreq);
--
-- /* Make sure that we can fit in the original buffer */
-- if (tmp >= (ifc->ifc_buf + ifc->ifc_len + sizeof(struct ifreq))) {
-- break;
-- }
-- }
-- /* Replace the length with the actually used length */
-- ifc->ifc_len = ifc->ifc_len - (ifc->ifc_buf - tmp);
-- return 0;
-- }
-- }
-- default:
-- errno = EINVAL;
-- return -1;
-- }/*end switch*/
--}
--
--/* arpa/inet.h */
--int wpurple_inet_aton(const char *name, struct in_addr *addr) {
-- if((addr->s_addr = inet_addr(name)) == INADDR_NONE)
-- return 0;
-- else
-- return 1;
--}
--
--/* Thanks to GNU wget for this inet_ntop() implementation */
--const char *
--wpurple_inet_ntop (int af, const void *src, char *dst, socklen_t cnt)
--{
-- /* struct sockaddr can't accomodate struct sockaddr_in6. */
-- union {
-- struct sockaddr_in6 sin6;
-- struct sockaddr_in sin;
-- } sa;
-- DWORD dstlen = cnt;
-- size_t srcsize;
--
-- ZeroMemory(&sa, sizeof(sa));
-- switch (af)
-- {
-- case AF_INET:
-- sa.sin.sin_family = AF_INET;
-- sa.sin.sin_addr = *(struct in_addr *) src;
-- srcsize = sizeof (sa.sin);
-- break;
-- case AF_INET6:
-- sa.sin6.sin6_family = AF_INET6;
-- sa.sin6.sin6_addr = *(struct in6_addr *) src;
-- srcsize = sizeof (sa.sin6);
-- break;
-- default:
-- abort ();
-- }
--
-- if (WSAAddressToString ((struct sockaddr *) &sa, srcsize, NULL, dst, &dstlen) != 0)
-- {
-- errno = WSAGetLastError();
-- return NULL;
-- }
-- return (const char *) dst;
--}
--
--int
--wpurple_inet_pton(int af, const char *src, void *dst)
--{
-- /* struct sockaddr can't accomodate struct sockaddr_in6. */
-- union {
-- struct sockaddr_in6 sin6;
-- struct sockaddr_in sin;
-- } sa;
-- size_t srcsize;
--
-- switch(af)
-- {
-- case AF_INET:
-- sa.sin.sin_family = AF_INET;
-- srcsize = sizeof (sa.sin);
-- break;
-- case AF_INET6:
-- sa.sin6.sin6_family = AF_INET6;
-- srcsize = sizeof (sa.sin6);
-- break;
-- default:
-- errno = WSAEPFNOSUPPORT;
-- return -1;
-- }
--
-- if (WSAStringToAddress(src, af, NULL, (struct sockaddr *) &sa, &srcsize) != 0)
-- {
-- errno = WSAGetLastError();
-- return -1;
-- }
--
-- switch(af)
-- {
-- case AF_INET:
-- memcpy(dst, &sa.sin.sin_addr, sizeof(sa.sin.sin_addr));
-- break;
-- case AF_INET6:
-- memcpy(dst, &sa.sin6.sin6_addr, sizeof(sa.sin6.sin6_addr));
-- break;
-- }
--
-- return 1;
--}
--
--
--/* netdb.h */
--struct hostent* wpurple_gethostbyname(const char *name) {
-- struct hostent *hp;
--
-- if((hp = gethostbyname(name)) == NULL) {
-- errno = WSAGetLastError();
-- return NULL;
-- }
-- return hp;
--}
--
--/* string.h */
--char* wpurple_strerror(int errornum) {
-- if (errornum > WSABASEERR) {
-- switch(errornum) {
-- case WSAECONNABORTED: /* 10053 */
-- g_snprintf(errbuf, sizeof(errbuf), "%s", _("Connection interrupted by other software on your computer."));
-- break;
-- case WSAECONNRESET: /* 10054 */
-- g_snprintf(errbuf, sizeof(errbuf), "%s", _("Remote host closed connection."));
-- break;
-- case WSAETIMEDOUT: /* 10060 */
-- g_snprintf(errbuf, sizeof(errbuf), "%s", _("Connection timed out."));
-- break;
-- case WSAECONNREFUSED: /* 10061 */
-- g_snprintf(errbuf, sizeof(errbuf), "%s", _("Connection refused."));
-- break;
-- case WSAEADDRINUSE: /* 10048 */
-- g_snprintf(errbuf, sizeof(errbuf), "%s", _("Address already in use."));
-- break;
-- default:
-- g_snprintf(errbuf, sizeof(errbuf), "Windows socket error #%d", errornum);
-- }
-- } else {
-- const char *tmp = g_strerror(errornum);
-- g_snprintf(errbuf, sizeof(errbuf), "%s", tmp);
-- }
-- return errbuf;
--}
--
--/* unistd.h */
--
--/*
-- * We need to figure out whether fd is a file or socket handle.
-- */
--int wpurple_read(int fd, void *buf, unsigned int size) {
-- int ret;
--
-- if (fd < 0) {
-- errno = EBADF;
-- g_return_val_if_reached(-1);
-- }
--
-- if(wpurple_is_socket(fd)) {
-- if((ret = recv(fd, buf, size, 0)) == SOCKET_ERROR) {
-- errno = WSAGetLastError();
-- if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
-- errno = EAGAIN;
-- return -1;
-- }
--#if 0
-- else if( ret == 0 ) {
-- /* connection has been gracefully closed */
-- errno = WSAENOTCONN;
-- return -1;
-- }
--#endif
-- else {
-- /* success reading socket */
-- return ret;
-- }
-- } else {
-- /* fd is not a socket handle.. pass it off to read */
-- return _read(fd, buf, size);
-- }
--}
--
--int wpurple_send(int fd, const void *buf, unsigned int size, int flags) {
-- int ret;
--
-- ret = send(fd, buf, size, flags);
--
-- if (ret == SOCKET_ERROR) {
-- errno = WSAGetLastError();
-- if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
-- errno = EAGAIN;
-- return -1;
-- }
-- return ret;
--}
--
--int wpurple_write(int fd, const void *buf, unsigned int size) {
--
-- if (fd < 0) {
-- errno = EBADF;
-- g_return_val_if_reached(-1);
-- }
--
-- if(wpurple_is_socket(fd))
-- return wpurple_send(fd, buf, size, 0);
-- else
-- return _write(fd, buf, size);
--}
--
--int wpurple_recv(int fd, void *buf, size_t len, int flags) {
-- int ret;
--
-- if((ret = recv(fd, buf, len, flags)) == SOCKET_ERROR) {
-- errno = WSAGetLastError();
-- if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
-- errno = EAGAIN;
-- return -1;
-- } else {
-- return ret;
-- }
--}
--
--int wpurple_close(int fd) {
-- int ret;
--
-- if (fd < 0) {
-- errno = EBADF;
-- g_return_val_if_reached(-1);
-- }
--
-- if( wpurple_is_socket(fd) ) {
-- if( (ret = closesocket(fd)) == SOCKET_ERROR ) {
-- errno = WSAGetLastError();
-- return -1;
-- }
-- else
-- return 0;
-- }
-- else
-- return _close(fd);
--}
--
--int wpurple_gethostname(char *name, size_t size) {
-- if(gethostname(name, size) == SOCKET_ERROR) {
-- errno = WSAGetLastError();
-- return -1;
-- }
-- return 0;
--}
--
--/* sys/time.h */
--
--int wpurple_gettimeofday(struct timeval *p, struct timezone *z) {
-- int res = 0;
-- struct _timeb timebuffer;
--
-- if (z != 0) {
-- _tzset();
-- z->tz_minuteswest = _timezone/60;
-- z->tz_dsttime = _daylight;
-- }
--
-- if (p != 0) {
-- _ftime(&timebuffer);
-- p->tv_sec = timebuffer.time; /* seconds since 1-1-1970 */
-- p->tv_usec = timebuffer.millitm*1000; /* microseconds */
-- }
--
-- return res;
--}
--
--/* stdio.h */
--
--int wpurple_rename (const char *oldname, const char *newname) {
-- return g_rename(oldname, newname);
--}
--
--/* time.h */
--
--struct tm * wpurple_localtime_r (const time_t *time, struct tm *resultp) {
-- struct tm* tmptm;
--
-- if(!time)
-- return NULL;
-- tmptm = localtime(time);
-- if(resultp && tmptm)
-- return memcpy(resultp, tmptm, sizeof(struct tm));
-- else
-- return NULL;
--}
--
--/*
-- * Used by purple_utf8_strftime() by way of purple_internal_strftime()
-- * in src/util.c
-- *
-- * Code derived from PostgreSQL src/timezone/pgtz.c:
-- * http://developer.postgresql.org/cvsweb.cgi/pgsql/src/timezone/pgtz.c
-- */
--
--/*
--PostgreSQL Database Management System
--(formerly known as Postgres, then as Postgres95)
--
--Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
--
--Portions Copyright (c) 1994, The Regents of the University of California
--
--Permission to use, copy, modify, and distribute this software and its
--documentation for any purpose, without fee, and without a written agreement
--is hereby granted, provided that the above copyright notice and this
--paragraph and the following two paragraphs appear in all copies.
--
--IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
--DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
--LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
--DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
--POSSIBILITY OF SUCH DAMAGE.
--
--THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
--INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
--AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
--ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
--PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
--
--*/
--static struct
--{
-- char *wstd; /* Windows name of standard timezone */
-- char *wdst; /* Windows name of daylight timezone */
-- char *ustd; /* Unix name of standard timezone */
-- char *udst; /* Unix name of daylight timezone */
--} win32_tzmap[] =
--{
-- {
-- "", "",
-- "", "",
-- },
-- /*
-- * This list was built from the contents of the registry at
-- * "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"
-- * on Windows XP Professional SP1
-- */
-- {
-- "Afghanistan Standard Time", "Afghanistan Daylight Time",
-- "AFT", "AFT"
-- },
-- {
-- "Alaskan Standard Time", "Alaskan Daylight Time",
-- "AKST", "AKDT"
-- },
-- {
-- "Arab Standard Time", "Arab Daylight Time",
-- "AST", "AST"
-- },
-- {
-- "Arabian Standard Time", "Arabian Daylight Time",
-- "GST", "GST"
-- },
-- {
-- "Arabic Standard Time", "Arabic Daylight Time",
-- "AST", "ADT"
-- },
-- {
-- "Atlantic Standard Time", "Atlantic Daylight Time",
-- "AST", "ADT"
-- },
-- {
-- "AUS Central Standard Time", "AUS Central Daylight Time",
-- "CST", "CST"
-- },
-- {
-- "AUS Eastern Standard Time", "AUS Eastern Daylight Time",
-- "EST", "EST"
-- },
-- {
-- "Azores Standard Time", "Azores Daylight Time",
-- "AZOT", "AZOST"
-- },
-- {
-- "Canada Central Standard Time", "Canada Central Daylight Time",
-- "CST", "MDT"
-- },
-- {
-- "Cape Verde Standard Time", "Cape Verde Daylight Time",
-- "CVT", "CVST"
-- },
-- {
-- "Caucasus Standard Time", "Caucasus Daylight Time",
-- "AZT", "AZST"
-- },
-- {
-- "Cen. Australia Standard Time", "Cen. Australia Daylight Time",
-- "CST", "CST"
-- },
-- {
-- "Central America Standard Time", "Central America Daylight Time",
-- "CST", "CDT"
-- },
-- {
-- "Central Asia Standard Time", "Central Asia Daylight Time",
-- "BDT", "BDT"
-- },
-- {
-- "Central Europe Standard Time", "Central Europe Daylight Time",
-- "CET", "CEST"
-- },
-- {
-- "Central European Standard Time", "Central European Daylight Time",
-- "CET", "CEST"
-- },
-- {
-- "Central Pacific Standard Time", "Central Pacific Daylight Time",
-- "NCT", "NCST"
-- },
-- {
-- "Central Standard Time", "Central Daylight Time",
-- "CST", "CDT"
-- },
-- {
-- "China Standard Time", "China Daylight Time",
-- "HKT", "HKST"
-- },
-- {
-- "Dateline Standard Time", "Dateline Daylight Time",
-- "GMT+12", "GMT+12"
-- },
-- {
-- "E. Africa Standard Time", "E. Africa Daylight Time",
-- "EAT", "EAT"
-- },
-- {
-- "E. Australia Standard Time", "E. Australia Daylight Time",
-- "EST", "EST"
-- },
-- {
-- "E. Europe Standard Time", "E. Europe Daylight Time",
-- "EET", "EEST"
-- },
-- {
-- "E. South America Standard Time", "E. South America Daylight Time",
-- "BRT", "BRST"
-- },
-- {
-- "Eastern Standard Time", "Eastern Daylight Time",
-- "EST", "EDT"
-- },
-- {
-- "Egypt Standard Time", "Egypt Daylight Time",
-- "EET", "EEST"
-- },
-- {
-- "Ekaterinburg Standard Time", "Ekaterinburg Daylight Time",
-- "YEKT", "YEKST"
-- },
-- {
-- "Fiji Standard Time", "Fiji Daylight Time",
-- "FJT", "FJST"
-- },
-- {
-- "FLE Standard Time", "FLE Daylight Time",
-- "EET", "EEST"
-- },
-- {
-- "GMT Standard Time", "GMT Daylight Time",
-- "GMT", "IST"
-- },
-- {
-- "Greenland Standard Time", "Greenland Daylight Time",
-- "WGT", "WGST"
-- },
-- {
-- "Greenwich Standard Time", "Greenwich Daylight Time",
-- "WET", "WEST"
-- },
-- {
-- "GTB Standard Time", "GTB Daylight Time",
-- "EET", "EEST"
-- },
-- {
-- "Hawaiian Standard Time", "Hawaiian Daylight Time",
-- "HST", "HPT"
-- },
-- {
-- "India Standard Time", "India Daylight Time",
-- "IST", "IST"
-- },
-- {
-- "Iran Standard Time", "Iran Daylight Time",
-- "IRST", "IRDT"
-- },
-- {
-- "Jerusalem Standard Time", "Jerusalem Daylight Time",
-- "IST", "IDT"
-- },
-- {
-- "Korea Standard Time", "Korea Daylight Time",
-- "KST", "KDT"
-- },
-- {
-- "Mexico Standard Time", "Mexico Daylight Time",
-- "CST", "CDT"
-- },
-- {
-- "Mexico Standard Time", "Mexico Daylight Time",
-- "BOT", "BOST"
-- },
-- {
-- "Mid-Atlantic Standard Time", "Mid-Atlantic Daylight Time",
-- "GST", "GST"
-- },
-- {
-- "Mountain Standard Time", "Mountain Daylight Time",
-- "MST", "MDT"
-- },
-- {
-- "Myanmar Standard Time", "Myanmar Daylight Time",
-- "MMT", "MMT"
-- },
-- {
-- "N. Central Asia Standard Time", "N. Central Asia Daylight Time",
-- "ALMT", "ALMST"
-- },
-- {
-- "Nepal Standard Time", "Nepal Daylight Time",
-- "NPT", "NPT"
-- },
-- {
-- "New Zealand Standard Time", "New Zealand Daylight Time",
-- "NZST", "NZDT"
-- },
-- {
-- "Newfoundland Standard Time", "Newfoundland Daylight Time",
-- "NST", "NDT"
-- },
-- {
-- "North Asia East Standard Time", "North Asia East Daylight Time",
-- "IRKT", "IRKST"
-- },
-- {
-- "North Asia Standard Time", "North Asia Daylight Time",
-- "KRAT", "KRAST"
-- },
-- {
-- "Pacific SA Standard Time", "Pacific SA Daylight Time",
-- "CLT", "CLST"
-- },
-- {
-- "Pacific Standard Time", "Pacific Daylight Time",
-- "PST", "PDT"
-- },
-- {
-- "Romance Standard Time", "Romance Daylight Time",
-- "CET", "CEST"
-- },
-- {
-- "Russian Standard Time", "Russian Daylight Time",
-- "MSK", "MSD"
-- },
-- {
-- "SA Eastern Standard Time", "SA Eastern Daylight Time",
-- "ART", "ARST"
-- },
-- {
-- "SA Pacific Standard Time", "SA Pacific Daylight Time",
-- "COT", "COST"
-- },
-- {
-- "SA Western Standard Time", "SA Western Daylight Time",
-- "VET", "VET"
-- },
-- {
-- "Samoa Standard Time", "Samoa Daylight Time",
-- "SST", "NDT"
-- },
-- {
-- "SE Asia Standard Time", "SE Asia Daylight Time",
-- "ICT", "ICT"
-- },
-- {
-- "Malay Peninsula Standard Time", "Malay Peninsula Daylight Time",
-- "MYT", "MALST"
-- },
-- {
-- "South Africa Standard Time", "South Africa Daylight Time",
-- "CAT", "CAT"
-- },
-- {
-- "Sri Lanka Standard Time", "Sri Lanka Daylight Time",
-- "LKT", "IST"
-- },
-- {
-- "Taipei Standard Time", "Taipei Daylight Time",
-- "CST", "CDT"
-- },
-- {
-- "Tasmania Standard Time", "Tasmania Daylight Time",
-- "EST", "EST"
-- },
-- {
-- "Tokyo Standard Time", "Tokyo Daylight Time",
-- "JST", "JDT"
-- },
-- {
-- "Tonga Standard Time", "Tonga Daylight Time",
-- "TOT", "TOST"
-- },
-- {
-- "US Eastern Standard Time", "US Eastern Daylight Time",
-- "EST", "EDT"
-- },
-- {
-- "US Mountain Standard Time", "US Mountain Daylight Time",
-- "MST", "MDT"
-- },
-- {
-- "Vladivostok Standard Time", "Vladivostok Daylight Time",
-- "VLAT", "VLAST"
-- },
-- {
-- "W. Australia Standard Time", "W. Australia Daylight Time",
-- "WST", "WST"
-- },
--
-- /* Not mapped in PostgreSQL.
-- *
-- * I mapped this based on the following information... -- rlaager
-- * $ cd /usr/share/zoneinfo/Africa
-- * $ for i in * ; do echo `TZ=Africa/$i date +"%z %Z"` $i ; done | grep +0100
-- * +0100 CET Algiers
-- * +0100 WAT Bangui
-- * +0100 WAT Brazzaville
-- * +0100 CET Ceuta
-- * +0100 WAT Douala
-- * +0100 WAT Kinshasa
-- * +0100 WAT Lagos
-- * +0100 WAT Libreville
-- * +0100 WAT Luanda
-- * +0100 WAT Malabo
-- * +0100 WAT Ndjamena
-- * +0100 WAT Niamey
-- * +0100 WAT Porto-Novo
-- * +0100 CET Tunis
-- **/
-- {
-- "W. Central Africa Standard Time", "W. Central Africa Daylight Time",
-- "WAT", "WAT"
-- },
--
-- {
-- "W. Europe Standard Time", "W. Europe Daylight Time",
-- "CET", "CEST"
-- },
-- {
-- "West Asia Standard Time", "West Asia Daylight Time",
-- "PKT", "PKST"
-- },
-- {
-- "West Pacific Standard Time", "West Pacific Daylight Time",
-- "ChST", "ChST"
-- },
-- {
-- "Yakutsk Standard Time", "Yakutsk Daylight Time",
-- "YAKT", "YAKST"
-- },
-- {
-- NULL, NULL,
-- NULL, NULL
-- }
--};
--
--const char *
--wpurple_get_timezone_abbreviation(const struct tm *tm)
--{
-- int i;
-- char tzname[128];
-- char localtzname[256];
-- HKEY rootKey;
-- int idx;
--
-- if (!tm)
-- {
-- purple_debug_warning("wpurple", "could not determine current date/time: localtime failed\n");
-- return "";
-- }
--
-- if (strftime(tzname, sizeof(tzname) - 1, "%Z", tm) == 0)
-- {
-- purple_debug_error("wpurple", "timezone name is too long for the buffer\n");
-- return "";
-- }
--
-- for (i = 0; win32_tzmap[i].wstd != NULL; i++)
-- {
-- if (strcmp(tzname, win32_tzmap[i].wstd) == 0)
-- {
--#if 0
-- purple_debug_info("wpurple", "TZ \"%s\" matches Windows timezone \"%s\"\n",
-- win32_tzmap[i].ustd, tzname);
--#endif
-- /* Cache the Result */
-- if (i > 0) {
-- if (win32_tzmap[0].wstd[0] != '\0')
-- g_free(win32_tzmap[0].wstd);
-- win32_tzmap[0].wstd = g_strdup(tzname);
-- win32_tzmap[0].ustd = win32_tzmap[i].ustd;
-- }
--
-- return win32_tzmap[i].ustd;
-- }
-- if (strcmp(tzname, win32_tzmap[i].wdst) == 0)
-- {
--#if 0
-- purple_debug_info("wpurple", "TZ \"%s\" matches Windows timezone \"%s\"\n",
-- win32_tzmap[i].udst, tzname);
--#endif
-- /* Cache the Result */
-- if (i > 0) {
-- if (win32_tzmap[0].wdst[0] != '\0')
-- g_free(win32_tzmap[0].wdst);
-- win32_tzmap[0].wdst = g_strdup(tzname);
-- win32_tzmap[0].udst = win32_tzmap[i].udst;
-- }
--
-- return win32_tzmap[i].udst;
-- }
-- }
--
-- /*
-- * Localized Windows versions return localized names for the timezone.
-- * Scan the registry to find the English name, and then try matching
-- * against our table again.
-- */
-- memset(localtzname, 0, sizeof(localtzname));
-- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-- "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
-- 0,
-- KEY_READ,
-- &rootKey) != ERROR_SUCCESS)
-- {
-- purple_debug_warning("wpurple", "could not open registry key to identify Windows timezone: %i\n", (int) GetLastError());
-- return "";
-- }
--
-- for (idx = 0;; idx++)
-- {
-- char keyname[256];
-- char zonename[256];
-- DWORD namesize;
-- FILETIME lastwrite;
-- HKEY key;
-- LONG r;
--
-- memset(keyname, 0, sizeof(keyname));
-- namesize = sizeof(keyname);
-- if ((r = RegEnumKeyEx(rootKey,
-- idx,
-- keyname,
-- &namesize,
-- NULL,
-- NULL,
-- NULL,
-- &lastwrite)) != ERROR_SUCCESS)
-- {
-- if (r == ERROR_NO_MORE_ITEMS)
-- break;
-- purple_debug_warning("wpurple", "could not enumerate registry subkeys to identify Windows timezone: %i\n", (int) r);
-- break;
-- }
--
-- if ((r = RegOpenKeyEx(rootKey, keyname, 0, KEY_READ, &key)) != ERROR_SUCCESS)
-- {
-- purple_debug_warning("wpurple", "could not open registry subkey to identify Windows timezone: %i\n", (int) r);
-- break;
-- }
--
-- memset(zonename, 0, sizeof(zonename));
-- namesize = sizeof(zonename);
-- if ((r = RegQueryValueEx(key, "Std", NULL, NULL, (LPBYTE)zonename, &namesize)) != ERROR_SUCCESS)
-- {
-- purple_debug_warning("wpurple", "could not query value for 'std' to identify Windows timezone: %i\n", (int) r);
-- RegCloseKey(key);
-- break;
-- }
-- if (strcmp(tzname, zonename) == 0)
-- {
-- /* Matched zone */
-- g_strlcpy(localtzname, keyname, sizeof(localtzname));
-- RegCloseKey(key);
-- break;
-- }
-- memset(zonename, 0, sizeof(zonename));
-- namesize = sizeof(zonename);
-- if ((r = RegQueryValueEx(key, "Dlt", NULL, NULL, (LPBYTE)zonename, &namesize)) != ERROR_SUCCESS)
-- {
-- purple_debug_warning("wpurple", "could not query value for 'dlt' to identify Windows timezone: %i\n", (int) r);
-- RegCloseKey(key);
-- break;
-- }
-- if (strcmp(tzname, zonename) == 0)
-- {
-- /* Matched DST zone */
-- g_strlcpy(localtzname, keyname, sizeof(localtzname));
-- RegCloseKey(key);
-- break;
-- }
--
-- RegCloseKey(key);
-- }
--
-- RegCloseKey(rootKey);
--
-- if (localtzname[0])
-- {
-- /* Found a localized name, so scan for that one too */
-- for (i = 0; win32_tzmap[i].wstd != NULL; i++)
-- {
-- if (strcmp(localtzname, win32_tzmap[i].wstd) == 0)
-- {
--#if 0
-- purple_debug_info("wpurple", "TZ \"%s\" matches localized Windows timezone \"%s\" (\"%s\")\n",
-- win32_tzmap[i].ustd, tzname, localtzname);
--#endif
-- /* Cache the Result */
-- if (win32_tzmap[0].wstd[0] != '\0')
-- g_free(win32_tzmap[0].wstd);
-- win32_tzmap[0].wstd = g_strdup(tzname);
-- win32_tzmap[0].ustd = win32_tzmap[i].ustd;
--
-- return win32_tzmap[i].ustd;
-- }
-- if (strcmp(localtzname, win32_tzmap[i].wdst) == 0)
-- {
--#if 0
-- purple_debug_info("wpurple", "TZ \"%s\" matches localized Windows timezone \"%s\" (\"%s\")\n",
-- win32_tzmap[i].udst, tzname, localtzname);
--#endif
-- /* Cache the Result */
-- if (win32_tzmap[0].wdst[0] != '\0')
-- g_free(win32_tzmap[0].wdst);
--
-- win32_tzmap[0].wdst = g_strdup(tzname);
-- win32_tzmap[0].udst = win32_tzmap[i].udst;
--
-- return win32_tzmap[i].udst;
-- }
-- }
-- }
--
-- purple_debug_warning("wpurple", "could not find a match for Windows timezone \"%s\"\n", tzname);
-- return "";
--}
--
--int wpurple_g_access (const gchar *filename, int mode);
--/**
-- * @deprecated - remove for 3.0.0
-- */
--int
--wpurple_g_access (const gchar *filename, int mode)
--{
-- return g_access(filename, mode);
--}
--
--
-diff -Nur pidgin-2.10.7/libpurple/win32/libc_interface.h pidgin-2.10.7-nonprism/libpurple/win32/libc_interface.h
---- pidgin-2.10.7/libpurple/win32/libc_interface.h 2013-02-11 07:16:53.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/win32/libc_interface.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,154 +0,0 @@
--/*
-- * purple
-- *
-- * File: libc_interface.h
-- *
-- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--#ifndef _LIBC_INTERFACE_H_
--#define _LIBC_INTERFACE_H_
--#include <winsock2.h>
--#include <ws2tcpip.h>
--#include <io.h>
--#include <errno.h>
--#include "libc_internal.h"
--#include <glib.h>
--
--#ifdef __cplusplus
--extern "C" {
--#endif /* __cplusplus */
--
--#ifdef _MSC_VER
--#define S_IRUSR S_IREAD
--#define S_IWUSR S_IWRITE
--#define S_IXUSR S_IEXEC
--
--#define S_ISDIR(m) (((m)&S_IFDIR)==S_IFDIR)
--
--#define F_OK 0
--#endif
--
--/* sys/socket.h */
--#define socket( domain, style, protocol ) \
--wpurple_socket( domain, style, protocol )
--
--#define connect( socket, addr, length ) \
--wpurple_connect( socket, addr, length )
--
--#define getsockopt( socket, level, optname, optval, optlenptr ) \
--wpurple_getsockopt( socket, level, optname, optval, optlenptr )
--
--#define setsockopt( socket, level, optname, optval, optlen ) \
--wpurple_setsockopt( socket, level, optname, optval, optlen )
--
--#define getsockname( socket, addr, lenptr ) \
--wpurple_getsockname( socket, addr, lenptr )
--
--#define bind( socket, addr, length ) \
--wpurple_bind( socket, addr, length )
--
--#define listen( socket, n ) \
--wpurple_listen( socket, n )
--
--#define sendto(socket, buf, len, flags, to, tolen) \
--wpurple_sendto(socket, buf, len, flags, to, tolen)
--
--#define recv(fd, buf, len, flags) \
--wpurple_recv(fd, buf, len, flags)
--
--#define send(socket, buf, buflen, flags) \
--wpurple_send(socket, buf, buflen, flags)
--
--/* sys/ioctl.h */
--#define ioctl( fd, command, val ) \
--wpurple_ioctl( fd, command, val )
--
--/* fcntl.h */
--#define fcntl( fd, command, ... ) \
--wpurple_fcntl( fd, command, ##__VA_ARGS__ )
--
--/* arpa/inet.h */
--#define inet_aton( name, addr ) \
--wpurple_inet_aton( name, addr )
--
--#define inet_ntop( af, src, dst, cnt ) \
--wpurple_inet_ntop( af, src, dst, cnt )
--
--#define inet_pton( af, src, dst ) \
--wpurple_inet_pton( af, src, dst )
--
--/* netdb.h */
--#define gethostbyname( name ) \
--wpurple_gethostbyname( name )
--
--/* netinet/in.h */
--#define ntohl( netlong ) \
--(unsigned int)ntohl( netlong )
--
--/* string.h */
--#define hstrerror( herror ) \
--wpurple_strerror( errno )
--#define strerror( errornum ) \
--wpurple_strerror( errornum )
--#define g_strerror( errornum ) \
--wpurple_strerror( errornum )
--
--/* unistd.h */
--#define read( fd, buf, buflen ) \
--wpurple_read( fd, buf, buflen )
--
--#define write( socket, buf, buflen ) \
--wpurple_write( socket, buf, buflen )
--
--#define close( fd ) \
--wpurple_close( fd )
--
--#ifndef sleep
--#define sleep(x) Sleep((x)*1000)
--#endif
--
--#define gethostname( name, size ) \
--wpurple_gethostname( name, size )
--
--#define fsync(fd) _commit(fd)
--
--/* sys/time.h */
--#define gettimeofday( timeval, timezone ) \
--wpurple_gettimeofday( timeval, timezone )
--
--/* stdio.h */
--#undef snprintf
--#define snprintf _snprintf
--#undef vsnprintf
--#define vsnprintf _vsnprintf
--
--#define rename( oldname, newname ) \
--wpurple_rename( oldname, newname )
--
--/* sys/stat.h */
--#define fchmod(a,b)
--
--/* time.h */
--#define localtime_r( time, resultp ) \
--wpurple_localtime_r( time, resultp )
--
--#ifdef __cplusplus
--}
--#endif /* __cplusplus */
--
--#endif /* _LIBC_INTERFACE_H_ */
-diff -Nur pidgin-2.10.7/libpurple/win32/libc_internal.h pidgin-2.10.7-nonprism/libpurple/win32/libc_internal.h
---- pidgin-2.10.7/libpurple/win32/libc_internal.h 2013-02-11 07:16:53.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/win32/libc_internal.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,152 +0,0 @@
--/*
-- * purple
-- *
-- * File: libc_internal.h
-- *
-- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--#ifndef _LIBC_INTERNAL_
--#define _LIBC_INTERNAL_
--#include <glib.h>
--
--
--#ifdef __cplusplus
--extern "C" {
--#endif /* __cplusplus */
--
--/* helper for purple_utf8_strftime() by way of purple_internal_strftime() in src/util.c */
--const char *wpurple_get_timezone_abbreviation(const struct tm *tm);
--
--/* sys/socket.h */
--int wpurple_socket(int domain, int style, int protocol);
--int wpurple_connect(int socket, struct sockaddr *addr, u_long length);
--int wpurple_getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlenptr);
--int wpurple_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen);
--int wpurple_getsockname (int socket, struct sockaddr *addr, socklen_t *lenptr);
--int wpurple_bind(int socket, struct sockaddr *addr, socklen_t length);
--int wpurple_listen(int socket, unsigned int n);
--int wpurple_sendto(int socket, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
--int wpurple_recv(int fd, void *buf, size_t len, int flags);
--int wpurple_send(int fd, const void *buf, unsigned int size, int flags);
--
--/* arpa/inet.h */
--int wpurple_inet_aton(const char *name, struct in_addr *addr);
--const char *
--wpurple_inet_ntop (int af, const void *src, char *dst, socklen_t cnt);
--int wpurple_inet_pton(int af, const char *src, void *dst);
--
--/* netdb.h */
--struct hostent* wpurple_gethostbyname(const char *name);
--
--/* string.h */
--char* wpurple_strerror( int errornum );
--
--/* fcntl.h */
--int wpurple_fcntl(int socket, int command, ...);
--#define F_GETFL 3
--#define F_SETFL 4
--#define O_NONBLOCK 04000
--
--/* sys/ioctl.h */
--#define SIOCGIFCONF 0x8912 /* get iface list */
--int wpurple_ioctl(int fd, int command, void* opt);
--
--/* net/if.h */
--struct ifreq
--{
-- union
-- {
-- char ifrn_name[6]; /* Interface name, e.g. "en0". */
-- } ifr_ifrn;
--
-- union
-- {
-- struct sockaddr ifru_addr;
--#if 0
-- struct sockaddr ifru_dstaddr;
-- struct sockaddr ifru_broadaddr;
-- struct sockaddr ifru_netmask;
-- struct sockaddr ifru_hwaddr;
-- short int ifru_flags;
-- int ifru_ivalue;
-- int ifru_mtu;
--#endif
-- char *ifru_data;
-- } ifr_ifru;
--};
--# define ifr_name ifr_ifrn.ifrn_name /* interface name */
--# define ifr_addr ifr_ifru.ifru_addr /* address */
--#if 0
--# define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
--# define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
--# define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
--# define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
--# define ifr_flags ifr_ifru.ifru_flags /* flags */
--# define ifr_metric ifr_ifru.ifru_ivalue /* metric */
--# define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
--#endif
--# define ifr_data ifr_ifru.ifru_data /* for use by interface */
--#if 0
--# define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */
--# define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */
--# define ifr_qlen ifr_ifru.ifru_ivalue /* queue length */
--#endif
--
--
--struct ifconf
--{
-- int ifc_len; /* Size of buffer. */
-- union
-- {
-- char *ifcu_buf;
-- struct ifreq *ifcu_req;
-- } ifc_ifcu;
--};
--# define ifc_buf ifc_ifcu.ifcu_buf /* Buffer address. */
--# define ifc_req ifc_ifcu.ifcu_req /* Array of structures. */
--
--/* sys/time.h */
--#if __MINGW32_MAJOR_VERSION < 3 || (__MINGW32_MAJOR_VERSION == 3 && __MINGW32_MINOR_VERSION < 10)
--struct timezone {
-- int tz_minuteswest;
-- int tz_dsttime;
--};
--#else
--# include <sys/time.h>
--#endif
--int wpurple_gettimeofday(struct timeval *p, struct timezone *z);
--
--/* time.h */
--struct tm *wpurple_localtime_r(const time_t *time, struct tm *resultp);
--
--
--/* unistd.h */
--int wpurple_read(int fd, void *buf, unsigned int size);
--int wpurple_write(int fd, const void *buf, unsigned int size);
--int wpurple_close(int fd);
--int wpurple_gethostname(char *name, size_t size);
--
--
--/* stdio.h */
--int wpurple_rename(const char *oldname, const char *newname);
--
--#ifdef __cplusplus
--}
--#endif /* __cplusplus */
--
--#endif /* _LIBC_INTERNAL_ */
-diff -Nur pidgin-2.10.7/libpurple/win32/libpurplerc.rc.in pidgin-2.10.7-nonprism/libpurple/win32/libpurplerc.rc.in
---- pidgin-2.10.7/libpurple/win32/libpurplerc.rc.in 2013-02-11 07:16:53.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/win32/libpurplerc.rc.in 1969-12-31 21:00:00.000000000 -0300
-@@ -1,32 +0,0 @@
--#include <winver.h>
--#include "version.h"
--
--VS_VERSION_INFO VERSIONINFO
-- FILEVERSION PURPLE_MAJOR_VERSION,PURPLE_MINOR_VERSION,PURPLE_MICRO_VERSION,0
-- PRODUCTVERSION PURPLE_MAJOR_VERSION,PURPLE_MINOR_VERSION,PURPLE_MICRO_VERSION,0
-- FILEFLAGSMASK 0
-- FILEFLAGS 0
-- FILEOS VOS__WINDOWS32
-- FILETYPE VFT_DLL
-- FILESUBTYPE VFT2_UNKNOWN
-- BEGIN
-- BLOCK "StringFileInfo"
-- BEGIN
-- BLOCK "040904B0"
-- BEGIN
-- VALUE "CompanyName", "The Pidgin developer community"
-- VALUE "FileDescription", "LibPurple Library"
-- VALUE "FileVersion", "@PURPLE_VERSION@"
-- VALUE "InternalName", "libpurple"
-- VALUE "LegalCopyright", "Copyright (C) 1998-2010 The Pidgin developer community (See the COPYRIGHT file in the source distribution)."
-- VALUE "OriginalFilename", "libpurple.dll"
-- VALUE "ProductName", "LibPurple"
-- VALUE "ProductVersion", "@PURPLE_VERSION@"
-- END
-- END
-- BLOCK "VarFileInfo"
-- BEGIN
-- VALUE "Translation", 0x409, 1200
-- END
-- END
--
-diff -Nur pidgin-2.10.7/libpurple/win32/rules.mak pidgin-2.10.7-nonprism/libpurple/win32/rules.mak
---- pidgin-2.10.7/libpurple/win32/rules.mak 2013-02-11 07:16:53.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/win32/rules.mak 1969-12-31 21:00:00.000000000 -0300
-@@ -1,13 +0,0 @@
--# Rules on how to make object files from various sources
--
--%.o: %.c
-- $(CC) $(CFLAGS) $(DEFINES) $(INCLUDE_PATHS) -o $@ -c $<
--
--%.c: %.xs
-- $(PERL) -MExtUtils::ParseXS -e 'ExtUtils::ParseXS::process_file(filename => "$<", output => "$@", typemap => "$(PURPLE_PERL_TOP)/common/typemap");'
--
--%.o: %.rc
-- $(WINDRES) -I$(PURPLE_TOP) -i $< -o $@
--
--%.desktop: %.desktop.in $(wildcard $(PIDGIN_TREE_TOP)/po/*.po)
-- LC_ALL=C $(PERL) $(INTLTOOL_MERGE) -d -u -c $(PIDGIN_TREE_TOP)/po/.intltool-merge-cache $(PIDGIN_TREE_TOP)/po $< $@
-diff -Nur pidgin-2.10.7/libpurple/win32/targets.mak pidgin-2.10.7-nonprism/libpurple/win32/targets.mak
---- pidgin-2.10.7/libpurple/win32/targets.mak 2013-02-11 07:16:53.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/win32/targets.mak 1969-12-31 21:00:00.000000000 -0300
-@@ -1,59 +0,0 @@
--#
--# targets.mak
--#
--# This file should be included at the end of all Makefile.mingw
--# files for better handling of cross directory dependencies
--#
--
--$(PIDGIN_CONFIG_H): $(PIDGIN_CONFIG_H).mingw $(PIDGIN_TREE_TOP)/configure.ac
-- sed -e 's/@VERSION@/$(PIDGIN_VERSION)/; s/@DISPLAY_VERSION@/$(DISPLAY_VERSION)/' $@.mingw > $@
--
--$(PURPLE_PURPLE_H): $(PURPLE_PURPLE_H).in
-- sed -e 's/@PLUGINS_DEFINE@/#define PURPLE_PLUGINS 1/' $@.in > $@
--
--$(PURPLE_VERSION_H): $(PURPLE_VERSION_H).in $(PIDGIN_TREE_TOP)/configure.ac
-- awk 'BEGIN {FS="[\\(\\)\\[\\]]"} \
-- /^m4_define..purple_major_version/ {system("sed -e s/@PURPLE_MAJOR_VERSION@/"$$5"/ $@.in > $@");} \
-- /^m4_define..purple_minor_version/ {system("sed -e s/@PURPLE_MINOR_VERSION@/"$$5"/ $@ > $@.tmp && mv $@.tmp $@");} \
-- /^m4_define..purple_micro_version/ {system("sed -e s/@PURPLE_MICRO_VERSION@/"$$5"/ $@ > $@.tmp && mv $@.tmp $@"); exit}' $(PIDGIN_TREE_TOP)/configure.ac
--
--$(PIDGIN_REVISION_RAW_TXT):
-- (hg --cwd $(PIDGIN_TREE_TOP) id -i --debug) 2>/dev/null >$@ \
-- || rm -f $@
--
--$(PIDGIN_REVISION_H): $(PIDGIN_REVISION_RAW_TXT)
-- if [ -f $< ]; then \
-- sed 's/^\(.\{1,\}\)$$/#define REVISION "\1"/' $< > $@; \
-- fi
-- [ -f $@ ] || echo "#define REVISION \"unknown\"" > $@
--
--$(PURPLE_DLL) $(PURPLE_DLL).a: $(PURPLE_VERSION_H)
-- $(MAKE) -C $(PURPLE_TOP) -f $(MINGW_MAKEFILE) libpurple.dll
--
--$(PURPLE_PERL_DLL) $(PURPLE_PERL_DLL).a:
-- $(MAKE) -C $(PURPLE_PERL_TOP) -f $(MINGW_MAKEFILE) perl.dll
--
--$(PIDGIN_DLL) $(PIDGIN_DLL).a:
-- $(MAKE) -C $(PIDGIN_TOP) -f $(MINGW_MAKEFILE) pidgin.dll
--
--$(PIDGIN_EXE):
-- $(MAKE) -C $(PIDGIN_TOP) -f $(MINGW_MAKEFILE) pidgin.exe
--
--# Installation Directories
--$(PIDGIN_INSTALL_DIR):
-- mkdir -p $(PIDGIN_INSTALL_DIR)
--
--$(PIDGIN_INSTALL_PERL_DIR):
-- mkdir -p $(PIDGIN_INSTALL_PERL_DIR)
--
--$(PIDGIN_INSTALL_PLUGINS_DIR):
-- mkdir -p $(PIDGIN_INSTALL_PLUGINS_DIR)
--
--$(PURPLE_INSTALL_PO_DIR):
-- mkdir -p $(PURPLE_INSTALL_PO_DIR)
--
--#$(PURPLE_INSTALL_PLUGINS_DIR):
--# mkdir -p $(PURPLE_INSTALL_PLUGINS_DIR)
--
--#$(PURPLE_INSTALL_PERL_DIR):
--# mkdir -p $(PURPLE_INSTALL_PERL_DIR)
-diff -Nur pidgin-2.10.7/libpurple/win32/win32dep.c pidgin-2.10.7-nonprism/libpurple/win32/win32dep.c
---- pidgin-2.10.7/libpurple/win32/win32dep.c 2013-02-11 07:16:53.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/win32/win32dep.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,403 +0,0 @@
--/*
-- * purple
-- *
-- * File: win32dep.c
-- * Date: June, 2002
-- * Description: Windows dependant code for Purple
-- *
-- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--#define _WIN32_IE 0x501
--#include "internal.h"
--#include <winuser.h>
--
--#include "debug.h"
--#include "notify.h"
--
--/*
-- * LOCALS
-- */
--static char *app_data_dir = NULL, *install_dir = NULL,
-- *lib_dir = NULL, *locale_dir = NULL;
--
--static HINSTANCE libpurpledll_hInstance = NULL;
--
--/*
-- * PUBLIC CODE
-- */
--
--/* Escape windows dir separators. This is needed when paths are saved,
-- and on being read back have their '\' chars used as an escape char.
-- Returns an allocated string which needs to be freed.
--*/
--char *wpurple_escape_dirsep(const char *filename) {
-- int sepcount = 0;
-- const char *tmp = filename;
-- char *ret;
-- int cnt = 0;
--
-- g_return_val_if_fail(filename != NULL, NULL);
--
-- while(*tmp) {
-- if(*tmp == '\\')
-- sepcount++;
-- tmp++;
-- }
-- ret = g_malloc0(strlen(filename) + sepcount + 1);
-- while(*filename) {
-- ret[cnt] = *filename;
-- if(*filename == '\\')
-- ret[++cnt] = '\\';
-- filename++;
-- cnt++;
-- }
-- ret[cnt] = '\0';
-- return ret;
--}
--
--/* Determine whether the specified dll contains the specified procedure.
-- If so, load it (if not already loaded). */
--FARPROC wpurple_find_and_loadproc(const char *dllname, const char *procedure) {
-- HMODULE hmod;
-- BOOL did_load = FALSE;
-- FARPROC proc = 0;
--
-- wchar_t *wc_dllname = g_utf8_to_utf16(dllname, -1, NULL, NULL, NULL);
--
-- if(!(hmod = GetModuleHandleW(wc_dllname))) {
-- purple_debug_warning("wpurple", "%s not already loaded; loading it...\n", dllname);
-- if(!(hmod = LoadLibraryW(wc_dllname))) {
-- purple_debug_error("wpurple", "Could not load: %s (%s)\n", dllname,
-- g_win32_error_message(GetLastError()));
-- g_free(wc_dllname);
-- return NULL;
-- }
-- else
-- did_load = TRUE;
-- }
--
-- g_free(wc_dllname);
-- wc_dllname = NULL;
--
-- if((proc = GetProcAddress(hmod, procedure))) {
-- purple_debug_info("wpurple", "This version of %s contains %s\n",
-- dllname, procedure);
-- return proc;
-- }
-- else {
-- purple_debug_warning("wpurple", "Function %s not found in dll %s\n",
-- procedure, dllname);
-- if(did_load) {
-- /* unload dll */
-- FreeLibrary(hmod);
-- }
-- return NULL;
-- }
--}
--
--/* Determine Purple Paths during Runtime */
--
--/* Get paths to special Windows folders. */
--gchar *wpurple_get_special_folder(int folder_type) {
-- gchar *retval = NULL;
-- wchar_t utf_16_dir[MAX_PATH + 1];
--
-- if (SUCCEEDED(SHGetFolderPathW(NULL, folder_type, NULL,
-- SHGFP_TYPE_CURRENT, utf_16_dir))) {
-- retval = g_utf16_to_utf8(utf_16_dir, -1, NULL, NULL, NULL);
-- }
--
-- return retval;
--}
--
--const char *wpurple_install_dir(void) {
-- static gboolean initialized = FALSE;
--
-- if (!initialized) {
-- char *tmp = NULL;
-- wchar_t winstall_dir[MAXPATHLEN];
-- if (GetModuleFileNameW(libpurpledll_hInstance, winstall_dir,
-- MAXPATHLEN) > 0) {
-- tmp = g_utf16_to_utf8(winstall_dir, -1,
-- NULL, NULL, NULL);
-- }
--
-- if (tmp == NULL) {
-- tmp = g_win32_error_message(GetLastError());
-- purple_debug_error("wpurple",
-- "GetModuleFileName error: %s\n", tmp);
-- g_free(tmp);
-- return NULL;
-- } else {
-- install_dir = g_path_get_dirname(tmp);
-- g_free(tmp);
-- initialized = TRUE;
-- }
-- }
--
-- return install_dir;
--}
--
--const char *wpurple_lib_dir(void) {
-- static gboolean initialized = FALSE;
--
-- if (!initialized) {
-- const char *inst_dir = wpurple_install_dir();
-- if (inst_dir != NULL) {
-- lib_dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "plugins", inst_dir);
-- initialized = TRUE;
-- } else {
-- return NULL;
-- }
-- }
--
-- return lib_dir;
--}
--
--const char *wpurple_locale_dir(void) {
-- static gboolean initialized = FALSE;
--
-- if (!initialized) {
-- const char *inst_dir = wpurple_install_dir();
-- if (inst_dir != NULL) {
-- locale_dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "locale", inst_dir);
-- initialized = TRUE;
-- } else {
-- return NULL;
-- }
-- }
--
-- return locale_dir;
--}
--
--const char *wpurple_data_dir(void) {
--
-- if (!app_data_dir) {
-- /* Set app data dir, used by purple_home_dir */
-- const char *newenv = g_getenv("PURPLEHOME");
-- if (newenv)
-- app_data_dir = g_strdup(newenv);
-- else {
-- app_data_dir = wpurple_get_special_folder(CSIDL_APPDATA);
-- if (!app_data_dir)
-- app_data_dir = g_strdup("C:");
-- }
-- purple_debug_info("wpurple", "Purple settings dir: %s\n",
-- app_data_dir);
-- }
--
-- return app_data_dir;
--}
--
--/* Miscellaneous */
--
--gboolean wpurple_write_reg_string(HKEY rootkey, const char *subkey, const char *valname,
-- const char *value) {
-- HKEY reg_key;
-- gboolean success = FALSE;
--
-- wchar_t *wc_subkey = g_utf8_to_utf16(subkey, -1, NULL,
-- NULL, NULL);
--
-- if(RegOpenKeyExW(rootkey, wc_subkey, 0,
-- KEY_SET_VALUE, &reg_key) == ERROR_SUCCESS) {
-- wchar_t *wc_valname = NULL;
--
-- if (valname)
-- wc_valname = g_utf8_to_utf16(valname, -1,
-- NULL, NULL, NULL);
--
-- if(value) {
-- wchar_t *wc_value = g_utf8_to_utf16(value, -1,
-- NULL, NULL, NULL);
-- int len = (wcslen(wc_value) * sizeof(wchar_t)) + 1;
-- if(RegSetValueExW(reg_key, wc_valname, 0, REG_SZ,
-- (LPBYTE)wc_value, len
-- ) == ERROR_SUCCESS)
-- success = TRUE;
-- g_free(wc_value);
-- } else
-- if(RegDeleteValueW(reg_key, wc_valname) == ERROR_SUCCESS)
-- success = TRUE;
--
-- g_free(wc_valname);
-- }
-- g_free(wc_subkey);
--
-- if(reg_key != NULL)
-- RegCloseKey(reg_key);
--
-- return success;
--}
--
--static HKEY _reg_open_key(HKEY rootkey, const char *subkey, REGSAM access) {
-- HKEY reg_key = NULL;
-- LONG rv;
--
-- wchar_t *wc_subkey = g_utf8_to_utf16(subkey, -1, NULL,
-- NULL, NULL);
-- rv = RegOpenKeyExW(rootkey, wc_subkey, 0, access, &reg_key);
--
-- g_free(wc_subkey);
--
-- if (rv != ERROR_SUCCESS) {
-- char *errmsg = g_win32_error_message(rv);
-- purple_debug_error("wpurple", "Could not open reg key '%s' subkey '%s'.\nMessage: (%ld) %s\n",
-- ((rootkey == HKEY_LOCAL_MACHINE) ? "HKLM" :
-- (rootkey == HKEY_CURRENT_USER) ? "HKCU" :
-- (rootkey == HKEY_CLASSES_ROOT) ? "HKCR" : "???"),
-- subkey, rv, errmsg);
-- g_free(errmsg);
-- }
--
-- return reg_key;
--}
--
--static gboolean _reg_read(HKEY reg_key, const char *valname, LPDWORD type, LPBYTE data, LPDWORD data_len) {
-- LONG rv;
--
-- wchar_t *wc_valname = NULL;
-- if (valname)
-- wc_valname = g_utf8_to_utf16(valname, -1, NULL, NULL, NULL);
-- rv = RegQueryValueExW(reg_key, wc_valname, 0, type, data, data_len);
-- g_free(wc_valname);
--
-- if (rv != ERROR_SUCCESS) {
-- char *errmsg = g_win32_error_message(rv);
-- purple_debug_error("wpurple", "Could not read from reg key value '%s'.\nMessage: (%ld) %s\n",
-- valname, rv, errmsg);
-- g_free(errmsg);
-- }
--
-- return (rv == ERROR_SUCCESS);
--}
--
--gboolean wpurple_read_reg_dword(HKEY rootkey, const char *subkey, const char *valname, LPDWORD result) {
--
-- DWORD type;
-- DWORD nbytes;
-- HKEY reg_key = _reg_open_key(rootkey, subkey, KEY_QUERY_VALUE);
-- gboolean success = FALSE;
--
-- if(reg_key) {
-- if(_reg_read(reg_key, valname, &type, (LPBYTE)result, &nbytes))
-- success = TRUE;
-- RegCloseKey(reg_key);
-- }
--
-- return success;
--}
--
--char *wpurple_read_reg_string(HKEY rootkey, const char *subkey, const char *valname) {
--
-- DWORD type;
-- DWORD nbytes;
-- HKEY reg_key = _reg_open_key(rootkey, subkey, KEY_QUERY_VALUE);
-- char *result = NULL;
--
-- if(reg_key) {
-- if(_reg_read(reg_key, valname, &type, NULL, &nbytes) && type == REG_SZ) {
-- LPBYTE data = (LPBYTE) g_new(wchar_t, ((nbytes + 1) / sizeof(wchar_t)) + 1);
--
-- if(_reg_read(reg_key, valname, &type, data, &nbytes)) {
-- wchar_t *wc_temp = (wchar_t*) data;
-- wc_temp[nbytes / sizeof(wchar_t)] = '\0';
-- result = g_utf16_to_utf8(wc_temp, -1,
-- NULL, NULL, NULL);
-- }
-- g_free(data);
-- }
-- RegCloseKey(reg_key);
-- }
--
-- return result;
--}
--
--void wpurple_init(void) {
-- WORD wVersionRequested;
-- WSADATA wsaData;
--
-- if (!g_thread_supported())
-- g_thread_init(NULL);
--
-- purple_debug_info("wpurple", "wpurple_init start\n");
-- purple_debug_info("wpurple", "libpurple version: " DISPLAY_VERSION "\n");
--
-- purple_debug_info("wpurple", "Glib:%u.%u.%u\n",
-- glib_major_version, glib_minor_version, glib_micro_version);
--
-- /* Winsock init */
-- wVersionRequested = MAKEWORD(2, 2);
-- WSAStartup(wVersionRequested, &wsaData);
--
-- /* Confirm that the winsock DLL supports 2.2 */
-- /* Note that if the DLL supports versions greater than
-- 2.2 in addition to 2.2, it will still return 2.2 in
-- wVersion since that is the version we requested. */
-- if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
-- purple_debug_error("wpurple", "Could not find a usable WinSock DLL. Oh well.\n");
-- WSACleanup();
-- }
--
-- purple_debug_info("wpurple", "wpurple_init end\n");
--}
--
--/* Windows Cleanup */
--
--void wpurple_cleanup(void) {
-- purple_debug_info("wpurple", "wpurple_cleanup\n");
--
-- /* winsock cleanup */
-- WSACleanup();
--
-- g_free(app_data_dir);
-- g_free(install_dir);
-- g_free(lib_dir);
-- g_free(locale_dir);
--
-- app_data_dir = NULL;
-- install_dir = NULL;
-- lib_dir = NULL;
-- locale_dir = NULL;
--
-- libpurpledll_hInstance = NULL;
--}
--
--long
--wpurple_get_tz_offset() {
-- TIME_ZONE_INFORMATION tzi;
-- DWORD ret;
-- long off = -1;
--
-- if ((ret = GetTimeZoneInformation(&tzi)) != TIME_ZONE_ID_INVALID)
-- {
-- off = -(tzi.Bias * 60);
-- if (ret == TIME_ZONE_ID_DAYLIGHT)
-- off -= tzi.DaylightBias * 60;
-- }
--
-- return off;
--}
--
--/* DLL initializer */
--/* suppress gcc "no previous prototype" warning */
--BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
--BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
-- libpurpledll_hInstance = hinstDLL;
-- return TRUE;
--}
-diff -Nur pidgin-2.10.7/libpurple/win32/win32dep.h pidgin-2.10.7-nonprism/libpurple/win32/win32dep.h
---- pidgin-2.10.7/libpurple/win32/win32dep.h 2013-02-11 07:16:53.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/win32/win32dep.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,92 +0,0 @@
--/*
-- * purple
-- *
-- * File: win32dep.h
-- *
-- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--#ifndef _WIN32DEP_H_
--#define _WIN32DEP_H_
--#include <winsock2.h>
--#include <windows.h>
--#include <shlobj.h>
--#include <process.h>
--#include "wpurpleerror.h"
--#include "libc_interface.h"
--
--
--#ifdef __cplusplus
--extern "C" {
--#endif /* __cplusplus */
--
--/* the winapi headers don't yet have winhttp.h, so we use the struct from msdn directly */
--typedef struct {
-- BOOL fAutoDetect;
-- LPWSTR lpszAutoConfigUrl;
-- LPWSTR lpszProxy;
-- LPWSTR lpszProxyBypass;
--} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
--
--/* rpcndr.h defines small as char, causing problems, so we need to undefine it */
--#undef small
--
--/*
-- * PROTOS
-- */
--
--/**
-- ** win32dep.c
-- **/
--/* Windows helper functions */
--FARPROC wpurple_find_and_loadproc(const char *dllname, const char *procedure);
--gboolean wpurple_read_reg_dword(HKEY rootkey, const char *subkey, const char *valname, LPDWORD result);
--char *wpurple_read_reg_string(HKEY rootkey, const char *subkey, const char *valname); /* needs to be g_free'd */
--gboolean wpurple_write_reg_string(HKEY rootkey, const char *subkey, const char *valname, const char *value);
--char *wpurple_escape_dirsep(const char *filename); /* needs to be g_free'd */
--GIOChannel *wpurple_g_io_channel_win32_new_socket(int socket); /* Until we get the post-2.8 glib win32 giochannel implementation working, use the thread-based one */
--
--/* Determine Purple paths */
--gchar *wpurple_get_special_folder(int folder_type); /* needs to be g_free'd */
--const char *wpurple_install_dir(void);
--const char *wpurple_lib_dir(void);
--const char *wpurple_locale_dir(void);
--const char *wpurple_data_dir(void);
--
--/* init / cleanup */
--void wpurple_init(void);
--void wpurple_cleanup(void);
--
--long wpurple_get_tz_offset(void);
--
--/*
-- * MACROS
-- */
--
--/*
-- * Purple specific
-- */
--#define DATADIR wpurple_install_dir()
--#define LIBDIR wpurple_lib_dir()
--#define LOCALEDIR wpurple_locale_dir()
--
--#ifdef __cplusplus
--}
--#endif /* __cplusplus */
--
--#endif /* _WIN32DEP_H_ */
--
-diff -Nur pidgin-2.10.7/libpurple/win32/wpurpleerror.h pidgin-2.10.7-nonprism/libpurple/win32/wpurpleerror.h
---- pidgin-2.10.7/libpurple/win32/wpurpleerror.h 2013-02-11 07:16:53.000000000 -0200
-+++ pidgin-2.10.7-nonprism/libpurple/win32/wpurpleerror.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,58 +0,0 @@
--/*
-- * purple
-- *
-- * File: wpurpleerror.h
-- * Date: October 14, 2002
-- * Description: Convert Winsock errors to Unix errors
-- *
-- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--#ifndef _WPURPLEERROR_H
--#define _WPURPLEERROR_H
--
--/* Here we define unix socket errors as windows socket errors */
--
--#define ENETDOWN WSAENETDOWN
--#define EAFNOSUPPORT WSAEAFNOSUPPORT
--#define EINPROGRESS WSAEINPROGRESS
--#define ENOBUFS WSAENOBUFS
--#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
--#define EPROTOTYPE WSAEPROTOTYPE
--#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
--
--#define EADDRINUSE WSAEADDRINUSE
--#define EINPROGRESS WSAEINPROGRESS
--#define EALREADY WSAEALREADY
--#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
--#define ECONNREFUSED WSAECONNREFUSED
--#define EISCONN WSAEISCONN
--#define ENETUNREACH WSAENETUNREACH
--#define ENOTSOCK WSAENOTSOCK
--#define ETIMEDOUT WSAETIMEDOUT
--#define EWOULDBLOCK WSAEWOULDBLOCK
--
--#define ENOTCONN WSAENOTCONN
--#define ENETRESET WSAENETRESET
--#define EOPNOTSUPP WSAEOPNOTSUPP
--#define ESHUTDOWN WSAESHUTDOWN
--#define EMSGSIZE WSAEMSGSIZE
--#define ECONNABORTED WSAECONNABORTED
--#define ECONNRESET WSAECONNRESET
--#define EHOSTUNREACH WSAEHOSTUNREACH
--
--#endif /* end _WPURPLEERROR_H */
-diff -Nur pidgin-2.10.7/m4macros/Makefile.in pidgin-2.10.7-nonprism/m4macros/Makefile.in
---- pidgin-2.10.7/m4macros/Makefile.in 2013-02-11 07:17:23.000000000 -0200
-+++ pidgin-2.10.7-nonprism/m4macros/Makefile.in 2013-08-17 00:04:19.720029689 -0300
-@@ -151,8 +151,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -214,8 +212,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/Makefile.in pidgin-2.10.7-nonprism/Makefile.in
---- pidgin-2.10.7/Makefile.in 2013-02-11 07:17:25.000000000 -0200
-+++ pidgin-2.10.7-nonprism/Makefile.in 2013-08-17 00:05:38.535783624 -0300
-@@ -218,8 +218,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -281,8 +279,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/Makefile.mingw pidgin-2.10.7-nonprism/Makefile.mingw
---- pidgin-2.10.7/Makefile.mingw 2013-02-11 07:16:50.000000000 -0200
-+++ pidgin-2.10.7-nonprism/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,210 +0,0 @@
--# Makefile.mingw
--#
--# Author: hermanator12002@yahoo.com
--# Date 9/11/02
--# Description: Top Makefile for win32 (mingw) port of Pidgin and libpurple
--#
--
--PIDGIN_TREE_TOP := .
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--# Generate a X.X.X.X version for the installer file versioning header
--# The last digit will be 99 for a final release, 0 for dev or unknown, or the beta number
--PIDGIN_PRODUCT_VERSION = $(shell \
--awk 'BEGIN {FS="."} { \
-- if (int($$3) == $$3) { \
-- $$4 = "99"; \
-- } else { \
-- $$5 = $$3; \
-- sub(int($$3), "", $$5); \
-- if ($$5 == "dev") { \
-- $$4 = "0"; \
-- } else { \
-- if (sub("beta", "", $$5) > 0) { \
-- $$4 = $$5; \
-- } else { \
-- $$4 = "0"; \
-- } \
-- } \
-- } \
-- printf("%s.%s.%s.%s", $$1, $$2, int($$3), $$4); \
-- exit; \
--}' VERSION)
--
--GTK_INSTALL_VERSION = 2.16.6.1
--
--authenticode_sign = $(MONO_SIGNCODE) \
-- -spc "$(SIGNCODE_SPC)" -v "$(SIGNCODE_PVK)" \
-- -a sha1 -$$ commercial \
-- -n "$(2)" -i "https://pidgin.im" \
-- -t "http://timestamp.verisign.com/scripts/timstamp.dll" -tr 10 \
-- $(1)
--
--gpg_sign = $(GPG_SIGN) -ab $(1) && $(GPG_SIGN) --verify $(1).asc
--
--STRIPPED_RELEASE_DIR = $(PIDGIN_TREE_TOP)/pidgin-$(PIDGIN_VERSION)-win32bin
--DEBUG_SYMBOLS_DIR = $(PIDGIN_TREE_TOP)/pidgin-$(PIDGIN_VERSION)-dbgsym
--
--PIDGIN_INST_DEP_DIR="$(WIN32_DEV_TOP)/pidgin-inst-deps-20120910"
--
--# Any *.dll or *.exe files included in win32-install-dir that we don't compile
--# should be included in this list so they don't get stripped
--EXTERNAL_DLLS = \
-- comerr32.dll \
-- exchndl.dll \
-- freebl3.dll \
-- gssapi32.dll \
-- k5sprt32.dll \
-- krb5_32.dll \
-- libenchant.dll \
-- libenchant_ispell.dll \
-- libenchant_myspell.dll \
-- libgtkspell-0.dll \
-- libmeanwhile-1.dll \
-- libnspr4.dll \
-- libplc4.dll \
-- libplds4.dll \
-- libsasl.dll \
-- libssp-0.dll \
-- libxml2-2.dll \
-- nss3.dll \
-- nssutil3.dll \
-- saslANONYMOUS.dll \
-- saslCRAMMD5.dll \
-- saslDIGESTMD5.dll \
-- saslGSSAPI.dll \
-- saslLOGIN.dll \
-- saslPLAIN.dll \
-- libsilc-1-1-2.dll \
-- libsilcclient-1-1-3.dll \
-- smime3.dll \
-- softokn3.dll \
-- sqlite3.dll \
-- ssl3.dll
--
--#build an expression for `find` to use to ignore the above files
--EXTERNAL_DLLS_FIND_EXP = $(patsubst %,-o -name %,$(EXTERNAL_DLLS))
--
--include $(PIDGIN_COMMON_RULES)
--
--.PHONY: all docs install installer installer_offline installer_zip debug_symbols_zip installers clean uninstall create_release_install_dir generate_installer_includes $(PIDGIN_REVISION_H) $(PIDGIN_REVISION_RAW_TXT) gtk_runtime_zip
--
--all: $(PIDGIN_CONFIG_H) $(PIDGIN_REVISION_H)
-- $(MAKE) -C $(PURPLE_TOP) -f $(MINGW_MAKEFILE)
-- $(MAKE) -C $(PIDGIN_TOP) -f $(MINGW_MAKEFILE)
--ifndef DISABLE_NLS
-- $(MAKE) -C $(PURPLE_PO_TOP) -f $(MINGW_MAKEFILE)
--endif
--
--install: all $(PIDGIN_INSTALL_DIR)
-- $(MAKE) -C $(PURPLE_TOP) -f $(MINGW_MAKEFILE) install
-- $(MAKE) -C $(PIDGIN_TOP) -f $(MINGW_MAKEFILE) install
--ifndef DISABLE_NLS
-- $(MAKE) -C $(PURPLE_PO_TOP) -f $(MINGW_MAKEFILE) install
--endif
-- $(MAKE) -C share/ca-certs -f $(MINGW_MAKEFILE) install
-- $(MAKE) -C share/sounds -f $(MINGW_MAKEFILE) install
-- mkdir -p $(PIDGIN_INSTALL_DIR)/spellcheck/lib/enchant
-- cp $(GTKSPELL_TOP)/bin/libgtkspell-0.dll $(PIDGIN_INSTALL_DIR)/spellcheck
-- cp $(ENCHANT_TOP)/bin/libenchant.dll $(PIDGIN_INSTALL_DIR)/spellcheck
-- cp -R $(ENCHANT_TOP)/lib/enchant/*.dll $(PIDGIN_INSTALL_DIR)/spellcheck/lib/enchant
-- cp $(PIDGIN_INST_DEP_DIR)/exchndl.dll $(PIDGIN_INSTALL_DIR)
-- cp $(GCC_SSP_TOP)/bin/libssp-0.dll $(PIDGIN_INSTALL_DIR)
--
--gtk_runtime_zip:
-- pidgin/win32/nsis/generate_gtk_zip.sh "`pwd`" "$(GPG_SIGN)"
--
--generate_installer_includes: create_release_install_dir gtk_runtime_zip debug_symbols_zip $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/nsis_translations.desktop
-- rm -f pidgin/win32/nsis/pidgin-translations.nsh pidgin/win32/nsis/pidgin-spellcheck.nsh pidgin/win32/nsis/pidgin-spellcheck-preselect.nsh
-- find $(STRIPPED_RELEASE_DIR)/locale -maxdepth 1 -mindepth 1 \
-- -exec basename {} ';' \
-- | LC_ALL=C sort | sed -e s/^/\!insertmacro\ LANG_SECTION\ \"/ -e s/$$/\"/ \
-- > pidgin/win32/nsis/pidgin-translations.nsh
-- #Convert the available.lst lines to "!insertmacro SPELLCHECK_SECTION lang lang_name lang_file"
-- sed -e "/^#/d" -e "s/^[^,]\{1,\},[^,]\{1,\},/\"/" \
-- -e "s/,/\"\ \"/" -e "s/,/\"\ \"/" -e "s/[\ \t]*$$/\"/" \
-- -e "s/^/\!insertmacro\ SPELLCHECK_SECTION\ /" \
-- pidgin/win32/nsis/available.lst \
-- > pidgin/win32/nsis/pidgin-spellcheck.nsh
-- #Convert the lines to "!insertmacro CHECK_SPELLCHECK_SECTION lang"
-- iconv -f latin1 -t utf-8 pidgin/win32/nsis/pidgin-spellcheck.nsh | \
-- sed -e "s/SPELLCHECK_SECTION/CHECK_SPELLCHECK_SECTION/" \
-- -e "s/ \"[^\"]*\"\ \"[^\"]*\"[\t\ ]*$$//" | \
-- iconv -f utf-8 -t latin1 \
-- > pidgin/win32/nsis/pidgin-spellcheck-preselect.nsh
-- #Generate the Installer translations
-- echo "!define GCOMPRIS_NSIS_INCLUDE_PATH \".\"" > $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/langmacros.nsh
-- echo "@INSERT_TRANSLATIONS@" >> $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/langmacros.nsh
-- $(PERL) $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/create_nsis_translations.pl \
-- $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/nsis_translations.desktop \
-- $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/langmacros.nsh \
-- $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/translations
--
--create_release_install_dir: install
-- rm -rf $(STRIPPED_RELEASE_DIR)
-- mkdir $(STRIPPED_RELEASE_DIR)
-- tar -cf - $(PIDGIN_INSTALL_DIR) --exclude=Gtk --exclude=spellcheck/share \
-- | tar --strip 2 -xC $(STRIPPED_RELEASE_DIR) -f -
-- find $(STRIPPED_RELEASE_DIR) \( -name '*.dll' -o -name '*.exe' \) \
-- -not \( -false $(EXTERNAL_DLLS_FIND_EXP) \) \
-- -exec $(STRIP) --strip-unneeded {} ';'
-- $(call authenticode_sign, $(STRIPPED_RELEASE_DIR)/pidgin.exe, "Pidgin $(PIDGIN_VERSION)")
--
--installer: generate_installer_includes
-- $(eval $@_DEBUG_SYMBOLS_SHA1SUM := $(shell sha1sum $(DEBUG_SYMBOLS_DIR).zip | sed -e "s/\ .*$$//"))
-- $(eval $@_GTK_SHA1SUM := $(shell sha1sum pidgin/win32/nsis/gtk-runtime-$(GTK_INSTALL_VERSION).zip | sed -e "s/\ .*$$//"))
-- $(MAKENSIS) -V3 -DPIDGIN_VERSION="$(PIDGIN_VERSION)" -DPIDGIN_PRODUCT_VERSION="$(PIDGIN_PRODUCT_VERSION)" \
-- -DPIDGIN_INSTALL_DIR="$(STRIPPED_RELEASE_DIR)" -DGTK_INSTALL_VERSION="$(GTK_INSTALL_VERSION)" \
-- -DDEBUG_SYMBOLS_SHA1SUM="$($@_DEBUG_SYMBOLS_SHA1SUM)" -DGTK_SHA1SUM="$($@_GTK_SHA1SUM)"\
-- pidgin/win32/nsis/pidgin-installer.nsi
-- $(call authenticode_sign, pidgin/win32/nsis/pidgin-$(PIDGIN_VERSION).exe, "Pidgin Installer")
-- mv pidgin/win32/nsis/pidgin-$(PIDGIN_VERSION).exe ./
-- $(call gpg_sign, pidgin-$(PIDGIN_VERSION).exe)
--
--installer_offline: generate_installer_includes
-- $(MAKENSIS) -V3 -DPIDGIN_VERSION="$(PIDGIN_VERSION)" -DPIDGIN_PRODUCT_VERSION="$(PIDGIN_PRODUCT_VERSION)" \
-- -DPIDGIN_INSTALL_DIR="$(STRIPPED_RELEASE_DIR)" -DGTK_INSTALL_VERSION="$(GTK_INSTALL_VERSION)" \
-- -DOFFLINE_INSTALLER \
-- pidgin/win32/nsis/pidgin-installer.nsi
-- $(call authenticode_sign, pidgin/win32/nsis/pidgin-$(PIDGIN_VERSION)-offline.exe, "Pidgin Installer")
-- mv pidgin/win32/nsis/pidgin-$(PIDGIN_VERSION)-offline.exe ./
-- $(call gpg_sign, pidgin-$(PIDGIN_VERSION)-offline.exe)
--
--installer_zip: create_release_install_dir
-- rm -f pidgin-$(PIDGIN_VERSION)-win32-bin.zip
-- zip -9 -r pidgin-$(PIDGIN_VERSION)-win32-bin.zip $(STRIPPED_RELEASE_DIR)
-- $(call gpg_sign, pidgin-$(PIDGIN_VERSION)-win32-bin.zip)
--
--debug_symbols_zip: install
-- rm -rf $(DEBUG_SYMBOLS_DIR) $(DEBUG_SYMBOLS_DIR).zip
-- mkdir $(DEBUG_SYMBOLS_DIR)
-- tar -cf - `find $(PIDGIN_INSTALL_DIR) \( -name '*.dll' -o -name '*.exe' \) \
-- -not \( -false $(EXTERNAL_DLLS_FIND_EXP) \) -print` \
-- | tar --strip 2 --xform s/$$/.dbgsym/ -xC $(DEBUG_SYMBOLS_DIR) -f -
-- cp $(MEANWHILE_TOP)/bin/libmeanwhile-1.dll.unstripped $(DEBUG_SYMBOLS_DIR)/libmeanwhile-1.dll.dbgsym
-- zip -9 -r $(DEBUG_SYMBOLS_DIR).zip $(DEBUG_SYMBOLS_DIR)
-- $(call gpg_sign, $(DEBUG_SYMBOLS_DIR).zip)
--
--installers: installer installer_offline debug_symbols_zip installer_zip
--
--Doxyfile.mingw: Doxyfile.in
-- sed -e "s/@PACKAGE@/pidgin/" -e "s/@VERSION@/$(PIDGIN_VERSION)/" -e "s/@top_srcdir@/$(PIDGIN_TREE_TOP)/g" -e "s/@enable_dot@/NO/" $< > $@
--
--docs: Doxyfile.mingw
-- @echo "Running doxygen..."
-- @doxygen Doxyfile.mingw
--
--clean:
-- $(MAKE) -C $(PURPLE_PO_TOP) -f $(MINGW_MAKEFILE) clean
-- $(MAKE) -C $(PIDGIN_TOP) -f $(MINGW_MAKEFILE) clean
-- $(MAKE) -C $(PURPLE_TOP) -f $(MINGW_MAKEFILE) clean
-- $(MAKE) -C share/ca-certs -f $(MINGW_MAKEFILE) clean
-- rm -f $(PIDGIN_CONFIG_H) $(PIDGIN_REVISION_H) $(PIDGIN_REVISION_RAW_TXT) ./VERSION pidgin-$(PIDGIN_VERSION)*.exe pidgin-$(PIDGIN_VERSION)-win32-bin.zip $(DEBUG_SYMBOLS_DIR).zip
-- rm -rf doc/html Doxyfile.mingw
--
--uninstall:
-- rm -rf $(PURPLE_INSTALL_PERL_DIR) $(PIDGIN_INSTALL_PLUGINS_DIR) $(PURPLE_INSTALL_PO_DIR) $(PIDGIN_INSTALL_DIR) $(STRIPPED_RELEASE_DIR) $(DEBUG_SYMBOLS_DIR)
-- rm -f ./VERSION
--
--include $(PIDGIN_COMMON_TARGETS)
--
-diff -Nur pidgin-2.10.7/NEWS pidgin-2.10.7-nonprism/NEWS
---- pidgin-2.10.7/NEWS 2013-02-11 07:16:50.000000000 -0200
-+++ pidgin-2.10.7-nonprism/NEWS 2013-08-16 22:35:02.839098729 -0300
-@@ -984,7 +984,7 @@
- Luke: Not much to see here, some bug fixes that you all will enjoy as
- the semester draws to a close and everyone still in school gets bogged
- down with projects, papers, and exams. Enjoy! Oh, and if you are interested
-- in the perl or gadu-gadu functionality, please step up to help write
-+ in the perl functionality, please step up to help write
- patches, as both of these code blocks are currently unmaintained.
-
- Tim: I fixed a couple bugs this time. In other news, Kim wants to get
diff -Nur pidgin-2.10.7/pidgin/gtkaccount.c pidgin-2.10.7-nonprism/pidgin/gtkaccount.c
--- pidgin-2.10.7/pidgin/gtkaccount.c 2013-02-11 07:16:53.000000000 -0200
+++ pidgin-2.10.7-nonprism/pidgin/gtkaccount.c 2013-08-27 22:45:35.495576079 -0300
@@ -154779,185 +2414,6 @@ diff -Nur pidgin-2.10.7/pidgin/Makefile.in pidgin-2.10.7-nonprism/pidgin/Makefil
@ENABLE_GTK_TRUE@AM_CPPFLAGS = \
@ENABLE_GTK_TRUE@ -DDATADIR=\"$(datadir)\" \
@ENABLE_GTK_TRUE@ -DLIBDIR=\"$(libdir)/pidgin/\" \
-diff -Nur pidgin-2.10.7/pidgin/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/Makefile.mingw
---- pidgin-2.10.7/pidgin/Makefile.mingw 2013-02-11 07:16:53.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,175 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of Pidgin
--#
--
--PIDGIN_TREE_TOP := ..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES))
--
--##
--## VARIABLE DEFINITIONS
--##
--EXE_TARGET := pidgin
--PIDGIN_TARGET := pidgin
--EXE_NAME := $(EXE_TARGET).exe
--
--WINAPP := -mwindows
--
--LDFLAGS := $(WINAPP) $(LD_HARDENING_OPTIONS) -Wl,--enable-auto-import -lssp
--
--##
--## INCLUDE PATHS
--##
--PURPLE_INCLUDE_PATHS = \
-- -I$(PURPLE_TOP) \
-- -I$(PURPLE_TOP)/win32 \
-- -I$(PIDGIN_TREE_TOP) \
-- -I$(GTK_TOP)/include \
-- -I$(GTK_TOP)/include/glib-2.0 \
-- -I$(GTK_TOP)/lib/glib-2.0/include
--
--INCLUDE_PATHS += \
-- $(PURPLE_INCLUDE_PATHS) \
-- -I$(PIDGIN_TOP) \
-- -I$(PIDGIN_TOP)/win32 \
-- -I$(GTK_TOP)/include/gtk-2.0 \
-- -I$(GTK_TOP)/include/pango-1.0 \
-- -I$(GTK_TOP)/include/atk-1.0 \
-- -I$(GTK_TOP)/include/cairo \
-- -I$(GTK_TOP)/lib/gtk-2.0/include \
-- -I$(GTKSPELL_TOP)/include/gtkspell-2.0
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP) \
-- -L$(PIDGIN_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--PIDGIN_C_SRC = \
-- gtkaccount.c \
-- gtkblist-theme-loader.c \
-- gtkblist-theme.c \
-- gtkblist.c \
-- gtkcellrendererexpander.c \
-- gtkcertmgr.c \
-- gtkconn.c \
-- gtkconv.c \
-- gtkdebug.c \
-- gtkdialogs.c \
-- gtkdnd-hints.c \
-- gtkdocklet.c \
-- gtkeventloop.c \
-- gtkft.c \
-- gtkicon-theme-loader.c \
-- gtkicon-theme.c \
-- gtkidle.c \
-- gtkimhtml.c \
-- gtkimhtmltoolbar.c \
-- gtklog.c \
-- gtkmain.c \
-- gtkmedia.c \
-- gtkmenutray.c \
-- gtknotify.c \
-- gtkplugin.c \
-- gtkpluginpref.c \
-- gtkpounce.c \
-- gtkprefs.c \
-- gtkprivacy.c \
-- gtkrequest.c \
-- gtkroomlist.c \
-- gtksavedstatuses.c \
-- gtkscrollbook.c \
-- gtksmiley.c \
-- gtksound.c \
-- gtksourceiter.c \
-- gtksourceundomanager.c \
-- gtkstatus-icon-theme.c \
-- gtkstatusbox.c \
-- gtkthemes.c \
-- gtkutils.c \
-- gtkwhiteboard.c \
-- minidialog.c \
-- pidginstock.c \
-- pidgintooltip.c \
-- win32/MinimizeToTray.c \
-- win32/gtkdocklet-win32.c \
-- win32/gtkwin32dep.c \
-- win32/untar.c \
-- win32/wspell.c
--
--PIDGIN_RC_SRC = win32/pidgin_dll_rc.rc
--PIDGIN_OBJECTS = $(PIDGIN_C_SRC:%.c=%.o) $(PIDGIN_RC_SRC:%.rc=%.o)
--
--EXE_RC_SRC = win32/pidgin_exe_rc.rc
--EXE_C_SRC = win32/winpidgin.c
--EXE_OBJECTS = $(EXE_C_SRC:%.c=%.o) $(EXE_RC_SRC:%.rc=%.o)
--
--##
--## LIBRARIES
--##
--
--PIDGIN_LIBS = \
-- -lintl \
-- -lglib-2.0 \
-- -lgobject-2.0 \
-- -lgthread-2.0 \
-- -lpurple \
-- -lz \
-- -lgtk-win32-2.0 \
-- -latk-1.0 \
-- -lcairo \
-- -lpango-1.0 \
-- -lgdk-win32-2.0 \
-- -lgdk_pixbuf-2.0 \
-- -lgdi32 \
-- -lwinmm
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install install_shallow clean
--
--all: $(EXE_TARGET).exe $(PIDGIN_TARGET).dll
-- $(MAKE) -C $(PIDGIN_PLUGINS_TOP) -f $(MINGW_MAKEFILE)
--
--win32/pidgin_exe_rc.rc: win32/pidgin_exe_rc.rc.in $(PIDGIN_TREE_TOP)/VERSION
-- sed -e 's/@PIDGIN_VERSION@/$(PIDGIN_VERSION)/g' \
-- -e 's/@ORIGINAL_FILENAME@/$(EXE_NAME)/' \
-- $@.in > $@
--
--install_shallow: $(PIDGIN_INSTALL_DIR) $(EXE_TARGET).exe $(PIDGIN_TARGET).dll
-- cp $(EXE_TARGET).exe $(PIDGIN_TARGET).dll $(PIDGIN_INSTALL_DIR)
--
--install: install_shallow all
-- $(MAKE) -C $(PIDGIN_PLUGINS_TOP) -f $(MINGW_MAKEFILE) install
-- $(MAKE) -C $(PIDGIN_PIXMAPS_TOP) -f $(MINGW_MAKEFILE) install
--
--win32/pidgin_dll_rc.rc: win32/pidgin_dll_rc.rc.in $(PIDGIN_TREE_TOP)/VERSION
-- sed -e 's/@PIDGIN_VERSION@/$(PIDGIN_VERSION)/g' \
-- $@.in > $@
--
--$(EXE_OBJECTS) $(PIDGIN_OBJECTS): $(PIDGIN_CONFIG_H)
--
--$(PIDGIN_TARGET).dll $(PIDGIN_TARGET).dll.a: $(PURPLE_DLL).a $(PIDGIN_OBJECTS)
-- $(CC) -shared $(PIDGIN_OBJECTS) $(LIB_PATHS) $(PIDGIN_LIBS) $(DLL_LD_FLAGS) -Wl,--output-def,$(PIDGIN_TARGET).def,--out-implib,$(PIDGIN_TARGET).dll.a -o $(PIDGIN_TARGET).dll
--
--$(EXE_TARGET).exe: $(PIDGIN_CONFIG_H) $(PIDGIN_DLL).a $(EXE_OBJECTS) $(PIDGIN_TARGET).dll
-- $(CC) $(EXE_OBJECTS) $(LDFLAGS) -o $(EXE_TARGET).exe
--
--##
--## CLEAN RULES
--##
--clean:
-- $(MAKE) -C $(PIDGIN_PLUGINS_TOP) -f $(MINGW_MAKEFILE) clean
-- $(MAKE) -C $(PIDGIN_PIXMAPS_TOP) -f $(MINGW_MAKEFILE) clean
-- rm -f $(PIDGIN_OBJECTS) $(PIDGIN_RC_SRC) $(EXE_OBJECTS) $(EXE_RC_SRC)
-- rm -f $(PIDGIN_TARGET).dll $(PIDGIN_TARGET).dll.a $(PIDGIN_TARGET).def
-- rm -f $(EXE_TARGET).exe
--
--include $(PIDGIN_COMMON_TARGETS)
diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/default.theme.in pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/default/24/default.theme.in
--- pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/default.theme.in 2013-02-11 07:16:53.000000000 -0200
+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/default/24/default.theme.in 2013-08-16 23:13:41.759061988 -0300
@@ -155496,58 +2952,6 @@ diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/default.theme.in pidgin
-confused.png :-, :,
-hungry.png :-C :C
-stressed.png :-s :s
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/Makefile.in pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/default/24/Makefile.in
---- pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/Makefile.in 2013-02-11 07:17:23.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/default/24/Makefile.in 2013-08-17 00:02:25.939870063 -0300
-@@ -151,8 +151,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -214,8 +212,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/default/24/Makefile.mingw
---- pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/Makefile.mingw 2013-02-11 07:16:53.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/default/24/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,27 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of Pidgin pixmaps
--#
--
--PIDGIN_TREE_TOP := ../../../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--datadir = $(PIDGIN_INSTALL_DIR)
---include ./Makefile.am.mingw
--
--.PHONY: install clean
--
--install: ./Makefile.am.mingw theme
-- if test '$(pidginsmileypix_DATA)'; then \
-- mkdir -p $(pidginsmileypixdir); \
-- cp $(pidginsmileypix_DATA) $(pidginsmileypixdir); \
-- fi;
--
--clean:
-- rm -f theme ./Makefile.am.mingw
--
--./Makefile.am.mingw: ./Makefile.am
-- sed -e 's/^if\ INSTALL_PIXMAPS/ifeq (\$$(INSTALL_PIXMAPS), 1)/' ./Makefile.am > $@
-- include $@
--
diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/theme pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/default/24/theme
--- pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/theme 2013-02-11 07:17:58.000000000 -0200
+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/default/24/theme 2013-08-16 23:15:55.929941297 -0300
@@ -156086,110 +3490,6 @@ diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/theme pidgin-2.10.7-non
-confused.png :-, :,
-hungry.png :-C :C
-stressed.png :-s :s
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/none/Makefile.in pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/none/Makefile.in
---- pidgin-2.10.7/pidgin/pixmaps/emotes/none/Makefile.in 2013-02-11 07:17:23.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/none/Makefile.in 2013-08-17 00:01:20.721202021 -0300
-@@ -151,8 +151,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -214,8 +212,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/none/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/none/Makefile.mingw
---- pidgin-2.10.7/pidgin/pixmaps/emotes/none/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/none/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,27 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of Pidgin pixmaps
--#
--
--PIDGIN_TREE_TOP := ../../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--datadir = $(PIDGIN_INSTALL_DIR)
---include ./Makefile.am.mingw
--
--.PHONY: install clean
--
--install: ./Makefile.am.mingw theme
-- if test '$(pidginsmileypix_DATA)'; then \
-- mkdir -p $(pidginsmileypixdir); \
-- cp $(pidginsmileypix_DATA) $(pidginsmileypixdir); \
-- fi;
--
--clean:
-- rm -f theme ./Makefile.am.mingw
--
--./Makefile.am.mingw: ./Makefile.am
-- sed -e 's/^if\ INSTALL_PIXMAPS/ifeq (\$$(INSTALL_PIXMAPS), 1)/' ./Makefile.am > $@
-- include $@
--
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/small/16/Makefile.in pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/small/16/Makefile.in
---- pidgin-2.10.7/pidgin/pixmaps/emotes/small/16/Makefile.in 2013-02-11 07:17:23.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/small/16/Makefile.in 2013-08-17 00:01:44.881943374 -0300
-@@ -151,8 +151,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -214,8 +212,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/small/16/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/small/16/Makefile.mingw
---- pidgin-2.10.7/pidgin/pixmaps/emotes/small/16/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/small/16/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,27 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of Pidgin pixmaps
--#
--
--PIDGIN_TREE_TOP := ../../../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--datadir = $(PIDGIN_INSTALL_DIR)
---include ./Makefile.am.mingw
--
--.PHONY: install clean
--
--install: ./Makefile.am.mingw theme
-- if test '$(pidginsmileypix_DATA)'; then \
-- mkdir -p $(pidginsmileypixdir); \
-- cp $(pidginsmileypix_DATA) $(pidginsmileypixdir); \
-- fi;
--
--clean:
-- rm -f theme ./Makefile.am.mingw
--
--./Makefile.am.mingw: ./Makefile.am
-- sed -e 's/^if\ INSTALL_PIXMAPS/ifeq (\$$(INSTALL_PIXMAPS), 1)/' ./Makefile.am > $@
-- include $@
--
diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/small/16/small.theme.in pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/small/16/small.theme.in
--- pidgin-2.10.7/pidgin/pixmaps/emotes/small/16/small.theme.in 2013-02-11 07:16:54.000000000 -0200
+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/small/16/small.theme.in 2013-08-16 23:19:01.815778718 -0300
@@ -157074,5666 +4374,6 @@ diff -Nur pidgin-2.10.7/pidgin/pixmaps/Makefile.in pidgin-2.10.7-nonprism/pidgin
@INSTALL_PIXMAPS_TRUE@ protocols/scalable/zephyr.svg
@INSTALL_PIXMAPS_TRUE@STATUS_11 = \
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/pixmaps/Makefile.mingw
---- pidgin-2.10.7/pidgin/pixmaps/Makefile.mingw 2013-02-11 07:16:53.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,51 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of Pidgin pixmaps
--#
--
--PIDGIN_TREE_TOP := ../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--datadir := $(PIDGIN_INSTALL_DIR)
---include ./Makefile.am.mingw
--
--.PHONY: install clean
--
--install: ./Makefile.am.mingw
-- if test '$(SUBDIRS)'; then \
-- list='$(SUBDIRS)'; for subdir in $$list; do \
-- $(MAKE) -C $$subdir -f $(MINGW_MAKEFILE) install || exit 1 ;\
-- done; \
-- fi;
-- if test '$(nobase_dist_pidginpixmap_DATA)'; then \
-- list='$(nobase_dist_pidginpixmap_DATA)'; for file in $$list; do \
-- dir=`dirname $$file`; \
-- mkdir -p $(pidginpixmapdir)/$$dir; \
-- cp $$file $(pidginpixmapdir)/$$dir/; \
-- done; \
-- fi;
-- if test '$(pidginbuttonpix_DATA)'; then \
-- mkdir -p $(pidginbuttonpixdir); \
-- cp $(pidginbuttonpix_DATA) $(pidginbuttonpixdir); \
-- fi;
-- if test '$(pidgindistpix_DATA)'; then \
-- mkdir -p $(pidgindistpixdir); \
-- cp $(pidgindistpix_DATA) $(pidgindistpixdir); \
-- fi;
--
--clean: ./Makefile.am.mingw
-- if test '$(SUBDIRS)'; then \
-- list='$(SUBDIRS)'; for subdir in $$list; do \
-- $(MAKE) -C $$subdir -f $(MINGW_MAKEFILE) clean;\
-- done; \
-- fi;
-- rm -f ./Makefile.am.mingw
--
--./Makefile.am.mingw: ./Makefile.am ./Makefile.mingw
-- sed \
-- -e 's/^if\ INSTALL_PIXMAPS/ifeq (\$$(INSTALL_PIXMAPS), 1)/' \
-- -e 's/^if\ ENABLE_TRAYCOMPAT/ifeq (\$$(ENABLE_TRAYCOMPAT), 1)/' \
-- $< > $@
-- include $@
--
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/aim.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/aim.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/facebook.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/facebook.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/gadu-gadu.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/gadu-gadu.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/google-talk.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/google-talk.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/icq.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/icq.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/meanwhile.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/meanwhile.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/msn.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/msn.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/mxit.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/mxit.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/myspace.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/myspace.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/novell.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/novell.png differ
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/aim.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/aim.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/aim.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/aim.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,265 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="16px"
-- height="16px"
-- id="svg4248"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/16/scalable"
-- sodipodi:docname="aim.svg"
-- inkscape:export-filename="/home/hbons/Bureaublad/aim.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs4250">
-- <inkscape:perspective
-- sodipodi:type="inkscape:persp3d"
-- inkscape:vp_x="0 : 8 : 1"
-- inkscape:vp_y="0 : 1000 : 0"
-- inkscape:vp_z="16 : 8 : 1"
-- inkscape:persp3d-origin="8 : 5.3333333 : 1"
-- id="perspective40" />
-- <linearGradient
-- id="linearGradient8711"
-- inkscape:collect="always">
-- <stop
-- id="stop8713"
-- offset="0"
-- style="stop-color:#bb7e07;stop-opacity:1" />
-- <stop
-- id="stop8715"
-- offset="1"
-- style="stop-color:#926205;stop-opacity:1" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8703">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8705" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8707" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8686">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8688" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8690" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8784">
-- <stop
-- style="stop-color:#bb9007;stop-opacity:1;"
-- offset="0"
-- id="stop8786" />
-- <stop
-- style="stop-color:#927005;stop-opacity:1"
-- offset="1"
-- id="stop8788" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8776">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8778" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8780" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8653">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8655" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8657" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8637">
-- <stop
-- style="stop-color:#be7800;stop-opacity:1"
-- offset="0"
-- id="stop8639" />
-- <stop
-- style="stop-color:#906400;stop-opacity:1"
-- offset="1"
-- id="stop8641" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8637"
-- id="linearGradient8643"
-- x1="9.1367941"
-- y1="1.628371"
-- x2="16.636042"
-- y2="10.933484"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8653"
-- id="linearGradient8659"
-- x1="4.7796931"
-- y1="-4.2560463"
-- x2="14.475067"
-- y2="9.7333546"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8776"
-- id="linearGradient8782"
-- x1="9.4571943"
-- y1="4.418859"
-- x2="4.7050147"
-- y2="15.798837"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8711"
-- id="linearGradient8790"
-- x1="11.863748"
-- y1="8.6871567"
-- x2="1.8747424"
-- y2="13.60194"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="translate(1.2641541,-0.2145011)" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8686"
-- id="linearGradient8692"
-- x1="8.3698959"
-- y1="-1.1186354"
-- x2="14.103671"
-- y2="8.6191578"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8784"
-- id="linearGradient8696"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="translate(1.2641541,-0.2145011)"
-- x1="5.2542644"
-- y1="8.9798889"
-- x2="8.4612246"
-- y2="14.318395" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8703"
-- id="linearGradient8709"
-- x1="4.9951673"
-- y1="8.807704"
-- x2="11.323474"
-- y2="13.381649"
-- gradientUnits="userSpaceOnUse" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="19.324309"
-- inkscape:cx="22.516951"
-- inkscape:cy="8.219724"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- inkscape:grid-bbox="true"
-- inkscape:document-units="px"
-- inkscape:window-width="1440"
-- inkscape:window-height="847"
-- inkscape:window-x="0"
-- inkscape:window-y="0"
-- inkscape:snap-bbox="true"
-- inkscape:snap-nodes="false"
-- objecttolerance="10"
-- gridtolerance="10">
-- <inkscape:grid
-- type="xygrid"
-- visible="true"
-- enabled="true"
-- id="grid7865" />
-- </sodipodi:namedview>
-- <metadata
-- id="metadata4253">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- id="layer1"
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer">
-- <path
-- style="opacity:1;fill:#f8c766;fill-opacity:1;stroke:url(#linearGradient8790);stroke-width:1.00000024000000010;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- d="M 8.9039189,4.5121855 C 2.6129138,6.1978553 8.2398799,12.598865 1.5258742,12.598865 L 1.5342001,15.603027 C 7.5993543,15.603027 7.4985792,12.514605 7.4985792,12.514605 C 9.596051,12.514605 10.513648,13.498816 10.513648,15.520135 L 14.530663,15.541737 C 14.530663,9.8333244 9.0743771,9.4942293 9.0743771,9.4942293 C 9.0743771,9.4942293 14.495884,9.4837515 14.495884,9.4837515 C 14.495884,9.4837515 14.522789,6.4996057 14.522789,6.4996057 C 12.764013,6.4996057 9.6229595,6.7951443 8.9039189,4.5121855 z"
-- id="path4275"
-- sodipodi:nodetypes="cccccccccc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-1.0049574"
-- inkscape:original="M 8.90625 4.5 C 2.6152446 6.1856697 8.2452557 12.59375 1.53125 12.59375 L 1.53125 15.59375 C 7.5964042 15.59375 7.5 12.5 7.5 12.5 C 9.597472 12.5 10.5 13.509931 10.5 15.53125 L 14.53125 15.53125 C 14.53125 9.8228378 9.0625 9.5 9.0625 9.5 C 9.0625 9.5 14.5 9.46875 14.5 9.46875 C 14.5 9.4687502 14.53125 6.5 14.53125 6.5 C 12.772474 6.5 9.6252906 6.7829588 8.90625 4.5 z "
-- style="opacity:1;fill:none;fill-opacity:1;stroke:url(#linearGradient8709);stroke-width:1.00000024000000010;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path8698"
-- d="M 8.59375,5.71875 C 7.7134558,6.0620005 7.2084274,6.4771924 6.9375,6.96875 C 6.6038545,7.5741002 6.4857642,8.3919875 6.375,9.3125 C 6.2642358,10.233013 6.1551074,11.306258 5.40625,12.21875 C 4.8173687,12.93631 3.7928472,13.277265 2.53125,13.4375 L 2.53125,14.46875 C 4.5119249,14.298403 5.6447647,13.783904 6.0625,13.34375 C 6.5586949,12.820926 6.5,12.53125 6.5,12.53125 C 6.4929534,12.261059 6.5950282,11.999416 6.7831848,11.80538 C 6.9713414,11.611343 7.2297197,11.501268 7.5,11.5 C 8.7100314,11.5 9.7708702,11.807465 10.5,12.5625 C 11.005067,13.085512 11.24875,13.784669 11.375,14.53125 L 13.28125,14.53125 C 12.990694,12.836887 12.221366,11.796156 11.28125,11.25 C 10.140118,10.587065 9,10.5 9,10.5 C 8.4861533,10.434579 8.1061894,9.9893393 8.1223688,9.4715975 C 8.1385483,8.9538556 8.5455711,8.5332097 9.0625,8.5 C 9.0625,8.5 12.168012,8.4764051 13.5,8.46875 C 13.504703,8.0219179 13.526621,7.9084884 13.53125,7.46875 C 12.783297,7.4790943 12.026654,7.5202371 11.125,7.34375 C 10.175282,7.157855 9.2606835,6.5802813 8.59375,5.71875 z" />
-- <path
-- sodipodi:type="arc"
-- style="fill:#f8c766;fill-opacity:1;stroke:url(#linearGradient8643);stroke-width:2.02997636999999997;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path4302"
-- sodipodi:cx="10.555883"
-- sodipodi:cy="4.0385542"
-- sodipodi:rx="5.074944"
-- sodipodi:ry="5.074944"
-- d="M 15.630827,4.0385542 A 5.074944,5.074944 0 1 1 5.4809394,4.0385542 A 5.074944,5.074944 0 1 1 15.630827,4.0385542 z"
-- transform="matrix(0.4926163,0,0,0.4926163,3.7999997,1.0105423)" />
-- <path
-- sodipodi:type="arc"
-- style="fill:none;fill-opacity:1;stroke:url(#linearGradient8692);stroke-width:3.38329338999999996;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path8682"
-- sodipodi:cx="10.555883"
-- sodipodi:cy="4.0385542"
-- sodipodi:rx="5.074944"
-- sodipodi:ry="5.074944"
-- d="M 15.630827,4.0385542 A 5.074944,5.074944 0 1 1 5.4809394,4.0385542 A 5.074944,5.074944 0 1 1 15.630827,4.0385542 z"
-- transform="matrix(0.2955698,0,0,0.2955698,5.8799995,1.8063252)" />
-- <rect
-- style="opacity:0.11574074;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
-- id="rect8649"
-- width="1"
-- height="4"
-- x="1"
-- y="12" />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/gadu-gadu.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/gadu-gadu.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/gadu-gadu.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/gadu-gadu.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,365 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="16px"
-- height="16px"
-- id="svg10335"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- sodipodi:docname="emote-select.svg"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape"
-- inkscape:export-filename="/home/hbons/Bureaublad/gadu-gadu.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90">
-- <defs
-- id="defs10337">
-- <linearGradient
-- id="linearGradient8687"
-- inkscape:collect="always">
-- <stop
-- id="stop8689"
-- offset="0"
-- style="stop-color:#f57575;stop-opacity:1" />
-- <stop
-- id="stop8691"
-- offset="1"
-- style="stop-color:#fea523;stop-opacity:0;" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8653">
-- <stop
-- style="stop-color:#a40000;stop-opacity:1;"
-- offset="0"
-- id="stop8655" />
-- <stop
-- style="stop-color:#ef2929;stop-opacity:1"
-- offset="1"
-- id="stop8657" />
-- </linearGradient>
-- <inkscape:perspective
-- sodipodi:type="inkscape:persp3d"
-- inkscape:vp_x="0 : 8 : 1"
-- inkscape:vp_y="0 : 1000 : 0"
-- inkscape:vp_z="16 : 8 : 1"
-- inkscape:persp3d-origin="8 : 5.3333333 : 1"
-- id="perspective44" />
-- <linearGradient
-- id="linearGradient11170"
-- inkscape:collect="always">
-- <stop
-- id="stop11172"
-- offset="0"
-- style="stop-color:#000000;stop-opacity:1" />
-- <stop
-- id="stop11174"
-- offset="1"
-- style="stop-color:#2e3436;stop-opacity:0;" />
-- </linearGradient>
-- <linearGradient
-- id="linearGradient11164"
-- inkscape:collect="always">
-- <stop
-- id="stop11166"
-- offset="0"
-- style="stop-color:#000000;stop-opacity:1" />
-- <stop
-- id="stop11168"
-- offset="1"
-- style="stop-color:#2e3436;stop-opacity:0;" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient22870">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop22872" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop22874" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient22870"
-- id="linearGradient20933"
-- gradientUnits="userSpaceOnUse"
-- x1="-11.187567"
-- y1="-14.181667"
-- x2="31.90255"
-- y2="35.477989" />
-- <linearGradient
-- id="linearGradient11461"
-- inkscape:collect="always">
-- <stop
-- id="stop11463"
-- offset="0"
-- style="stop-color:#fbfeac;stop-opacity:1" />
-- <stop
-- id="stop11465"
-- offset="1"
-- style="stop-color:#eedb3c;stop-opacity:0;" />
-- </linearGradient>
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient11461"
-- id="radialGradient20931"
-- gradientUnits="userSpaceOnUse"
-- cx="11.806158"
-- cy="10.04414"
-- fx="11.88395"
-- fy="6.1128922"
-- r="10.561975"
-- gradientTransform="matrix(1.9034559,3.0329373e-8,-4.2282289e-8,2.6533656,-10.666343,-17.069444)" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient22526"
-- id="linearGradient20942"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(0.8000001,0,0,0.8980646,-0.6999993,-2.2354831)"
-- x1="8.5062485"
-- y1="9.7487373"
-- x2="8.7451591"
-- y2="10.765122" />
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient22526">
-- <stop
-- style="stop-color:#f57575;stop-opacity:1"
-- offset="0"
-- id="stop22528" />
-- <stop
-- style="stop-color:#fea523;stop-opacity:0;"
-- offset="1"
-- id="stop22530" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8687"
-- id="linearGradient20915"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="translate(7.000002,1)"
-- x1="9.2937651"
-- y1="8.8493233"
-- x2="8.7171106"
-- y2="10" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient11164"
-- id="linearGradient11158"
-- gradientUnits="userSpaceOnUse"
-- x1="9.432662"
-- y1="9.6526775"
-- x2="10.732871"
-- y2="9.6526775" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient11170"
-- id="linearGradient11160"
-- gradientUnits="userSpaceOnUse"
-- x1="9.432662"
-- y1="9.6526775"
-- x2="10.732871"
-- y2="9.6526775" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8653"
-- id="linearGradient8659"
-- x1="14.605568"
-- y1="14.845765"
-- x2="9.3490162"
-- y2="3.9909718"
-- gradientUnits="userSpaceOnUse" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="31.392433"
-- inkscape:cx="15.513311"
-- inkscape:cy="8.506005"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- inkscape:grid-bbox="true"
-- inkscape:document-units="px"
-- inkscape:snap-nodes="false"
-- inkscape:snap-bbox="true"
-- objecttolerance="10"
-- gridtolerance="10"
-- inkscape:window-width="1440"
-- inkscape:window-height="847"
-- inkscape:window-x="0"
-- inkscape:window-y="0">
-- <inkscape:grid
-- type="xygrid"
-- id="grid10376"
-- visible="true"
-- enabled="true" />
-- </sodipodi:namedview>
-- <metadata
-- id="metadata10340">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- id="layer1"
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer">
-- <rect
-- style="opacity:1;fill:#a40000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
-- id="rect8683"
-- width="2.0000002"
-- height="2"
-- x="12"
-- y="12"
-- rx="1"
-- ry="1" />
-- <rect
-- style="opacity:1;fill:#a40000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
-- id="rect8685"
-- width="2.0000002"
-- height="2"
-- x="2"
-- y="12"
-- rx="1"
-- ry="1" />
-- <rect
-- style="opacity:1;fill:#ef2929;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
-- id="rect8681"
-- width="2.0000002"
-- height="2"
-- x="12"
-- y="2"
-- rx="1"
-- ry="1" />
-- <rect
-- style="opacity:1;fill:#ef2929;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
-- id="rect8679"
-- width="2.0000002"
-- height="2"
-- x="1.9999998"
-- y="2"
-- rx="1"
-- ry="1" />
-- <rect
-- style="opacity:1;fill:#a40000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
-- id="rect8675"
-- width="2.0000002"
-- height="2"
-- x="14"
-- y="7"
-- rx="1"
-- ry="1" />
-- <rect
-- style="opacity:1;fill:#ef2929;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
-- id="rect8671"
-- width="2.0000002"
-- height="2"
-- x="-2.3841858e-07"
-- y="7"
-- rx="1"
-- ry="1" />
-- <rect
-- style="opacity:1;fill:#a40000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
-- id="rect8665"
-- width="2.0000002"
-- height="2"
-- x="7"
-- y="14"
-- rx="1"
-- ry="1" />
-- <rect
-- style="opacity:1;fill:#ef2929;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
-- id="rect8663"
-- width="2.0000002"
-- height="2"
-- x="7"
-- y="0"
-- rx="1"
-- ry="1" />
-- <rect
-- inkscape:label="22x22"
-- y="-0.90471238"
-- x="-0.90471238"
-- height="17.809425"
-- width="17.809425"
-- id="rect6749"
-- style="opacity:0;fill:#d3d7cf;fill-opacity:0;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
-- <path
-- transform="matrix(0.651488,0,0,0.651488,0.30843,0.8446922)"
-- d="M 21.781414,10.983024 A 9.975256,9.975256 0 1 1 1.8309021,10.983024 A 9.975256,9.975256 0 1 1 21.781414,10.983024 z"
-- sodipodi:ry="9.975256"
-- sodipodi:rx="9.975256"
-- sodipodi:cy="10.983024"
-- sodipodi:cx="11.806158"
-- id="path17960"
-- style="opacity:1;fill:#fcaf3e;fill-opacity:1;stroke:url(#linearGradient8659);stroke-width:1.53875661000000008;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;enable-background:new"
-- sodipodi:type="arc" />
-- <path
-- transform="matrix(0.5513643,0,0,0.5513643,1.490506,1.944353)"
-- d="M 21.781414,10.983024 A 9.975256,9.975256 0 1 1 1.8309021,10.983024 A 9.975256,9.975256 0 1 1 21.781414,10.983024 z"
-- sodipodi:ry="9.975256"
-- sodipodi:rx="9.975256"
-- sodipodi:cy="10.983024"
-- sodipodi:cx="11.806158"
-- id="path17964"
-- style="opacity:1;fill:url(#radialGradient20931);fill-opacity:1;stroke:url(#linearGradient20933);stroke-width:1.81368327;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;enable-background:new"
-- sodipodi:type="arc" />
-- <path
-- id="path17966"
-- d="M 8.5000005,6.7451615 C 8.5000005,7.9844904 7.604002,8.9903231 6.500001,8.9903231 C 5.3959999,8.9903231 4.5000001,7.9844904 4.5000001,6.7451615 C 4.5000001,5.5058325 5.3959999,4.5000005 6.500001,4.5000005 C 7.604002,4.5000005 8.5000005,5.5058325 8.5000005,6.7451615 z"
-- style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:url(#linearGradient20942);stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;display:inline;enable-background:new" />
-- <path
-- sodipodi:nodetypes="cscsc"
-- id="path17974"
-- d="M 11,10 C 10.887023,11.226829 9.4422911,12 8.0000003,12 C 6.5577095,12 5.2085418,11.396721 5,10 C 5.6322481,10.739405 6.7426661,11.065616 8.0000003,11.065616 C 9.2573337,11.065616 10.367752,10.739405 11,10 z"
-- style="opacity:1;fill:#b40c0c;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;enable-background:new" />
-- <a
-- style="opacity:1;display:inline;enable-background:new"
-- id="a22276"
-- transform="matrix(0.8295523,0,0,0.9130993,-3.698956,-3.261344)">
-- <path
-- style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:url(#linearGradient20915);stroke-width:1.14899766;stroke-miterlimit:4;stroke-opacity:1;display:inline;enable-background:new"
-- d="M 18.5,11 C 18.5,12.38 17.380001,13.5 16,13.5 C 14.62,13.5 13.5,12.38 13.5,11 C 13.5,9.62 14.62,8.5 16,8.5 C 17.380001,8.5 18.5,9.62 18.5,11 z"
-- id="path22835" />
-- </a>
-- <path
-- transform="matrix(0.9747196,0,0,0.5150957,-2.4615398,2.0279474)"
-- d="M 10.732871,9.6526775 A 1.0259361,1.9413869 0 1 1 8.6809988,9.6526775 A 1.0259361,1.9413869 0 1 1 10.732871,9.6526775 z"
-- sodipodi:ry="1.9413869"
-- sodipodi:rx="1.0259361"
-- sodipodi:cy="9.6526775"
-- sodipodi:cx="9.7069349"
-- id="path17968"
-- style="opacity:1;fill:url(#linearGradient11160);fill-opacity:1;stroke:none;stroke-width:0.98640186;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;enable-background:new"
-- sodipodi:type="arc" />
-- <path
-- transform="matrix(-0.9747196,0,0,0.5150957,18.46154,2.0279474)"
-- d="M 10.732871,9.6526775 A 1.0259361,1.9413869 0 1 1 8.6809988,9.6526775 A 1.0259361,1.9413869 0 1 1 10.732871,9.6526775 z"
-- sodipodi:ry="1.9413869"
-- sodipodi:rx="1.0259361"
-- sodipodi:cy="9.6526775"
-- sodipodi:cx="9.7069349"
-- id="path11156"
-- style="opacity:1;fill:url(#linearGradient11158);fill-opacity:1;stroke:none;stroke-width:0.98640186;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;enable-background:new"
-- sodipodi:type="arc" />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/icq.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/icq.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/icq.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/icq.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,579 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="16px"
-- height="16px"
-- id="svg4248"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/16"
-- sodipodi:docname="icq.svg"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape"
-- inkscape:export-filename="/home/hbons/Bureaublad/icq.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90">
-- <defs
-- id="defs4250">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8780">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8782" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8784" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8772">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8774" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8776" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8764">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8766" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8768" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8756">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8758" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8760" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8748">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8750" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8752" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8740">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8742" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8744" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8732">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8734" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8736" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8724">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8726" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8728" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8716">
-- <stop
-- style="stop-color:#4e9a06;stop-opacity:1;"
-- offset="0"
-- id="stop8718" />
-- <stop
-- style="stop-color:#2a5402;stop-opacity:1"
-- offset="1"
-- id="stop8720" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8708">
-- <stop
-- style="stop-color:#4e9a06;stop-opacity:1;"
-- offset="0"
-- id="stop8710" />
-- <stop
-- style="stop-color:#346804;stop-opacity:1"
-- offset="1"
-- id="stop8712" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8700">
-- <stop
-- style="stop-color:#b90000;stop-opacity:1"
-- offset="0"
-- id="stop8702" />
-- <stop
-- style="stop-color:#6c0000;stop-opacity:1"
-- offset="1"
-- id="stop8704" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8692">
-- <stop
-- style="stop-color:#4e9a06;stop-opacity:1;"
-- offset="0"
-- id="stop8694" />
-- <stop
-- style="stop-color:#3c7604;stop-opacity:1"
-- offset="1"
-- id="stop8696" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8684">
-- <stop
-- style="stop-color:#4e9a06;stop-opacity:1;"
-- offset="0"
-- id="stop8686" />
-- <stop
-- style="stop-color:#356a04;stop-opacity:1"
-- offset="1"
-- id="stop8688" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8676">
-- <stop
-- style="stop-color:#4e9a06;stop-opacity:1;"
-- offset="0"
-- id="stop8678" />
-- <stop
-- style="stop-color:#346803;stop-opacity:1"
-- offset="1"
-- id="stop8680" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8668">
-- <stop
-- style="stop-color:#4e9a06;stop-opacity:1;"
-- offset="0"
-- id="stop8670" />
-- <stop
-- style="stop-color:#336603;stop-opacity:1"
-- offset="1"
-- id="stop8672" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8660">
-- <stop
-- style="stop-color:#4e9a06;stop-opacity:1;"
-- offset="0"
-- id="stop8662" />
-- <stop
-- style="stop-color:#3a7404;stop-opacity:1"
-- offset="1"
-- id="stop8664" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8652">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8654" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8656" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8644">
-- <stop
-- style="stop-color:#c4a000;stop-opacity:1;"
-- offset="0"
-- id="stop8646" />
-- <stop
-- style="stop-color:#907600;stop-opacity:1"
-- offset="1"
-- id="stop8648" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2321">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2323" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0"
-- offset="1"
-- id="stop2325" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2361">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2363" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2365" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2321"
-- id="linearGradient4381"
-- gradientUnits="userSpaceOnUse"
-- x1="11.787398"
-- y1="11.115861"
-- x2="12.075002"
-- y2="12.360133" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2361"
-- id="linearGradient4383"
-- gradientUnits="userSpaceOnUse"
-- x1="6.3009863"
-- y1="8.3052416"
-- x2="6.3009863"
-- y2="17.320574"
-- gradientTransform="matrix(0.7516425,0,0,0.6729501,-0.8826506,1.4152198)" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8644"
-- id="linearGradient8650"
-- x1="6.5158038"
-- y1="6.3653116"
-- x2="9.9300232"
-- y2="10.764107"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8652"
-- id="linearGradient8658"
-- x1="10.444659"
-- y1="12.360133"
-- x2="13.705344"
-- y2="12.360133"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8660"
-- id="linearGradient8666"
-- x1="9.8111737"
-- y1="4.9999985"
-- x2="17.188837"
-- y2="4.9999985"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(0.666684,0,0,0.8570726,0.499765,-0.7853612)" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8668"
-- id="linearGradient8674"
-- x1="15.004629"
-- y1="16.519621"
-- x2="16.441046"
-- y2="19.245642"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8676"
-- id="linearGradient8682"
-- x1="11.152212"
-- y1="15.892158"
-- x2="9.9561481"
-- y2="19.775995"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8684"
-- id="linearGradient8690"
-- x1="13.906936"
-- y1="12.503142"
-- x2="22.096945"
-- y2="12.503142"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8692"
-- id="linearGradient8698"
-- x1="17.85483"
-- y1="7.9999962"
-- x2="19.682709"
-- y2="9.6703825"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8700"
-- id="linearGradient8706"
-- x1="5.3079047"
-- y1="14.33169"
-- x2="6.2636456"
-- y2="16.783527"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8708"
-- id="linearGradient8714"
-- x1="4.4860797"
-- y1="2.7814157"
-- x2="6.3950372"
-- y2="4.8916488"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8716"
-- id="linearGradient8722"
-- x1="6.2442408"
-- y1="8.825284"
-- x2="7.2848325"
-- y2="12.785048"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8724"
-- id="linearGradient8730"
-- x1="13.914243"
-- y1="3.5516012"
-- x2="12.632175"
-- y2="7.0243564"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(0.507229,0,0,0.7963119,2.6510069,-0.4796384)" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8732"
-- id="linearGradient8738"
-- x1="8.2830858"
-- y1="4.66011"
-- x2="10.320723"
-- y2="6.5236211"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(0.658982,0,0,0.733665,-0.42174,-4.3113681e-2)" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8740"
-- id="linearGradient8746"
-- x1="4.4425683"
-- y1="8.8338633"
-- x2="8.630022"
-- y2="10.278849"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(0.8000894,0,0,0.761045,-1.308226,-0.22823)" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8748"
-- id="linearGradient8754"
-- x1="19.372143"
-- y1="6.7050757"
-- x2="15.963639"
-- y2="9.5312366"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(0.7538717,0,0,0.6730629,-1.1855766,0.1251422)" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8756"
-- id="linearGradient8762"
-- x1="19.567648"
-- y1="13.050652"
-- x2="15.45147"
-- y2="12.219797"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8764"
-- id="linearGradient8770"
-- x1="16.516554"
-- y1="18.227236"
-- x2="14.661788"
-- y2="15.899495"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(0.6456695,0,0,0.740569,0.8060648,-0.220494)" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8772"
-- id="linearGradient8778"
-- x1="10.093229"
-- y1="18.792187"
-- x2="10.940947"
-- y2="15.521823"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(0.7610362,0,0,0.799758,-0.9891698,-1.10256)" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8780"
-- id="linearGradient8786"
-- x1="4.1927366"
-- y1="16.487579"
-- x2="6.7825565"
-- y2="14.544259"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(0.7516425,0,0,0.6729501,-0.8826506,1.4152198)" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="33.645576"
-- inkscape:cx="17.956733"
-- inkscape:cy="7.8216704"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- inkscape:grid-bbox="true"
-- inkscape:document-units="px"
-- inkscape:window-width="1440"
-- inkscape:window-height="847"
-- inkscape:window-x="0"
-- inkscape:window-y="0"
-- objecttolerance="10"
-- gridtolerance="10"
-- inkscape:snap-bbox="true"
-- inkscape:snap-nodes="false">
-- <inkscape:grid
-- type="xygrid"
-- id="grid7872"
-- visible="true"
-- enabled="true" />
-- </sodipodi:namedview>
-- <metadata
-- id="metadata4253">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- id="layer1"
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer">
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient8674);stroke-width:1.21922076000000001;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 12.963148,17.247339 C 12.171926,14.859179 12.454176,14.470485 13.497752,13.880864 C 14.541326,13.291244 15.108816,13.335817 16.744216,15.111033 C 17.767103,16.844843 17.750309,18.730526 16.706739,19.320144 C 15.663162,19.909767 13.986034,18.981148 12.963148,17.247339 z "
-- id="path2226"
-- transform="matrix(0.801314,0,0,0.839525,-1.523412,-1.868634)" />
-- <path
-- style="opacity:0.75;fill:none;fill-opacity:1;stroke:url(#linearGradient8770);stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 10.228804,10.517757 C 10.129288,10.479606 10.118014,10.490039 9.8252606,10.679756 C 9.6724455,10.778787 9.5775476,10.848926 9.5427802,10.888041 C 9.5080129,10.927156 9.5107318,10.913111 9.5024259,10.957469 C 9.4869472,11.040134 9.5429901,11.490751 9.7445519,12.230322 C 10.019277,12.740003 10.386743,13.148547 10.692879,13.341176 C 11.011903,13.541914 11.205257,13.517117 11.298194,13.45689 C 11.392617,13.395699 11.497569,13.253133 11.499966,12.855177 C 11.502252,12.475722 11.370376,11.941058 11.1166,11.420325 C 10.645066,10.845418 10.310619,10.549121 10.228804,10.517757 z"
-- id="path2242" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient8690);stroke-width:1.18385111999999992;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 16.771005,15.319703 C 14.33106,13.896777 14.27539,13.249081 14.702189,11.643547 C 15.128987,10.03802 15.633686,9.5050301 18.317374,9.5025628 C 20.461323,10.081613 21.854951,11.854605 21.428153,13.460133 C 21.001355,15.065667 18.914955,15.898753 16.771005,15.319703 z "
-- id="path2216"
-- transform="matrix(0.856389,0,0,0.833173,-2.916658,-1.417277)" />
-- <path
-- style="opacity:0.75;fill:none;fill-opacity:1;stroke:url(#linearGradient8762);stroke-width:1.30062020000000000;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 18.15625,10.5 C 17.064518,10.522558 16.402045,10.67233 16.1875,10.8125 C 15.955817,10.963867 15.820346,11.171396 15.625,11.90625 C 15.423716,12.663442 15.422318,12.879125 15.53125,13.09375 C 15.632536,13.29331 16.159381,13.76998 17.15625,14.375 C 17.98874,14.571156 18.819892,14.51269 19.40625,14.28125 C 20.02513,14.036974 20.378057,13.677476 20.5,13.21875 C 20.621263,12.762585 20.482161,12.251369 20.0625,11.71875 C 19.662743,11.211393 18.978208,10.748423 18.15625,10.5 z "
-- id="path2238"
-- transform="matrix(0.786923,0,0,0.751219,-1.665053,-0.387804)" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient8698);stroke-width:1.22383844999999991;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 18.231066,10.043051 C 15.826638,10.834882 15.435297,10.552414 14.841659,9.5080341 C 14.248025,8.4636559 14.292902,7.895729 16.08021,6.2590696 C 17.825828,5.235395 19.724355,5.2521994 20.317989,6.2965763 C 20.911627,7.3409564 19.976685,9.0193762 18.231066,10.043051 z "
-- id="path2224"
-- transform="matrix(0.833845,0,0,0.800696,-2.590942,-0.905561)" />
-- <path
-- style="fill:#ef2929;fill-opacity:1;stroke:url(#linearGradient8706);stroke-width:1.22309434000000006;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 7.2295458,17.045044 C 4.8262841,17.837501 4.435133,17.554808 3.8417836,16.509603 C 3.2484366,15.464398 3.2932918,14.896022 5.0797326,13.258068 C 6.8245041,12.233585 8.7221095,12.250402 9.3154554,13.295606 C 9.9088085,14.34081 8.9743169,16.020559 7.2295458,17.045044 z "
-- id="path2228"
-- transform="matrix(0.835521,0,0,0.800063,-1.432383,-0.501236)" />
-- <path
-- style="opacity:0.75;fill:url(#linearGradient4383);fill-opacity:1;stroke:url(#linearGradient8786);stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 4.8486235,10.500046 C 4.4564782,10.496935 3.9190242,10.637124 3.3923161,10.899611 C 2.8449198,11.364365 2.5603453,11.685808 2.5232295,11.782857 C 2.4833052,11.88725 2.475064,11.884191 2.6641625,12.182421 C 2.765801,12.342716 2.8393005,12.443491 2.8755619,12.476837 C 2.9118233,12.510183 2.8851423,12.490643 2.9225396,12.497866 C 2.9909999,12.51109 3.4626384,12.466271 4.1909363,12.26654 C 4.7259059,11.978527 5.1414644,11.620122 5.3418889,11.299174 C 5.5465286,10.971477 5.5126093,10.773335 5.4593331,10.689313 C 5.4086116,10.60932 5.2638969,10.503341 4.8486235,10.500046 z"
-- id="path2244" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient8682);stroke-width:1.18253027999999993;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 7.6891342,15.77365 C 9.1118334,13.334726 9.7586709,13.278647 11.361671,13.703963 C 12.964665,14.129276 13.496553,14.633183 13.497097,17.314646 C 12.917316,19.457228 11.145785,20.850948 9.5427895,20.425634 C 7.93979,20.000318 7.109353,17.916231 7.6891342,15.77365 z "
-- id="path2218"
-- transform="matrix(0.834348,0,0,0.857095,-1.761273,-2.072186)" />
-- <path
-- style="opacity:0.75;fill:none;fill-opacity:1;stroke:url(#linearGradient8778);stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 6.5498451,10.543916 C 6.4093043,10.616602 6.0575323,11.02735 5.5985498,11.81853 C 5.4505732,12.478908 5.4715025,13.128474 5.6461146,13.592993 C 5.8305566,14.083663 6.1144425,14.372852 6.4547155,14.467729 C 6.7934078,14.562164 7.1943156,14.450544 7.5962698,14.117834 C 7.9788085,13.801196 8.3117436,13.270312 8.5000003,12.618288 C 8.4834797,11.748172 8.3825717,11.225309 8.2859589,11.068757 C 8.1814922,10.899479 8.0370643,10.799946 7.4773579,10.643886 C 6.8871683,10.479326 6.6912608,10.470777 6.5498451,10.543916 z"
-- id="path2240" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient8714);stroke-width:1.00000142999999997;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 7.1358685,3.3890634 C 7.7698834,5.3939828 7.5437147,5.7203005 6.707483,6.2153016 C 5.8712512,6.7103014 5.4165141,6.6728807 4.1060474,5.1825438 C 3.2863948,3.7269694 3.29985,2.1438938 4.1360794,1.6488936 C 4.9723098,1.1538927 6.3162154,1.933489 7.1358685,3.3890634 z"
-- id="path2222" />
-- <path
-- style="opacity:0.75;fill:none;fill-opacity:1;stroke:url(#linearGradient8738);stroke-width:0.99999988;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 4.9118956,2.5017868 C 4.8344656,2.4933075 4.7351802,2.5160688 4.6853705,2.5476409 C 4.5947769,2.6050638 4.5024975,2.7622504 4.5000318,3.1666707 C 4.4976449,3.5581659 4.6240111,4.1063439 4.8913024,4.6340007 C 5.3464159,5.169468 5.6802006,5.4473321 5.7768094,5.4823009 C 5.8806263,5.5198786 5.8903157,5.5109256 6.1886732,5.3218116 C 6.3467933,5.2215868 6.4419865,5.153277 6.4769778,5.1154684 C 6.5119691,5.0776597 6.4898306,5.0865385 6.497571,5.0466873 C 6.5117411,4.9737348 6.4672348,4.52308 6.2710459,3.8086276 C 5.8382221,3.0048392 5.2079215,2.5342044 4.9118956,2.5017868 z"
-- id="path2232" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient8722);stroke-width:1.18378782000000005;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 7.2320598,6.6863636 C 9.6715923,8.1091434 9.7272104,8.7568487 9.3003538,10.362442 C 8.8734993,11.96803 8.3688269,12.501065 5.6854848,12.503723 C 3.5418523,11.924813 2.1485268,10.151886 2.5753806,8.5462983 C 3.002236,6.9407045 5.0884273,6.1074547 7.2320598,6.6863636 z "
-- id="path2220"
-- transform="matrix(0.8565,0,0,0.833155,-1.639952,-0.917534)" />
-- <path
-- style="opacity:0.75;fill:none;fill-opacity:1;stroke:url(#linearGradient8746);stroke-width:1.00000083;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 4.1673858,5.5985208 C 3.5054714,5.4505063 2.8569334,5.4716193 2.3921875,5.6460861 C 1.9012783,5.8303746 1.6129084,6.1118678 1.5170897,6.4546964 C 1.4218347,6.7955083 1.5091367,7.1942976 1.842126,7.5962639 C 2.1592142,7.9790353 2.7135907,8.3119339 3.3672964,8.5000048 C 4.2422495,8.4831842 4.7779308,8.3858367 4.9424724,8.2859609 C 5.1201805,8.1780935 5.2118965,8.0341525 5.3675199,7.4773506 C 5.5280018,6.9031664 5.529332,6.7148477 5.4425283,6.549827 C 5.3619401,6.3966226 4.9589342,6.0564559 4.1673858,5.5985208 z"
-- id="path2234" />
-- <path
-- style="opacity:0.75;fill:none;fill-opacity:1;stroke:url(#linearGradient8754);stroke-width:1.00000203;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 12.855285,4.500051 C 12.462919,4.4969506 11.922943,4.6374156 11.394658,4.8996821 C 10.844605,5.3646776 10.559734,5.7082145 10.522993,5.8041104 C 10.483512,5.9071611 10.474936,5.8852008 10.664344,6.1827083 C 10.766342,6.3429165 10.840542,6.4443185 10.876371,6.4771733 C 10.9122,6.5100281 10.886952,6.4911647 10.923488,6.4982065 C 10.991576,6.5113294 11.462538,6.4555529 12.219205,6.2458079 C 12.737907,5.9609072 13.130324,5.6126604 13.326454,5.2993132 C 13.531108,4.9723484 13.51988,4.7711454 13.467804,4.68935 C 13.41783,4.6108533 13.270794,4.5033345 12.855285,4.500051 z"
-- id="path2236" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient8666);stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 11.375232,4.5493545 C 10.422975,6.6416097 9.9911458,6.6905364 8.9215873,6.3281422 C 7.8520275,5.9657484 7.4975249,5.534567 7.5000157,3.2363329 C 7.8893038,1.3991926 9.0732966,0.20229738 10.142856,0.56469125 C 11.212416,0.92708537 11.764519,2.7122143 11.375232,4.5493545 z"
-- id="path2192" />
-- <path
-- style="opacity:0.75;fill:none;fill-opacity:1;stroke:url(#linearGradient8730);stroke-width:1.00000024;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 9.8631692,1.5360262 C 9.6347437,1.4415107 9.3708203,1.5274542 9.1023257,1.8595278 C 8.8466524,2.1757441 8.6265865,2.7251574 8.4999913,3.3774976 C 8.5099761,4.2473344 8.5751845,4.7795065 8.6426495,4.9452367 C 8.7155134,5.124228 8.8111337,5.2149983 9.1815803,5.3682774 C 9.5648319,5.5268552 9.6889381,5.5298463 9.7997656,5.4429315 C 9.9026575,5.3622401 10.127302,4.9625969 10.433802,4.1738094 C 10.533317,3.5150226 10.518933,2.8709279 10.4021,2.4069923 C 10.27869,1.9169393 10.091661,1.6305687 9.8631692,1.5360262 z"
-- id="path2230" />
-- <path
-- style="fill:#edd400;fill-opacity:1;stroke:url(#linearGradient8650);stroke-width:0.99999994000000003;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 10.411141,8.6353601 C 10.047567,9.96976 8.6723022,10.768109 7.3413532,10.417389 C 6.0104022,10.066669 5.2252873,8.6990358 5.5888616,7.3646359 C 5.9524355,6.0302378 7.3277,5.231889 8.6586509,5.5826094 C 9.9895999,5.9333292 10.774715,7.300962 10.411141,8.6353601 z"
-- id="path1317" />
-- <path
-- transform="matrix(1.208973,0.318578,-0.279444,1.025629,-3.144373,-8.523741)"
-- style="opacity:0.69907406999999999;fill:url(#linearGradient4381);fill-opacity:1;stroke:url(#linearGradient8658);stroke-width:0.86744213000000003;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 13.271623,12.360133 C 13.271623,13.140766 12.735537,13.774323 12.075002,13.774323 C 11.414466,13.774323 10.87838,13.140766 10.87838,12.360133 C 10.87838,11.579501 11.414466,10.945944 12.075002,10.945944 C 12.735537,10.945944 13.271623,11.579501 13.271623,12.360133 z "
-- id="path2319" />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/meanwhile.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/meanwhile.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/meanwhile.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/meanwhile.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,218 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="16px"
-- height="16px"
-- id="svg4239"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/16/scalable"
-- sodipodi:docname="meanwhile.svg"
-- inkscape:export-filename="/home/hbons/Bureaublad/meanwhile.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs4241">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8675">
-- <stop
-- style="stop-color:#fcaf3e;stop-opacity:1;"
-- offset="0"
-- id="stop8677" />
-- <stop
-- style="stop-color:#f57900;stop-opacity:1"
-- offset="1"
-- id="stop8679" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8667">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8669" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8671" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8650">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8652" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8654" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8642">
-- <stop
-- style="stop-color:#ce5c00;stop-opacity:1;"
-- offset="0"
-- id="stop8644" />
-- <stop
-- style="stop-color:#9f3400;stop-opacity:1"
-- offset="1"
-- id="stop8646" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8634">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8636" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8638" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8634"
-- id="linearGradient8640"
-- x1="9.2996664"
-- y1="-1.1926658"
-- x2="22.00433"
-- y2="12.53125"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8642"
-- id="linearGradient8648"
-- x1="8.701582"
-- y1="8.7882452"
-- x2="14.751598"
-- y2="21.009844"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8650"
-- id="linearGradient8656"
-- x1="5.3650107"
-- y1="-2.7280362"
-- x2="16.534615"
-- y2="7.1899891"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8642"
-- id="linearGradient8661"
-- gradientUnits="userSpaceOnUse"
-- x1="8.701582"
-- y1="8.7882452"
-- x2="14.751598"
-- y2="21.009844" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8667"
-- id="linearGradient8673"
-- x1="2.0414412"
-- y1="-0.75497365"
-- x2="26.409824"
-- y2="23.59227"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8675"
-- id="linearGradient8681"
-- x1="13.609824"
-- y1="12.881368"
-- x2="13.609824"
-- y2="19.507627"
-- gradientUnits="userSpaceOnUse" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="27.3287"
-- inkscape:cx="20.064702"
-- inkscape:cy="8.5317934"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- inkscape:grid-bbox="true"
-- inkscape:document-units="px"
-- inkscape:window-width="1440"
-- inkscape:window-height="847"
-- inkscape:window-x="0"
-- inkscape:window-y="0"
-- inkscape:snap-bbox="true"
-- inkscape:snap-nodes="false"
-- objecttolerance="10"
-- gridtolerance="10">
-- <inkscape:grid
-- type="xygrid"
-- id="grid7858"
-- visible="true"
-- enabled="true" />
-- </sodipodi:namedview>
-- <metadata
-- id="metadata4244">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- id="layer1"
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer">
-- <path
-- sodipodi:type="arc"
-- style="fill:#fcaf3e;fill-opacity:1;stroke:#ce5c00;stroke-width:2.02997327000000016;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path4302"
-- sodipodi:cx="10.555883"
-- sodipodi:cy="4.0385542"
-- sodipodi:rx="5.074944"
-- sodipodi:ry="5.074944"
-- d="M 15.630827,4.0385542 A 5.074944,5.074944 0 1 1 5.4809394,4.0385542 A 5.074944,5.074944 0 1 1 15.630827,4.0385542 z"
-- transform="matrix(0.4926164,0,0,0.4926165,2.7999985,1.0105418)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:none;fill-opacity:1;stroke:url(#linearGradient8656);stroke-width:3.38329315000000008;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path4273"
-- sodipodi:cx="10.555883"
-- sodipodi:cy="4.0385542"
-- sodipodi:rx="5.074944"
-- sodipodi:ry="5.074944"
-- d="M 15.630827,4.0385542 A 5.074944,5.074944 0 1 1 5.4809394,4.0385542 A 5.074944,5.074944 0 1 1 15.630827,4.0385542 z"
-- transform="matrix(0.2955698,0,0,0.2955699,4.8799997,1.8063249)" />
-- <path
-- style="fill:url(#linearGradient8681);fill-opacity:1;stroke:url(#linearGradient8648);stroke-width:1.38365983999999997;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 18.764798,2.8497364 C 18.764798,6.4835545 17.015921,10.340055 12.458352,10.340055 C 7.9302336,10.340055 6.1696302,5.9347403 6.1696302,3.0077289 L 3.5191672,5.0743501 C 3.5191672,11.592509 7.7563904,12.376951 7.7563904,13.61498 C 7.7563904,14.942901 3.5055266,16.358274 3.5055266,21.425015 L 9.1348464,21.369834 C 9.1348464,19.244403 10.433516,15.786914 12.492742,15.786914 C 14.516622,15.786914 15.962656,19.213604 15.962656,21.335386 L 21.491428,21.351408 C 21.491428,15.947962 17.306969,15.024839 17.306969,13.58672 C 17.306969,12.395751 21.452377,11.632096 21.452377,5.0650054 L 18.764798,2.8497364 z"
-- id="rect2213"
-- sodipodi:nodetypes="czccccczccccc"
-- transform="matrix(0.725563,0,0,0.719891,-1.060965,0.139182)" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-1.3863388"
-- inkscape:original="M 18.75 2.84375 C 18.750001 6.477568 17.026319 10.34375 12.46875 10.34375 C 7.9406315 10.34375 6.15625 5.9270114 6.15625 3 L 3.53125 5.0625 C 3.53125 11.580659 7.75 12.386971 7.75 13.625 C 7.7499998 14.952921 3.5 16.370759 3.5 21.4375 L 9.125 21.375 C 9.1249997 19.249568 10.440774 15.78125 12.5 15.78125 C 14.52388 15.78125 15.96875 19.221968 15.96875 21.34375 L 21.5 21.34375 C 21.5 15.940304 17.3125 15.031869 17.3125 13.59375 C 17.3125 12.402781 21.4375 11.629591 21.4375 5.0625 L 18.75 2.84375 z "
-- style="fill:none;fill-opacity:1;stroke:url(#linearGradient8673);stroke-width:1.38365983999999997;stroke-miterlimit:4;stroke-opacity:1"
-- id="path8663"
-- d="M 19.8125,5.5 C 19.553993,6.6500796 19.130624,7.7658345 18.4375,8.75 C 17.214147,10.487035 15.139545,11.71875 12.46875,11.71875 C 9.7539446,11.71875 7.6786908,10.319904 6.46875,8.5625 C 5.8161471,7.614613 5.3955271,6.5877094 5.125,5.5625 L 5,5.65625 C 5.1326144,8.1177354 5.8516259,9.5128134 6.65625,10.40625 C 7.0969248,10.895565 7.5574921,11.26294 8,11.65625 C 8.2212539,11.852905 8.4668482,12.050594 8.6875,12.34375 C 8.9081518,12.636906 9.125,13.076568 9.125,13.625 C 9.1249998,14.696474 8.5196644,15.229886 8.0625,15.6875 C 7.6053356,16.145114 7.1243156,16.554217 6.65625,17.0625 C 5.973649,17.803752 5.4431444,18.79741 5.15625,20.03125 L 7.90625,20 C 8.0647552,19.034828 8.3367207,18.075404 8.8125,17.15625 C 9.5156693,15.797803 10.692058,14.40625 12.5,14.40625 C 14.29756,14.40625 15.483981,15.747434 16.21875,17.09375 C 16.715676,18.004266 16.982752,18.998 17.15625,19.96875 L 19.84375,19.96875 C 19.573522,18.630932 19.078136,17.632125 18.40625,16.9375 C 17.956341,16.472365 17.46334,16.095102 17,15.65625 C 16.53666,15.217398 15.9375,14.626068 15.9375,13.59375 C 15.9375,13.044739 16.156655,12.598898 16.375,12.3125 C 16.593345,12.026102 16.816217,11.846739 17.03125,11.65625 C 17.461317,11.275273 17.91606,10.919853 18.34375,10.4375 C 19.12911,9.5517623 19.845064,8.1414304 19.96875,5.625 L 19.8125,5.5 z"
-- transform="matrix(0.725563,0,0,0.719891,-1.060965,0.139182)" />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/msn.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/msn.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/msn.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/msn.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,352 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="16px"
-- height="16px"
-- id="svg4239"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/16/scalable"
-- sodipodi:docname="msn.svg"
-- inkscape:export-filename="/home/hbons/Bureaublad/msn.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs4241">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8709">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8711" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8713" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8701">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8703" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8705" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8693">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8695" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8697" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8685">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8687" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8689" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8677">
-- <stop
-- style="stop-color:#5c3566;stop-opacity:1;"
-- offset="0"
-- id="stop8679" />
-- <stop
-- style="stop-color:#874e96;stop-opacity:1"
-- offset="1"
-- id="stop8681" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8660">
-- <stop
-- style="stop-color:#275ba6;stop-opacity:1"
-- offset="0"
-- id="stop8662" />
-- <stop
-- style="stop-color:#183765;stop-opacity:1"
-- offset="1"
-- id="stop8664" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8652">
-- <stop
-- style="stop-color:#4e9a06;stop-opacity:1;"
-- offset="0"
-- id="stop8654" />
-- <stop
-- style="stop-color:#2f5f02;stop-opacity:1"
-- offset="1"
-- id="stop8656" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8644">
-- <stop
-- style="stop-color:#c4a000;stop-opacity:1;"
-- offset="0"
-- id="stop8646" />
-- <stop
-- style="stop-color:#786300;stop-opacity:1"
-- offset="1"
-- id="stop8648" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8636">
-- <stop
-- style="stop-color:#ce5d00;stop-opacity:1;"
-- offset="0"
-- id="stop8638" />
-- <stop
-- style="stop-color:#833b00;stop-opacity:1"
-- offset="1"
-- id="stop8640" />
-- </linearGradient>
-- <linearGradient
-- id="linearGradient2219"
-- inkscape:collect="always">
-- <stop
-- id="stop2221"
-- offset="0"
-- style="stop-color:#3465a4;stop-opacity:1;" />
-- <stop
-- id="stop2223"
-- offset="1"
-- style="stop-color:#3465a4;stop-opacity:0;" />
-- </linearGradient>
-- <linearGradient
-- id="linearGradient2228"
-- inkscape:collect="always">
-- <stop
-- id="stop2230"
-- offset="0"
-- style="stop-color:#f56600;stop-opacity:1;" />
-- <stop
-- id="stop2232"
-- offset="1"
-- style="stop-color:#f56600;stop-opacity:0;" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2228"
-- id="linearGradient4505"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(0.782765,0,0,0.747651,1.035995,0.614065)"
-- x1="20.007692"
-- y1="13.250565"
-- x2="18.727983"
-- y2="17.102213" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2219"
-- id="linearGradient4507"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(0.5438817,0,0,0.5799505,-0.3274572,-0.2722861)"
-- x1="10.200594"
-- y1="14.726058"
-- x2="13.252806"
-- y2="18.174761" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8636"
-- id="linearGradient8642"
-- x1="16.397886"
-- y1="7.1729202"
-- x2="19.359613"
-- y2="12.699073"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8644"
-- id="linearGradient8650"
-- x1="17.004478"
-- y1="15.059639"
-- x2="19.158651"
-- y2="19.232847"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(0.8565497,0,0,0.700607,-3.0651761,-0.162781)" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8652"
-- id="linearGradient8658"
-- x1="11.425816"
-- y1="15.977947"
-- x2="13.070351"
-- y2="19.869415"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8660"
-- id="linearGradient8666"
-- x1="1.1384629"
-- y1="4.3090925"
-- x2="6.360837"
-- y2="9.665041"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8677"
-- id="linearGradient8683"
-- x1="9.734354"
-- y1="10.855804"
-- x2="8.227417"
-- y2="7.5956616"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8685"
-- id="linearGradient8691"
-- x1="2.27721"
-- y1="6.7656131"
-- x2="10.084975"
-- y2="12.919206"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8709"
-- id="linearGradient8733"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(0.789526,0,0,0.621298,-1.921384,0.986574)"
-- x1="18.850323"
-- y1="18.158928"
-- x2="17.372902"
-- y2="13.093926" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8701"
-- id="linearGradient8742"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(0.599236,0,0,0.624815,0.408284,1.315959)"
-- x1="12.687945"
-- y1="18.895752"
-- x2="11.633714"
-- y2="15.440485" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8693"
-- id="linearGradient8745"
-- gradientUnits="userSpaceOnUse"
-- x1="13.573946"
-- y1="3.1337965"
-- x2="11.223683"
-- y2="8.5642729" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="27.3287"
-- inkscape:cx="20.590777"
-- inkscape:cy="9.6812143"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- inkscape:grid-bbox="true"
-- inkscape:document-units="px"
-- inkscape:window-width="1430"
-- inkscape:window-height="837"
-- inkscape:window-x="254"
-- inkscape:window-y="427"
-- inkscape:snap-nodes="false"
-- inkscape:snap-bbox="true"
-- objecttolerance="10"
-- gridtolerance="10">
-- <inkscape:grid
-- type="xygrid"
-- id="grid7864"
-- visible="true"
-- enabled="true" />
-- </sodipodi:namedview>
-- <metadata
-- id="metadata4244">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- id="layer1"
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer">
-- <path
-- style="fill:#edd400;fill-opacity:1;stroke:url(#linearGradient8650);stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
-- d="M 12.726618,6.7821693 C 14.954366,7.315014 15.232686,13.499992 12.702089,13.499992 C 10.20215,13.499992 4.63567,4.846936 12.726618,6.7821693 z"
-- id="rect2194" />
-- <path
-- style="opacity:0.5;fill:none;fill-opacity:1;stroke:url(#linearGradient8733);stroke-width:1.00000119;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 10.464305,7.5102029 C 10.084666,7.5060849 9.6095224,7.6779929 9.5306688,8.0961333 C 9.4083085,8.8812767 9.7824927,9.6266355 10.172483,10.280772 C 10.718966,11.141573 11.429181,11.932478 12.346756,12.402887 C 12.624698,12.609701 12.991224,12.391706 13.128703,12.12186 C 13.685105,10.954392 13.588008,9.5514732 13.062635,8.3912413 C 12.867487,7.9910733 12.482071,7.658617 12.022113,7.639864 C 11.508321,7.5519031 10.987071,7.4717107 10.464305,7.5102029 z"
-- id="path2259" />
-- <path
-- transform="matrix(0.712542,0,0,0.698139,-0.834614,0.18154)"
-- style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient8658);stroke-width:1.41783130000000002;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 13.316085,20.509475 C 10.851196,20.509475 4.3258741,14.508937 9.3204332,11.066555 C 14.310647,7.6271659 15.818731,20.509475 13.316085,20.509475 z "
-- id="rect2201" />
-- <path
-- style="opacity:0.5;fill:none;fill-opacity:1;stroke:url(#linearGradient8742);stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 6.9969196,8.5005798 C 6.4095407,8.5652754 5.9363988,9.0353859 5.6504082,9.5247059 C 5.3128668,10.187546 5.6118436,10.924286 5.9818793,11.497377 C 6.4590192,12.279805 7.2102283,12.858859 7.9986562,13.300897 C 8.6344334,13.702713 8.4099456,12.64584 8.4957981,12.27224 C 8.4979791,11.096105 8.2902419,9.8546211 7.6065424,8.8720886 C 7.4570093,8.6818207 7.2484632,8.5134511 6.9969196,8.5005798 z"
-- id="path2254" />
-- <path
-- transform="matrix(0.720961,0,0,0.718898,-0.697672,-0.282723)"
-- style="opacity:0.25;fill:none;fill-opacity:1;stroke:white;stroke-width:1.389027;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 20,3.5 C 18.995087,3.678281 17.104383,5.3426949 15.71875,7.0625 C 14.498278,8.5773128 13.796939,9.7027104 13.59375,10.03125 L 15.0625,13.375 C 17.799931,13.187054 19.57299,12.186552 19.84375,12 C 19.951969,11.755173 20.691026,10.13991 21.15625,8.125 C 21.405718,7.0445423 21.52736,5.9263632 21.4375,5.09375 C 21.34764,4.2611368 21.117806,3.8050199 20.65625,3.5625 C 20.487599,3.4738843 20.316754,3.4438049 20,3.5 z "
-- id="path2245" />
-- <path
-- style="fill:url(#linearGradient4507);fill-opacity:1;stroke:url(#linearGradient8666);stroke-width:1.00000106999999994;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 0.66009074,3.7661675 C 1.638065,2.0184654 11.689407,9.4126942 7.470982,10.391083 C 3.2580442,11.368199 -0.30791802,5.4960608 0.66009074,3.7661675 z"
-- id="rect2197" />
-- <path
-- transform="matrix(0.666514,0,0,0.713565,-0.165619,-0.134566)"
-- style="opacity:0.50000000000000000;fill:none;fill-opacity:1;stroke:url(#linearGradient8691);stroke-width:1.45003652999999999;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 2.9037792,8.1978741 C 3.2143877,9.0316623 3.9610232,9.9051913 4.759397,10.781009 C 6.3561448,12.532642 8.35926,13.89948 10.765977,13.389526 C 11.255672,13.285765 11.400406,13.151715 11.448617,13.081331 C 11.496824,13.010949 11.537361,12.912219 11.448617,12.641053 C 11.271127,12.098721 10.247411,11.388991 9.1968152,10.475925 C 8.146221,9.5628599 6.8660046,8.7034079 5.6266656,8.0176219 C 4.3873265,7.3318362 3.3045923,6.5498939 2.7239802,6.4956482 C 2.4148401,6.4667656 2.5931708,7.3640855 2.9037792,8.1978741 z"
-- id="path2249"
-- sodipodi:nodetypes="csssssssc" />
-- <path
-- transform="matrix(0.700821,0,0,0.664862,-0.245183,-0.148725)"
-- style="fill:url(#linearGradient4505);fill-opacity:1;stroke:url(#linearGradient8642);stroke-width:1.46497786000000008;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 12.478485,9.9508709 C 12.478485,9.9508709 17.866649,0.9861607 21.122294,2.6968071 C 24.404423,4.4213689 20.644961,12.673483 20.644961,12.673483 C 20.644961,12.673483 18.181394,14.512366 14.476578,14.512366 L 12.478485,9.9508709 z "
-- id="rect1317" />
-- <path
-- style="opacity:0.50000000000000000;fill:none;fill-opacity:1;stroke:url(#linearGradient8745);stroke-width:1.00000059999999991;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 13.641543,2.6087804 C 13.042222,2.7550593 12.566354,3.1867157 12.108436,3.5768078 C 11.18133,4.4213418 10.408475,5.418624 9.6753778,6.4315252 C 9.7266839,7.073663 10.22649,7.8212816 10.524225,8.4451141 C 11.523392,8.3745467 12.537477,8.14589 13.395949,7.6120796 C 13.929097,6.4895545 14.279568,5.2829939 14.46967,4.0564994 C 14.517847,3.5935306 14.505216,3.0568259 14.178422,2.69122 C 14.015215,2.4959594 13.853389,2.5338947 13.641543,2.6087804 z"
-- id="path1328"
-- sodipodi:nodetypes="ccccccsc" />
-- <path
-- style="fill:url(#linearGradient8683);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- d="M 7.84375,6.0625 C 7.2204009,5.7746851 6.7868533,6.5768349 7.0386107,7.0974232 C 7.2879783,8.4863432 7.8061372,9.8184408 8.4250523,11.082033 C 8.6624096,11.493677 8.9604116,12.091198 9.5358102,11.967269 C 10.350721,11.726246 9.8989976,10.67735 9.7858357,10.097672 C 9.4218582,8.8029479 8.9711599,7.5041911 8.2319551,6.3726804 C 8.1261729,6.2440217 7.9975858,6.1299296 7.84375,6.0625 z"
-- id="path2192" />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/novell.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/novell.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/novell.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/novell.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,163 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="16px"
-- height="16px"
-- id="svg4248"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/16/scalable"
-- sodipodi:docname="novell.svg"
-- inkscape:export-filename="/home/hbons/Bureaublad/Projecten/Pidgin/pidgin-mtn/pidgin/pixmaps/protocols/16/novell.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs4250">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8681">
-- <stop
-- style="stop-color:#b90000;stop-opacity:1"
-- offset="0"
-- id="stop8683" />
-- <stop
-- style="stop-color:#660000;stop-opacity:1"
-- offset="1"
-- id="stop8685" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8673">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8675" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8677" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient8657">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop8659" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop8661" />
-- </linearGradient>
-- <inkscape:perspective
-- sodipodi:type="inkscape:persp3d"
-- inkscape:vp_x="0 : 8 : 1"
-- inkscape:vp_y="0 : 1000 : 0"
-- inkscape:vp_z="16 : 8 : 1"
-- inkscape:persp3d-origin="8 : 5.3333333 : 1"
-- id="perspective14" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8657"
-- id="linearGradient8663"
-- x1="13.540643"
-- y1="4.1059771"
-- x2="13.540643"
-- y2="27.537933"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8673"
-- id="linearGradient8679"
-- x1="17.568361"
-- y1="-2.2142286"
-- x2="17.568361"
-- y2="21.473934"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient8681"
-- id="linearGradient8687"
-- x1="7.2145119"
-- y1="6.08881"
-- x2="19.957991"
-- y2="21.372702"
-- gradientUnits="userSpaceOnUse" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="23.791015"
-- inkscape:cx="21.551698"
-- inkscape:cy="9.5685566"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- inkscape:grid-bbox="true"
-- inkscape:document-units="px"
-- inkscape:window-width="1440"
-- inkscape:window-height="847"
-- inkscape:window-x="0"
-- inkscape:window-y="0"
-- inkscape:grid-points="true"
-- inkscape:snap-nodes="false"
-- inkscape:snap-bbox="true"
-- objecttolerance="10"
-- gridtolerance="10">
-- <inkscape:grid
-- type="xygrid"
-- id="grid7853"
-- visible="true"
-- enabled="true" />
-- </sodipodi:namedview>
-- <metadata
-- id="metadata4253">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- id="layer1"
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer">
-- <rect
-- style="fill:#ef1e1e;fill-opacity:1;stroke:url(#linearGradient8687);stroke-width:1.27949666999999989;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="rect1326"
-- width="18.090118"
-- height="19.004496"
-- x="3.4549403"
-- y="2.4977543"
-- ry="1.9604023"
-- rx="1.9604023"
-- transform="matrix(0.773903,0,0,0.789287,-2.173788,-1.471445)" />
-- <path
-- style="fill:url(#linearGradient8679);fill-opacity:1;stroke:url(#linearGradient8663);stroke-width:1.32302749000000008;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 5.5,3.5 C 4.9023199,3.5 4.46875,3.9335697 4.46875,4.53125 L 4.46875,19.46875 C 4.46875,20.066429 4.9023192,20.499999 5.5,20.5 L 19.5,20.5 C 20.097679,20.5 20.53125,20.066429 20.53125,19.46875 L 20.53125,4.53125 C 20.53125,3.9335703 20.097679,3.5 19.5,3.5 L 5.5,3.5 z "
-- id="path2201"
-- transform="matrix(0.747082,0,0,0.764706,-1.838521,-1.176469)" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="0"
-- inkscape:original="M 4.03125 4 L 4 12 L 6 12 L 6 7.96875 L 11 13 L 11 5.03125 L 9 5.03125 L 9 8.96875 L 4.03125 4 z "
-- style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-- id="path8697"
-- d="M 4.03125,4 L 4,12 L 6,12 L 6,7.96875 L 11,13 L 11,5.03125 L 9,5.03125 L 9,8.96875 L 4.03125,4 z" />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/yahoo.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/yahoo.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/yahoo.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/yahoo.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,138 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="16px"
-- height="16px"
-- id="svg4248"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/16/scalable"
-- sodipodi:docname="yahoo.svg"
-- inkscape:export-filename="/home/hbons/Bureaublad/yahoo.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs4250">
-- <inkscape:perspective
-- sodipodi:type="inkscape:persp3d"
-- inkscape:vp_x="0 : 8 : 1"
-- inkscape:vp_y="0 : 1000 : 0"
-- inkscape:vp_z="16 : 8 : 1"
-- inkscape:persp3d-origin="8 : 5.3333333 : 1"
-- id="perspective17" />
-- <linearGradient
-- id="linearGradient4123"
-- inkscape:collect="always">
-- <stop
-- id="stop4125"
-- offset="0"
-- style="stop-color:#ff0000;stop-opacity:1;" />
-- <stop
-- id="stop4127"
-- offset="1"
-- style="stop-color:#ff0000;stop-opacity:0;" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient4123"
-- id="linearGradient6737"
-- gradientUnits="userSpaceOnUse"
-- x1="20.181133"
-- y1="12.686874"
-- x2="20.181133"
-- y2="5.3694997" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient4123"
-- id="linearGradient6739"
-- gradientUnits="userSpaceOnUse"
-- x1="10.378018"
-- y1="18.430471"
-- x2="5.8631868"
-- y2="-0.23792659"
-- gradientTransform="matrix(0.676847,0,0,0.662872,0.3362294,0.7829564)" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="36.060436"
-- inkscape:cx="15.360711"
-- inkscape:cy="8.3801083"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- inkscape:grid-bbox="true"
-- inkscape:document-units="px"
-- inkscape:window-width="1440"
-- inkscape:window-height="847"
-- inkscape:window-x="0"
-- inkscape:window-y="0"
-- inkscape:grid-points="false"
-- inkscape:guide-points="false"
-- gridtolerance="10"
-- inkscape:object-points="false"
-- inkscape:object-nodes="false"
-- objecttolerance="10"
-- inkscape:snap-bbox="true"
-- inkscape:snap-nodes="false">
-- <inkscape:grid
-- type="xygrid"
-- id="grid7857"
-- visible="true"
-- enabled="true" />
-- </sodipodi:namedview>
-- <metadata
-- id="metadata4253">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- id="layer1"
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer">
-- <path
-- style="fill:white;fill-opacity:1;stroke:none;stroke-width:1.49293232;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- d="M 0.24196135,4.148819 L 0.24910211,7.1529832 L 3.5563617,7.147764 L 7.6406917,12.763032 L 7.642012,14.664616 L 4.6774169,14.67713 L 4.6586789,17.695272 L 13.533193,17.684579 L 13.569765,14.669366 L 10.619662,14.679398 L 10.629019,12.755768 L 14.593143,8.6330885 L 16.51876,8.6465912 L 16.509766,5.6235735 L 12.050243,5.6188666 L 12.072495,7.7727612 L 10.847264,10.121315 L 8.9433829,10.071394 L 7.9521191,7.1118568 L 9.0229281,7.1259776 L 9.0246268,4.0988967 L 0.24196135,4.148819 z "
-- id="path6741"
-- sodipodi:nodetypes="cccccccccccccccccccccc"
-- transform="matrix(0.676847,0,0,0.662872,0.331396,0.782369)" />
-- <rect
-- style="opacity:0;fill:none;fill-opacity:1;stroke:#a40000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="rect3203"
-- width="0"
-- height="2.5118096"
-- x="6"
-- y="6.4881902"
-- transform="translate(-1.463597e-2,-4.995136)" />
-- <path
-- style="fill:url(#linearGradient6739);fill-opacity:1;stroke:#a40000;stroke-width:1.00000047999999997;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- d="M 6.5 3.5 L 0.5 3.53125 L 0.5 5.53125 L 2.75 5.53125 L 5.5 9.25 L 5.5 10.5 L 4.28125 10.5 C 3.3577546 10.5 3.5 11.5 3.5 11.5 L 3.5 12.5 L 6.5 12.5 L 9.5 12.5 L 9.5 11.21875 C 9.4999997 11.21875 9.4638896 10.5 8.71875 10.5 L 7.53125 10.5 L 7.53125 9.6875 L 10.21875 6.5 L 11.53125 6.5 L 11.5 4.5 L 8.5 4.5 L 8.5 5.8125 L 7.09375 7.5 L 6.65625 7.5 L 5.1875 5.5 L 6.5 5.5 L 6.5 3.5 z M 13.5 3.5 L 13.53125 9.9375 L 15.71875 3.5 L 13.5 3.5 z M 12.5 10.5 C 11.948 10.5 11.5 10.948002 11.5 11.5 C 11.5 12.051998 11.948 12.5 12.5 12.5 C 13.052 12.5 13.5 12.051998 13.5 11.5 C 13.5 10.948002 13.052001 10.5 12.5 10.5 z "
-- id="rect3219" />
-- <rect
-- style="fill:white;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="rect4115"
-- width="1"
-- height="1"
-- x="15"
-- y="12"
-- transform="matrix(0.672571,0,0,0.662714,0.148779,0.239809)" />
-- </g>
--</svg>
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/yahoo.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/yahoo.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/aim.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/aim.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/facebook.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/facebook.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/gadu-gadu.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/gadu-gadu.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/google-talk.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/google-talk.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/icq.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/icq.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/meanwhile.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/meanwhile.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/msn.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/msn.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/mxit.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/mxit.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/myspace.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/myspace.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/novell.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/novell.png differ
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/aim.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/aim.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/aim.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/aim.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,187 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="24"
-- height="24"
-- id="svg2"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- version="1.0"
-- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols"
-- sodipodi:docname="aim.svg"
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/aim.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs4">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2263">
-- <stop
-- style="stop-color:#edc100;stop-opacity:1;"
-- offset="0"
-- id="stop2265" />
-- <stop
-- style="stop-color:#edc100;stop-opacity:0;"
-- offset="1"
-- id="stop2267" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2255">
-- <stop
-- style="stop-color:#edc100;stop-opacity:1;"
-- offset="0"
-- id="stop2257" />
-- <stop
-- style="stop-color:#edc100;stop-opacity:0;"
-- offset="1"
-- id="stop2259" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient3150">
-- <stop
-- style="stop-color:#2e3436;stop-opacity:1;"
-- offset="0"
-- id="stop3152" />
-- <stop
-- style="stop-color:#2e3436;stop-opacity:0;"
-- offset="1"
-- id="stop3154" />
-- </linearGradient>
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3150"
-- id="radialGradient4330"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
-- cx="10.748654"
-- cy="10.457643"
-- fx="10.748654"
-- fy="10.457643"
-- r="6.6449099" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2255"
-- id="linearGradient2261"
-- x1="12.514956"
-- y1="18.246853"
-- x2="12.514956"
-- y2="-0.22752593"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2263"
-- id="linearGradient2269"
-- x1="11.725797"
-- y1="6.7099471"
-- x2="11.725797"
-- y2="-1.7656245"
-- gradientUnits="userSpaceOnUse" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="18.194454"
-- inkscape:cx="21.028138"
-- inkscape:cy="12.129637"
-- inkscape:document-units="px"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- fill="#edd400"
-- showguides="true"
-- inkscape:guide-bbox="true"
-- inkscape:window-width="1268"
-- inkscape:window-height="971"
-- inkscape:window-x="6"
-- inkscape:window-y="21" />
-- <metadata
-- id="metadata7">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer"
-- id="layer1">
-- <path
-- style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.99999988;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- d="M 11.958337,8.6532903 C 10.214088,7.6488702 9.8526923,12.097445 8.6371785,14.197294 C 7.4474897,16.252529 3.5065645,17.589535 3.5065645,17.589535 L 5.9517457,22.489783 L 11.922453,16.916072 C 11.922453,16.916072 15.933817,19.534872 17.160901,22.390612 L 20.390534,19.246933 C 20.390534,19.246933 18.693358,15.872721 14.921211,13.538266 L 20.491001,12.72627 L 19.715221,8.8524949 C 16.110632,9.7210318 13.926705,9.7867691 11.958337,8.6532903 z "
-- id="path1322"
-- sodipodi:nodetypes="czccccccccs" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.45242631;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path1324"
-- sodipodi:cx="10.555883"
-- sodipodi:cy="4.0385542"
-- sodipodi:rx="5.074944"
-- sodipodi:ry="5.074944"
-- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
-- transform="matrix(0.688186,0,0,0.688819,6.743084,1.213885)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.25;fill:url(#radialGradient4330);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path3140"
-- sodipodi:cx="10.748654"
-- sodipodi:cy="10.457643"
-- sodipodi:rx="6.6449099"
-- sodipodi:ry="2.3675451"
-- d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z"
-- transform="matrix(1.805894,0,0,1.300982,-7.410933,6.474929)" />
-- <path
-- style="opacity:1;fill:url(#linearGradient2261);fill-opacity:1.0;stroke:#c4a000;stroke-width:0.99999988;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- d="M 11.958337,8.6532903 C 10.214088,7.6488702 9.8526923,12.097445 8.6371785,14.197294 C 7.4474897,16.252529 3.5065645,17.589535 3.5065645,17.589535 L 5.9517457,22.489783 L 11.922453,16.916072 C 11.922453,16.916072 15.933817,19.534872 17.160901,22.390612 L 20.390534,19.246933 C 20.390534,19.246933 18.693358,15.872721 14.921211,13.538266 L 20.491001,12.72627 L 19.715221,8.8524949 C 16.110632,9.7210318 13.926705,9.7867691 11.958337,8.6532903 z "
-- id="path4275"
-- sodipodi:nodetypes="czccccccccs" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.97533494"
-- inkscape:original="M 11.96875 8.65625 C 10.224501 7.6518295 9.8405138 12.087651 8.625 14.1875 C 7.4353113 16.242735 3.5 17.59375 3.5 17.59375 L 5.9375 22.5 L 11.9375 16.90625 C 11.9375 16.906249 15.929166 19.51926 17.15625 22.375 L 20.375 19.25 C 20.375001 19.25 18.678397 15.865705 14.90625 13.53125 L 20.5 12.71875 L 19.71875 8.84375 C 16.114161 9.7122866 13.937118 9.7897288 11.96875 8.65625 z "
-- xlink:href="#path4275"
-- style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999988;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path4304"
-- inkscape:href="#path4275"
-- d="M 11.5625,9.53125 C 11.452518,9.6624786 11.20418,10.047821 11,10.59375 C 10.56791,11.749055 10.203376,13.418405 9.46875,14.6875 C 8.6867322,16.038467 7.2662927,16.899179 6.0625,17.53125 C 5.412514,17.872536 5.2627915,17.893887 4.84375,18.0625 L 6.21875,20.90625 L 11.28125,16.1875 C 11.609827,15.89012 12.09758,15.851614 12.46875,16.09375 C 12.46875,16.09375 13.514111,16.786729 14.71875,17.84375 C 15.622229,18.636516 16.558838,19.686944 17.3125,20.84375 L 19.125,19.125 C 18.707223,18.391513 17.391924,16.222734 14.40625,14.375 C 14.042988,14.164323 13.855332,13.744801 13.940413,13.333577 C 14.025494,12.922352 14.364213,12.611735 14.78125,12.5625 L 19.34375,11.90625 L 18.9375,9.96875 C 15.910346,10.738935 13.497199,10.615244 11.5625,9.53125 z " />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:url(#linearGradient2269);fill-opacity:1.0;stroke:#c4a000;stroke-width:1.45242631;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path4302"
-- sodipodi:cx="10.555883"
-- sodipodi:cy="4.0385542"
-- sodipodi:rx="5.074944"
-- sodipodi:ry="5.074944"
-- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
-- transform="matrix(0.688186,0,0,0.688819,6.743084,1.213885)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.5;fill:#fce94f;fill-opacity:1;stroke:#ffffff;stroke-width:2.02834463;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path4273"
-- sodipodi:cx="10.555883"
-- sodipodi:cy="4.0385542"
-- sodipodi:rx="5.074944"
-- sodipodi:ry="5.074944"
-- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
-- transform="matrix(0.492994,0,0,0.493032,8.79793,2.010973)" />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/gadu-gadu.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/gadu-gadu.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/gadu-gadu.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/gadu-gadu.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,206 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="24"
-- height="24"
-- id="svg2"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- version="1.0"
-- sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/22/scalable"
-- sodipodi:docname="gadu-gadu.svg"
-- inkscape:export-filename="/home/hbons/GUI/Tango/Gaim Refresh/protocols/22/gadu-gadu.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs4">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient3150">
-- <stop
-- style="stop-color:#2e3436;stop-opacity:1;"
-- offset="0"
-- id="stop3152" />
-- <stop
-- style="stop-color:#2e3436;stop-opacity:0;"
-- offset="1"
-- id="stop3154" />
-- </linearGradient>
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3150"
-- id="radialGradient3156"
-- cx="10.748654"
-- cy="10.457643"
-- fx="10.748654"
-- fy="10.457643"
-- r="6.6449099"
-- gradientTransform="matrix(-0.842757,0,0,-0.35721,19.80716,14.19321)"
-- gradientUnits="userSpaceOnUse" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="24.007726"
-- inkscape:cx="16.146337"
-- inkscape:cy="13.950539"
-- inkscape:document-units="px"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- showguides="true"
-- inkscape:guide-bbox="true"
-- fill="#fce94f"
-- inkscape:window-width="1268"
-- inkscape:window-height="971"
-- inkscape:window-x="6"
-- inkscape:window-y="25" />
-- <metadata
-- id="metadata7">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer"
-- id="layer1">
-- <rect
-- style="opacity:1;fill:#c00;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="rect2235"
-- width="2.0000005"
-- height="3.000001"
-- x="-0.29289341"
-- y="7.3639612"
-- transform="matrix(0.707107,-0.707107,0.707107,0.707107,-1,1)" />
-- <rect
-- style="opacity:1;fill:#c00;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="rect2239"
-- width="2.0000033"
-- height="3.0000048"
-- x="-17.970564"
-- y="8.0710697"
-- transform="matrix(-0.707107,-0.707107,0.707107,-0.707107,-1,1)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.4;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path3140"
-- sodipodi:cx="10.748654"
-- sodipodi:cy="10.457643"
-- sodipodi:rx="6.6449099"
-- sodipodi:ry="2.3675451"
-- d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z"
-- transform="matrix(1.429666,0,0,1.267135,-3.866981,6.748756)" />
-- <rect
-- style="opacity:1;fill:#db2424;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="rect2192"
-- width="1.9907103"
-- height="3"
-- x="12"
-- y="1"
-- transform="translate(-1,1)" />
-- <rect
-- style="opacity:1;fill:#db2424;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="rect2203"
-- width="2"
-- height="3"
-- x="12"
-- y="18"
-- transform="translate(-1,1)" />
-- <rect
-- style="opacity:1;fill:#db2424;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="rect2211"
-- width="2"
-- height="3.4306233"
-- x="-12"
-- y="3"
-- transform="matrix(0,-1,1,0,-1,1)" />
-- <rect
-- style="opacity:1;fill:#db2424;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="rect2213"
-- width="2"
-- height="3"
-- x="-12"
-- y="20"
-- transform="matrix(0,-1,1,0,-1,1)" />
-- <rect
-- style="opacity:1;fill:#c00;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="rect2237"
-- width="2.0000019"
-- height="3.0000029"
-- x="-0.29289412"
-- y="23.57716"
-- transform="matrix(0.707107,-0.707107,0.707107,0.707107,-1,1)" />
-- <rect
-- style="opacity:1;fill:#c00;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="rect2241"
-- width="2.0000048"
-- height="3.0000067"
-- x="-17.970566"
-- y="-8.24265"
-- transform="matrix(-0.707107,-0.707107,0.707107,-0.707107,-1,1)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:#fce94f;fill-opacity:1;stroke:#c00;stroke-width:0.73921776;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2217"
-- sodipodi:cx="8.0702047"
-- sodipodi:cy="8.0363102"
-- sodipodi:rx="5.5372205"
-- sodipodi:ry="5.5372205"
-- d="M 13.607425 8.0363102 A 5.5372205 5.5372205 0 1 1 2.5329843,8.0363102 A 5.5372205 5.5372205 0 1 1 13.607425 8.0363102 z"
-- transform="matrix(1.354195,0,0,1.35137,1.070845,1.157102)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.7;fill:none;fill-opacity:1;stroke:#c4a000;stroke-width:0.85407299;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.4848485"
-- id="path2222"
-- sodipodi:cx="8.0702047"
-- sodipodi:cy="8.0363102"
-- sodipodi:rx="5.5372205"
-- sodipodi:ry="5.5372205"
-- d="M 13.607425 8.0363102 A 5.5372205 5.5372205 0 1 1 2.5329843,8.0363102 A 5.5372205 5.5372205 0 1 1 13.607425 8.0363102 z"
-- transform="matrix(1.171277,0,0,1.170443,2.525066,2.61184)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2243"
-- sodipodi:cx="9.8489876"
-- sodipodi:cy="10.583912"
-- sodipodi:rx="1.2626907"
-- sodipodi:ry="1.0417198"
-- d="M 11.111678 10.583912 A 1.2626907 1.0417198 0 1 1 8.5862969,10.583912 A 1.2626907 1.0417198 0 1 1 11.111678 10.583912 z"
-- transform="matrix(0,1.18426,-0.959955,0,20.16009,-1.168408)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2245"
-- sodipodi:cx="9.8489876"
-- sodipodi:cy="10.583912"
-- sodipodi:rx="1.2626907"
-- sodipodi:ry="1.0417198"
-- d="M 11.111678 10.583912 A 1.2626907 1.0417198 0 1 1 8.5862969,10.583912 A 1.2626907 1.0417198 0 1 1 11.111678 10.583912 z"
-- transform="matrix(0,-1.187938,0.959951,0,3.839963,22.19998)" />
-- <path
-- style="opacity:1;fill:#555753;fill-opacity:1;stroke:none;stroke-width:1.10482609;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- d="M 17.0113,10.955978 C 17.0113,13.182328 15.218558,14.007827 13,14.007827 C 10.819611,14.007827 9.0496187,13.101106 8.9887006,10.913915 L 8,10.942262 C 8.0756746,13.659262 10.29145,15 13,15 C 15.758926,15 17.999999,13.724591 18,10.955978 L 17.0113,10.955978 z "
-- id="path2247"
-- sodipodi:nodetypes="csccscc"
-- transform="translate(-1,1)" />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/icq.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/icq.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/icq.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/icq.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,291 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="24"
-- height="24"
-- id="svg2"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- version="1.0"
-- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols"
-- sodipodi:docname="icq.svg"
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/icq.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs4">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2361">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2363" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2365" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2321">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2323" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2325" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient3150">
-- <stop
-- style="stop-color:#2e3436;stop-opacity:1;"
-- offset="0"
-- id="stop3152" />
-- <stop
-- style="stop-color:#2e3436;stop-opacity:0;"
-- offset="1"
-- id="stop3154" />
-- </linearGradient>
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3150"
-- id="radialGradient3156"
-- cx="10.748654"
-- cy="10.457643"
-- fx="10.748654"
-- fy="10.457643"
-- r="6.6449099"
-- gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2321"
-- id="linearGradient2327"
-- x1="11.787398"
-- y1="11.115861"
-- x2="12.405842"
-- y2="13.791453"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2361"
-- id="linearGradient2367"
-- x1="6.3009863"
-- y1="8.3052416"
-- x2="6.3009863"
-- y2="17.320574"
-- gradientUnits="userSpaceOnUse" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="10.44997"
-- inkscape:cx="19.566864"
-- inkscape:cy="19.726611"
-- inkscape:document-units="px"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- fill="#ef2929"
-- inkscape:window-width="1268"
-- inkscape:window-height="971"
-- inkscape:window-x="6"
-- inkscape:window-y="21" />
-- <metadata
-- id="metadata7">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer"
-- id="layer1">
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.5;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path3140"
-- sodipodi:cx="10.748654"
-- sodipodi:cy="10.457643"
-- sodipodi:rx="6.6449099"
-- sodipodi:ry="2.3675451"
-- d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z"
-- transform="matrix(1.805894,0,0,1.478325,-7.410928,3.04021)" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 12.963148,17.247339 C 12.171926,14.859179 12.454176,14.470485 13.497752,13.880864 C 14.541326,13.291244 15.108816,13.335817 16.744216,15.111033 C 17.767103,16.844843 17.750309,18.730526 16.706739,19.320144 C 15.663162,19.909767 13.986034,18.981148 12.963148,17.247339 z "
-- id="path2226"
-- sodipodi:nodetypes="cscsc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.95876986"
-- inkscape:original="M 14.90625 13.59375 C 14.429506 13.434407 14.021787 13.58019 13.5 13.875 C 12.456424 14.464621 12.177528 14.86184 12.96875 17.25 C 13.991636 18.983809 15.675173 19.902122 16.71875 19.3125 C 17.76232 18.722882 17.772886 16.85881 16.75 15.125 C 15.9323 14.237392 15.382994 13.753093 14.90625 13.59375 z "
-- xlink:href="#path2226"
-- style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
-- id="path2242"
-- inkscape:href="#path2226"
-- d="M 14.6875,15.40625 C 14.513417,15.351665 14.472292,15.359975 14.03125,15.59375 C 13.796094,15.718394 13.674719,15.830029 13.625,15.875 C 13.575281,15.919971 13.600191,15.87903 13.59375,15.90625 C 13.581862,15.956485 13.642727,16.51095 13.9375,17.40625 C 14.348011,18.027075 14.877648,18.50949 15.34375,18.75 C 15.831028,19.001437 16.171295,18.981096 16.3125,18.90625 C 16.454211,18.831136 16.558976,18.656064 16.5625,18.1875 C 16.565896,17.735918 16.387216,17.080025 16,16.4375 C 15.331224,15.779693 14.857908,15.459683 14.6875,15.40625 z "
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 16.771005,15.319703 C 14.33106,13.896777 14.27539,13.249081 14.702189,11.643547 C 15.128987,10.03802 15.633686,9.5050301 18.317374,9.5025628 C 20.461323,10.081613 21.854951,11.854605 21.428153,13.460133 C 21.001355,15.065667 18.914955,15.898753 16.771005,15.319703 z "
-- id="path2216"
-- sodipodi:nodetypes="cscsc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.98264426"
-- inkscape:original="M 18.3125 9.5 C 15.628812 9.5024673 15.114298 10.050723 14.6875 11.65625 C 14.260701 13.261784 14.341304 13.889574 16.78125 15.3125 C 18.9252 15.89155 21.010703 15.074284 21.4375 13.46875 C 21.864298 11.863222 20.45645 10.07905 18.3125 9.5 z "
-- xlink:href="#path2216"
-- style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
-- id="path2238"
-- inkscape:href="#path2216"
-- d="M 18.21875,11.46875 C 17.125733,11.491249 16.482945,11.618664 16.28125,11.75 C 16.063159,11.892013 15.916049,12.106986 15.71875,12.84375 C 15.515581,13.602428 15.521796,13.851934 15.625,14.0625 C 15.720814,14.257989 16.227533,14.71374 17.21875,15.3125 C 18.053555,15.507642 18.8825,15.450801 19.46875,15.21875 C 20.087515,14.973829 20.440615,14.611396 20.5625,14.15625 C 20.683546,13.704238 20.542643,13.182022 20.125,12.65625 C 19.7273,12.155585 19.044575,11.716527 18.21875,11.46875 z "
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000048;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 18.231066,10.043051 C 15.826638,10.834882 15.435297,10.552414 14.841659,9.5080341 C 14.248025,8.4636559 14.292902,7.895729 16.08021,6.2590696 C 17.825828,5.235395 19.724355,5.2521994 20.317989,6.2965763 C 20.911627,7.3409564 19.976685,9.0193762 18.231066,10.043051 z "
-- id="path2224"
-- sodipodi:nodetypes="cscsc" />
-- <path
-- style="fill:#ef2929;fill-opacity:1;stroke:#a40000;stroke-width:1.00000119;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 7.2295458,17.045044 C 4.8262841,17.837501 4.435133,17.554808 3.8417836,16.509603 C 3.2484366,15.464398 3.2932918,14.896022 5.0797326,13.258068 C 6.8245041,12.233585 8.7221095,12.250402 9.3154554,13.295606 C 9.9088085,14.34081 8.9743169,16.020559 7.2295458,17.045044 z "
-- id="path2228"
-- sodipodi:nodetypes="cscsc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-1.0000435"
-- inkscape:original="M 7.625 12.5 C 6.858334 12.493206 5.9661358 12.737758 5.09375 13.25 C 3.3073092 14.887954 3.2504031 15.454794 3.84375 16.5 C 4.4370994 17.545205 4.8154885 17.823707 7.21875 17.03125 C 8.9635211 16.006765 9.9058531 14.326454 9.3125 13.28125 C 9.0158271 12.758648 8.391666 12.506794 7.625 12.5 z "
-- xlink:href="#path2228"
-- style="opacity:0.35;fill:url(#linearGradient2367);fill-opacity:1.0;stroke:#ffffff;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-- id="path2244"
-- inkscape:href="#path2228"
-- d="M 7.6875,14.46875 C 7.1850852,14.464327 6.4432058,14.680127 5.75,15.0625 C 5.0356604,15.736543 4.6689236,16.21317 4.625,16.34375 C 4.5776671,16.484465 4.5627519,16.46929 4.8125,16.90625 C 4.9456222,17.139159 5.046245,17.29527 5.09375,17.34375 C 5.141255,17.39223 5.1063252,17.364089 5.15625,17.375 C 5.2475037,17.394943 5.8597606,17.320365 6.8125,17.03125 C 7.5124448,16.612892 8.0523433,16.090381 8.3125,15.625 C 8.5782457,15.149621 8.5343603,14.864791 8.46875,14.75 C 8.3973728,14.625118 8.2193466,14.473432 7.6875,14.46875 z "
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 7.6891342,15.77365 C 9.1118334,13.334726 9.7586709,13.278647 11.361671,13.703963 C 12.964665,14.129276 13.496553,14.633183 13.497097,17.314646 C 12.917316,19.457228 11.145785,20.850948 9.5427895,20.425634 C 7.93979,20.000318 7.109353,17.916231 7.6891342,15.77365 z "
-- id="path2218"
-- sodipodi:nodetypes="cscsc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-1.0089091"
-- inkscape:original="M 9.46875 13.65625 C 8.9288282 13.921971 8.3988496 14.561788 7.6875 15.78125 C 7.1077188 17.923831 7.9282505 20.012184 9.53125 20.4375 C 11.134246 20.862814 12.920219 19.455082 13.5 17.3125 C 13.499456 14.631037 12.977994 14.144063 11.375 13.71875 C 10.5735 13.506092 10.008672 13.390529 9.46875 13.65625 z "
-- xlink:href="#path2218"
-- style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
-- id="path2240"
-- inkscape:href="#path2218"
-- d="M 9.9375,15.46875 C 9.758584,15.557674 9.317928,16.067421 8.71875,17.0625 C 8.5249462,17.893222 8.580847,18.722852 8.8125,19.3125 C 9.0570015,19.934852 9.4058239,20.288908 9.84375,20.40625 C 10.284224,20.524275 10.791323,20.413461 11.3125,20 C 11.80879,19.606283 12.253545,18.915371 12.5,18.09375 C 12.478422,16.998381 12.350171,16.329407 12.21875,16.125 C 12.076813,15.904237 11.884049,15.788763 11.15625,15.59375 C 10.38798,15.387892 10.114118,15.380968 9.9375,15.46875 z "
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 11.045283,4.7716972 C 11.837827,7.1821833 11.555107,7.5745105 10.509784,8.1696432 C 9.4644611,8.7647745 8.8960214,8.7197841 7.2578858,6.9279732 C 6.2332874,5.1779568 6.2501071,3.2746475 7.2954271,2.6795158 C 8.3407485,2.0843833 10.020684,3.0216808 11.045283,4.7716972 z "
-- id="path2222"
-- sodipodi:nodetypes="cscsc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.96927398"
-- inkscape:original="M 8.1875 2.5 C 7.8669984 2.4684749 7.5425803 2.5387169 7.28125 2.6875 C 6.23593 3.2826317 6.2254015 5.1874835 7.25 6.9375 C 8.8881356 8.7293109 9.4546774 8.7513811 10.5 8.15625 C 11.545323 7.5611173 11.823794 7.1917363 11.03125 4.78125 C 10.262801 3.4687377 9.1490049 2.5945754 8.1875 2.5 z "
-- xlink:href="#path2222"
-- style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
-- id="path2232"
-- inkscape:href="#path2222"
-- d="M 8.15625,4.46875 C 7.9850798,4.4518474 7.8807377,4.4788593 7.84375,4.5 C 7.7166113,4.5726675 7.5662606,4.8028687 7.5625,5.34375 C 7.5588632,5.8668265 7.7601774,6.5753594 8.15625,7.28125 C 8.8326599,7.9986853 9.3286876,8.3591367 9.46875,8.40625 C 9.6195275,8.4569676 9.6232062,8.4698326 10.0625,8.21875 C 10.296133,8.0852146 10.416881,7.988326 10.46875,7.9375 C 10.520619,7.886674 10.519109,7.8993051 10.53125,7.84375 C 10.553442,7.7422051 10.477378,7.1419568 10.1875,6.1875 C 9.551335,5.1240857 8.6060031,4.5131619 8.15625,4.46875 z "
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000048;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 7.2320598,6.6863636 C 9.6715923,8.1091434 9.7272104,8.7568487 9.3003538,10.362442 C 8.8734993,11.96803 8.3688269,12.501065 5.6854848,12.503723 C 3.5418523,11.924813 2.1485268,10.151886 2.5753806,8.5462983 C 3.002236,6.9407045 5.0884273,6.1074547 7.2320598,6.6863636 z "
-- id="path2220"
-- sodipodi:nodetypes="cscsc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-1.0062078"
-- inkscape:original="M 7.21875 6.6875 C 5.0751175 6.1085911 2.9893554 6.9256565 2.5625 8.53125 C 2.1356462 10.136838 3.5438674 11.92109 5.6875 12.5 C 8.3708421 12.497342 8.8856453 11.980588 9.3125 10.375 C 9.7393566 8.7694067 9.6582823 8.1102797 7.21875 6.6875 z "
-- xlink:href="#path2220"
-- style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
-- id="path2234"
-- inkscape:href="#path2220"
-- d="M 6.90625,8.625 C 6.0757552,8.4313739 5.2679182,8.4577406 4.6875,8.6875 C 4.0744067,8.9301939 3.7136786,9.3024203 3.59375,9.75 C 3.4731424,10.200114 3.5937551,10.700108 4,11.21875 C 4.386622,11.71234 5.0555378,12.160107 5.875,12.40625 C 6.9710054,12.383966 7.6389832,12.256351 7.84375,12.125 C 8.0649019,11.983138 8.1794028,11.792477 8.375,11.0625 C 8.5781494,10.304338 8.5991322,10.046076 8.5,9.84375 C 8.40803,9.6560422 7.8949355,9.2223583 6.90625,8.625 z "
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-1.0066811"
-- inkscape:original="M 18.625 5.5 C 17.857962 5.4932111 16.966559 5.7381628 16.09375 6.25 C 14.306442 7.8866594 14.250116 8.4556221 14.84375 9.5 C 15.437388 10.54438 15.814322 10.823081 18.21875 10.03125 C 19.964369 9.0075752 20.906138 7.3256299 20.3125 6.28125 C 20.015683 5.7590616 19.392038 5.5067889 18.625 5.5 z "
-- xlink:href="#path2224"
-- style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
-- id="path2236"
-- inkscape:href="#path2224"
-- d="M 18.65625,6.625 C 18.144193,6.6204563 17.412705,6.8326612 16.71875,7.21875 C 15.998485,7.9033831 15.63724,8.4003618 15.59375,8.53125 C 15.546933,8.6721515 15.527986,8.6470459 15.78125,9.09375 C 15.914256,9.3283439 16.014881,9.4828276 16.0625,9.53125 C 16.110119,9.5796724 16.073321,9.5513897 16.125,9.5625 C 16.221307,9.5832048 16.847896,9.4973699 17.84375,9.1875 C 18.526233,8.7666523 19.058938,8.2387438 19.3125,7.78125 C 19.577081,7.3038742 19.539587,7.0311908 19.46875,6.90625 C 19.408404,6.7998131 19.198718,6.6298135 18.65625,6.625 z "
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000024;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 16.312776,6.2243452 C 14.884428,8.6655097 14.236701,8.7225955 12.632405,8.2997676 C 11.028107,7.8769402 10.496367,7.373854 10.500103,4.6923611 C 11.08402,2.548855 12.859963,1.1523628 14.464261,1.5751903 C 16.068559,1.9980181 16.896691,4.0808393 16.312776,6.2243452 z "
-- id="path2192"
-- sodipodi:nodetypes="cscsc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.99950546"
-- inkscape:original="M 14.46875 1.5625 C 12.864452 1.1396725 11.083917 2.5439941 10.5 4.6875 C 10.496264 7.3689929 11.020702 7.8896727 12.625 8.3125 C 14.229296 8.7353279 14.884151 8.6599145 16.3125 6.21875 C 16.896415 4.0752441 16.073048 1.9853278 14.46875 1.5625 z "
-- xlink:href="#path2192"
-- style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
-- id="path2230"
-- inkscape:href="#path2192"
-- d="M 14.21875,2.53125 C 13.768437,2.4124791 13.248017,2.520656 12.71875,2.9375 C 12.214757,3.3344386 11.780816,4.0240635 11.53125,4.84375 C 11.550949,5.9366779 11.679626,6.6046957 11.8125,6.8125 C 11.956007,7.0369325 12.144428,7.1510597 12.875,7.34375 C 13.630622,7.5430474 13.875456,7.5464752 14.09375,7.4375 C 14.296413,7.3363279 14.739612,6.8347534 15.34375,5.84375 C 15.539967,5.0157934 15.511564,4.2073905 15.28125,3.625 C 15.03797,3.0098233 14.669402,2.6501106 14.21875,2.53125 z "
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:#edd400;fill-opacity:1;stroke:#c4a000;stroke-width:0.43295163;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path1317"
-- sodipodi:cx="12.075002"
-- sodipodi:cy="12.360133"
-- sodipodi:rx="1.1966218"
-- sodipodi:ry="1.4141895"
-- d="M 13.271623 12.360133 A 1.1966218 1.4141895 0 1 1 10.87838,12.360133 A 1.1966218 1.4141895 0 1 1 13.271623 12.360133 z"
-- transform="matrix(2.422923,0.638108,-0.560042,2.054325,-10.83461,-21.59688)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.4;fill:url(#linearGradient2327);fill-opacity:1.0;stroke:#ffffff;stroke-width:0.64902174;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2319"
-- sodipodi:cx="12.075002"
-- sodipodi:cy="12.360133"
-- sodipodi:rx="1.1966218"
-- sodipodi:ry="1.4141895"
-- d="M 13.271623 12.360133 A 1.1966218 1.4141895 0 1 1 10.87838,12.360133 A 1.1966218 1.4141895 0 1 1 13.271623 12.360133 z"
-- transform="matrix(1.616292,0.425671,-0.373594,1.370406,-3.399047,-10.57838)" />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/meanwhile.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/meanwhile.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/meanwhile.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/meanwhile.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,172 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="24"
-- height="24"
-- id="svg2"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- version="1.0"
-- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols"
-- sodipodi:docname="meanwhile.svg"
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/meanwhile.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs4">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2230">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2232" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2234" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2222">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2224" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2226" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient3150">
-- <stop
-- style="stop-color:#2e3436;stop-opacity:1;"
-- offset="0"
-- id="stop3152" />
-- <stop
-- style="stop-color:#2e3436;stop-opacity:0;"
-- offset="1"
-- id="stop3154" />
-- </linearGradient>
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3150"
-- id="radialGradient4330"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
-- cx="10.748654"
-- cy="10.457643"
-- fx="10.748654"
-- fy="10.457643"
-- r="6.6449099" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2222"
-- id="linearGradient2228"
-- x1="13.090998"
-- y1="0.78084093"
-- x2="13.090998"
-- y2="17.595036"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2230"
-- id="linearGradient2236"
-- x1="10.063863"
-- y1="-0.14116688"
-- x2="10.063863"
-- y2="7.1152339"
-- gradientUnits="userSpaceOnUse" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="13.788818"
-- inkscape:cx="4.860805"
-- inkscape:cy="9.6839037"
-- inkscape:document-units="px"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- fill="#f57900"
-- showguides="true"
-- inkscape:guide-bbox="true"
-- inkscape:window-width="1268"
-- inkscape:window-height="971"
-- inkscape:window-x="6"
-- inkscape:window-y="21" />
-- <metadata
-- id="metadata7">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer"
-- id="layer1">
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.3;fill:url(#radialGradient4330);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path3140"
-- sodipodi:cx="10.748654"
-- sodipodi:cy="10.457643"
-- sodipodi:rx="6.6449099"
-- sodipodi:ry="2.3675451"
-- d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z"
-- transform="matrix(1.805894,0,0,1.512171,-7.410928,4.606121)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:#f57900;fill-opacity:1;stroke:#ce5c00;stroke-width:1.45242631;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path4302"
-- sodipodi:cx="10.555883"
-- sodipodi:cy="4.0385542"
-- sodipodi:rx="5.074944"
-- sodipodi:ry="5.074944"
-- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
-- transform="matrix(0.688186,0,0,0.688819,4.743084,1.209666)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.45;fill:url(#linearGradient2236);fill-opacity:1.0;stroke:#ffffff;stroke-width:2.02834463;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path4273"
-- sodipodi:cx="10.555883"
-- sodipodi:cy="4.0385542"
-- sodipodi:rx="5.074944"
-- sodipodi:ry="5.074944"
-- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
-- transform="matrix(0.492994,0,0,0.493032,6.809086,2.006754)" />
-- <path
-- style="fill:#f57900;fill-opacity:1;stroke:#ce5c00;stroke-width:1.00000119;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 17.512653,3.583459 C 17.512653,5.7137825 16.562033,9.5267857 12.004464,9.5267857 C 7.4763459,9.5267857 6.5140012,5.7551862 6.5140012,3.5976845 L 2.5044094,4.4125109 C 2.5044094,11.110279 9.0401786,13.178571 9.0401786,13.178571 C 9.0401786,13.178571 4.4464285,16.409103 4.4464285,21.475844 L 9.5714286,21.522322 C 9.5714286,21.522322 10.279685,16.46875 12.089286,16.46875 C 13.943529,16.46875 15.401786,21.508929 15.401786,21.508929 L 20.502628,21.524951 C 20.502628,16.121505 15.254464,13.120535 15.254464,13.120535 C 15.254464,13.120535 21.508928,11.277721 21.508928,4.4267748 L 17.512653,3.583459 z "
-- id="rect2213"
-- sodipodi:nodetypes="czccccczccccc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.9525249"
-- inkscape:original="M 6.5 3.59375 L 2.5 4.40625 C 2.5000001 11.104018 9.03125 13.1875 9.03125 13.1875 C 9.0312503 13.1875 4.4375 16.402009 4.4375 21.46875 L 9.5625 21.53125 C 9.5625003 21.53125 10.284149 16.46875 12.09375 16.46875 C 13.947993 16.46875 15.40625 21.5 15.40625 21.5 L 20.5 21.53125 C 20.5 16.127803 15.25 13.125 15.25 13.125 C 15.25 13.125 21.5 11.288446 21.5 4.4375 L 17.5 3.59375 C 17.5 5.7240736 16.557569 9.53125 12 9.53125 C 7.4718818 9.5312498 6.5 5.7512517 6.5 3.59375 z "
-- xlink:href="#rect2213"
-- style="fill:url(#linearGradient2228);fill-opacity:1.0;stroke:#ffffff;stroke-width:1.00000119;stroke-miterlimit:4;stroke-opacity:1;opacity:0.45"
-- id="path2220"
-- inkscape:href="#rect2213"
-- d="M 5.6875,4.75 L 3.53125,5.1875 C 3.766386,7.7468676 5.0307437,9.4444151 6.375,10.5625 C 7.8598463,11.797521 9.3125,12.28125 9.3125,12.28125 C 9.6563341,12.393071 9.9072283,12.689904 9.9602145,13.047561 C 10.013201,13.405218 9.8591447,13.762043 9.5625,13.96875 C 9.5625,13.96875 6.1077373,16.59996 5.5625,20.53125 L 8.8125,20.59375 C 8.8948827,20.11702 8.9443109,19.67024 9.25,18.71875 C 9.4690397,18.036965 9.7468494,17.32194 10.15625,16.71875 C 10.565651,16.11556 11.197223,15.53125 12.09375,15.53125 C 12.98807,15.53125 13.639348,16.079917 14.125,16.65625 C 14.610652,17.232583 14.993863,17.890429 15.3125,18.5625 C 15.787201,19.563742 15.924647,20.125238 16.0625,20.5625 L 19.34375,20.59375 C 18.746486,16.428966 14.78125,13.9375 14.78125,13.9375 C 14.463324,13.745958 14.285599,13.387197 14.325851,13.018218 C 14.366103,12.649239 14.617002,12.337237 14.96875,12.21875 C 14.96875,12.21875 16.343303,11.809333 17.75,10.625 C 19.032471,9.5452564 20.256269,7.8458143 20.46875,5.1875 L 18.3125,4.75 C 18.187549,5.7582509 17.936893,6.8360203 17.25,7.875 C 16.2955,9.3187557 14.544016,10.46875 12,10.46875 C 9.4708902,10.46875 7.7086662,9.3456824 6.75,7.90625 C 6.0601086,6.8703815 5.8152026,5.7643315 5.6875,4.75 z " />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/msn.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/msn.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/msn.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/msn.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,223 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="24"
-- height="24"
-- id="svg2"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- version="1.0"
-- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols"
-- sodipodi:docname="msn.svg"
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/msn2.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs4">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient3816">
-- <stop
-- style="stop-color:#000000;stop-opacity:1;"
-- offset="0"
-- id="stop3818" />
-- <stop
-- style="stop-color:#000000;stop-opacity:0;"
-- offset="1"
-- id="stop3820" />
-- </linearGradient>
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3816"
-- id="radialGradient3822"
-- cx="31.112698"
-- cy="19.008621"
-- fx="31.112698"
-- fy="19.008621"
-- r="8.6620579"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2228">
-- <stop
-- style="stop-color:#f56600;stop-opacity:1;"
-- offset="0"
-- id="stop2230" />
-- <stop
-- style="stop-color:#f56600;stop-opacity:0;"
-- offset="1"
-- id="stop2232" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2219">
-- <stop
-- style="stop-color:#3465a4;stop-opacity:1;"
-- offset="0"
-- id="stop2221" />
-- <stop
-- style="stop-color:#3465a4;stop-opacity:0;"
-- offset="1"
-- id="stop2223" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2219"
-- id="linearGradient2251"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(0.747158,0,0,0.74873,0.374035,0.608489)"
-- x1="9.9973583"
-- y1="14.918511"
-- x2="14.069712"
-- y2="18.218639" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2228"
-- id="linearGradient1330"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(0.782765,0,0,0.747651,1.035995,0.614065)"
-- x1="20.998175"
-- y1="11.741063"
-- x2="17.999571"
-- y2="18.866741" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="29.556977"
-- inkscape:cx="19.409996"
-- inkscape:cy="10.944939"
-- inkscape:document-units="px"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- fill="#edd400"
-- showguides="true"
-- inkscape:guide-bbox="true"
-- inkscape:window-width="1268"
-- inkscape:window-height="971"
-- inkscape:window-x="6"
-- inkscape:window-y="21" />
-- <metadata
-- id="metadata7">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer"
-- id="layer1">
-- <path
-- d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1 22.45064,19.008621 A 8.6620579 8.6620579 0 1 1 39.774755 19.008621 z"
-- sodipodi:ry="8.6620579"
-- sodipodi:rx="8.6620579"
-- sodipodi:cy="19.008621"
-- sodipodi:cx="31.112698"
-- id="path4318"
-- style="opacity:0.4;color:#000000;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-- sodipodi:type="arc"
-- transform="matrix(1.044119,0,0,0.346338,-18.44114,13.41659)" />
-- <path
-- style="opacity:1;fill:#edd400;fill-opacity:1;stroke:#c4a000;stroke-width:1.00000083;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 18.436518,9.9127618 C 21.037357,10.673309 21.362289,19.501337 18.407881,19.501337 C 15.489266,19.501337 8.9905421,7.150538 18.436518,9.9127618 z "
-- id="rect2194"
-- sodipodi:nodetypes="czs" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.96520001"
-- inkscape:original="M 15.59375 9.53125 C 10.549483 10.044796 15.852462 19.5 18.40625 19.5 C 21.360658 19.5 21.038339 10.666797 18.4375 9.90625 C 17.256753 9.560972 16.31436 9.4578863 15.59375 9.53125 z "
-- xlink:href="#rect2194"
-- style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.00000024;stroke-miterlimit:4;stroke-opacity:1"
-- id="path2259"
-- inkscape:href="#rect2194"
-- d="M 16,10.75 C 15.512126,10.798024 15.253534,10.920051 15.09375,11.0625 C 14.933966,11.204949 14.83864,11.380838 14.78125,11.6875 C 14.66647,12.300825 14.844054,13.385232 15.3125,14.46875 C 15.780946,15.552268 16.512913,16.653582 17.21875,17.4375 C 17.924587,18.221418 18.67699,18.5625 18.75,18.5625 C 18.89196,18.5625 18.968845,18.54667 19.09375,18.4375 C 19.218655,18.32833 19.365593,18.098064 19.5,17.78125 C 19.768815,17.147621 19.923112,16.154119 19.90625,15.125 C 19.889388,14.095881 19.705611,13.023656 19.40625,12.25 C 19.106889,11.476344 18.724904,11.117253 18.53125,11.0625 C 17.425208,10.749781 16.582845,10.692627 16,10.75 z " />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000083;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 13.316085,20.509475 C 10.851196,20.509475 4.3258741,14.508937 9.3204332,11.066555 C 14.310647,7.6271659 15.818731,20.509475 13.316085,20.509475 z "
-- id="rect2201"
-- sodipodi:nodetypes="czz" />
-- <path
-- style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 10.99506,11.498797 C 10.735658,11.486846 10.370038,11.588319 9.8835883,11.932121 C 8.8737,12.645867 8.5374239,13.351301 8.4999186,14.121547 C 8.4624133,14.891791 8.7901654,15.780902 9.3391937,16.607457 C 9.8882225,17.43401 10.661309,18.195719 11.403357,18.728462 C 12.145404,19.261206 12.809412,19.500227 13.070994,19.500227 C 13.222335,19.500227 13.331682,19.0625 13.39947,18.682848 C 13.535046,17.923542 13.548476,16.808781 13.376787,15.695196 C 13.205098,14.58161 12.846108,13.444035 12.401414,12.661929 C 11.95672,11.879824 11.481565,11.52121 10.99506,11.498797 z "
-- id="path2254"
-- sodipodi:nodetypes="cssssssssc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.99454969"
-- inkscape:original="M 19.8125 2.53125 C 16.600144 3.1011521 12.46875 9.9375003 12.46875 9.9375 L 14.46875 14.5 C 18.173566 14.5 20.656251 12.6875 20.65625 12.6875 C 20.65625 12.6875 24.40713 4.4120618 21.125 2.6875 C 20.718044 2.4736692 20.271408 2.4498354 19.8125 2.53125 z "
-- xlink:href="#rect1317"
-- style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-- id="path2245"
-- inkscape:href="#rect1317"
-- d="M 20,3.5 C 18.995087,3.678281 17.104383,5.3426949 15.71875,7.0625 C 14.498278,8.5773128 13.796939,9.7027104 13.59375,10.03125 L 15.0625,13.375 C 17.799931,13.187054 19.57299,12.186552 19.84375,12 C 19.951969,11.755173 20.691026,10.13991 21.15625,8.125 C 21.405718,7.0445423 21.52736,5.9263632 21.4375,5.09375 C 21.34764,4.2611368 21.117806,3.8050199 20.65625,3.5625 C 20.487599,3.4738843 20.316754,3.4438049 20,3.5 z " />
-- <path
-- style="opacity:1;fill:url(#linearGradient2251);fill-opacity:1;stroke:#204a87;stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 1.7306799,5.8222291 C 3.0741729,3.5659039 16.882213,13.11203 11.087148,14.375153 C 5.2996209,15.636634 0.40087698,8.0555627 1.7306799,5.8222291 z "
-- id="rect2197"
-- sodipodi:nodetypes="czz" />
-- <path
-- style="opacity:0.2;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- d="M 2.7390794,8.1722341 C 3.0496879,9.0060223 3.6590736,9.9821112 4.4574474,10.857929 C 6.0541952,12.609562 8.35926,13.89948 10.765977,13.389526 C 11.255672,13.285765 11.400406,13.151715 11.448617,13.081331 C 11.496824,13.010949 11.537361,12.912219 11.448617,12.641053 C 11.271127,12.098721 10.521911,11.132591 9.4713148,10.219525 C 8.4207206,9.3064602 7.0856043,8.3957283 5.8462653,7.7099423 C 4.6069262,7.0241566 3.3045923,6.5498939 2.7239802,6.4956482 C 2.4148401,6.4667656 2.428471,7.3384455 2.7390794,8.1722341 z "
-- id="path2249"
-- sodipodi:nodetypes="cssssssss" />
-- <path
-- style="opacity:1;fill:url(#linearGradient1330);fill-opacity:1;stroke:#ce5d00;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 12.478485,9.9508709 C 12.478485,9.9508709 17.866649,0.9861607 21.122294,2.6968071 C 24.404423,4.4213689 20.644961,12.673483 20.644961,12.673483 C 20.644961,12.673483 18.181394,14.512366 14.476578,14.512366 L 12.478485,9.9508709 z "
-- id="rect1317"
-- sodipodi:nodetypes="czccc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.99298751"
-- inkscape:original="M 19.8125 2.53125 C 16.600144 3.1011521 12.46875 9.9375003 12.46875 9.9375 L 14.46875 14.5 C 18.173566 14.5 20.656251 12.6875 20.65625 12.6875 C 20.65625 12.6875 24.40713 4.4120618 21.125 2.6875 C 20.718044 2.4736692 20.271408 2.4498354 19.8125 2.53125 z "
-- xlink:href="#rect1317"
-- style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-- id="path1328"
-- inkscape:href="#rect1317"
-- d="M 20,3.5 C 18.994143,3.6784485 17.104459,5.3425998 15.71875,7.0625 C 14.49821,8.5773965 13.796948,9.7026949 13.59375,10.03125 L 15.0625,13.375 C 17.800353,13.18702 19.57294,12.186586 19.84375,12 C 19.951976,11.755161 20.690984,10.140091 21.15625,8.125 C 21.40574,7.0444453 21.527392,5.9266549 21.4375,5.09375 C 21.347608,4.2608451 21.11837,3.8053161 20.65625,3.5625 C 20.487225,3.4736876 20.316977,3.4437653 20,3.5 z " />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:#75507b;fill-opacity:1;stroke:#5c3566;stroke-width:1.35211551;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2192"
-- sodipodi:cx="13.4375"
-- sodipodi:cy="15.825892"
-- sodipodi:rx="0.8035714"
-- sodipodi:ry="5.1116071"
-- d="M 14.241071 15.825892 A 0.8035714 5.1116071 0 1 1 12.633929,15.825892 A 0.8035714 5.1116071 0 1 1 14.241071 15.825892 z"
-- transform="matrix(0.603448,-0.487879,0.280285,0.679821,0.46572,8.794406)" />
-- <image
-- id="image1314"
-- height="31.456791"
-- width="30.814816"
-- sodipodi:absref="/home/hbons/Desktop/MSN_groups_butterfly.gif"
-- xlink:href="/home/hbons/Desktop/MSN_groups_butterfly.gif"
-- x="-32"
-- y="-23.456791"
-- style="opacity:0.72727272" />
-- <image
-- id="image2210"
-- height="8"
-- width="8"
-- sodipodi:absref="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-- xlink:href="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-- x="-16"
-- y="14" />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/novell.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/novell.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/novell.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/novell.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,140 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="24"
-- height="24"
-- id="svg2"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- version="1.0"
-- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/22/scalable"
-- sodipodi:docname="novell.svg"
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/22/groupwise.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs4">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2190">
-- <stop
-- style="stop-color:#d3d7cf;stop-opacity:1;"
-- offset="0"
-- id="stop2192" />
-- <stop
-- style="stop-color:#d3d7cf;stop-opacity:0;"
-- offset="1"
-- id="stop2194" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient3150">
-- <stop
-- style="stop-color:#2e3436;stop-opacity:1;"
-- offset="0"
-- id="stop3152" />
-- <stop
-- style="stop-color:#2e3436;stop-opacity:0;"
-- offset="1"
-- id="stop3154" />
-- </linearGradient>
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3150"
-- id="radialGradient3156"
-- cx="10.748654"
-- cy="10.457643"
-- fx="10.748654"
-- fy="10.457643"
-- r="6.6449099"
-- gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
-- gradientUnits="userSpaceOnUse" />
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2190"
-- id="radialGradient2196"
-- cx="4.3022962"
-- cy="7.5011024"
-- fx="4.3022962"
-- fy="7.5011024"
-- r="8.5"
-- gradientTransform="matrix(-2.567716,2.567716,-2.581797,-2.581795,54.64024,19.71367)"
-- gradientUnits="userSpaceOnUse" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="18.194454"
-- inkscape:cx="19.83031"
-- inkscape:cy="13.86181"
-- inkscape:document-units="px"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- fill="#00ffff"
-- inkscape:window-width="1268"
-- inkscape:window-height="971"
-- inkscape:window-x="6"
-- inkscape:window-y="21" />
-- <metadata
-- id="metadata7">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer"
-- id="layer1">
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.5;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path3140"
-- sodipodi:cx="10.748654"
-- sodipodi:cy="10.457643"
-- sodipodi:rx="6.6449099"
-- sodipodi:ry="2.3675451"
-- d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z"
-- transform="matrix(1.655402,0,0,1.055946,-5.793349,9.457294)" />
-- <rect
-- style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:#888a85;stroke-width:0.99999988;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="rect1326"
-- width="18.090118"
-- height="19.004496"
-- x="3.4549403"
-- y="2.4977543"
-- ry="2.0372119"
-- rx="2.0372119" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.99578816"
-- inkscape:original="M 5.5 2.5 C 4.3713846 2.5 3.46875 3.4026344 3.46875 4.53125 L 3.46875 19.46875 C 3.46875 20.597365 4.3713846 21.499999 5.5 21.5 L 19.5 21.5 C 20.628615 21.5 21.53125 20.597365 21.53125 19.46875 L 21.53125 4.53125 C 21.53125 3.4026346 20.628615 2.5 19.5 2.5 L 5.5 2.5 z "
-- xlink:href="#rect1326"
-- style="opacity:1;fill:url(#radialGradient2196);fill-opacity:1;stroke:#ffffff;stroke-width:1.00000048;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2201"
-- inkscape:href="#rect1326"
-- d="M 4,2.5 C 3.7105801,2.5 3.5,2.7105801 3.5,3 L 3.5,20.65625 C 3.5,20.94567 3.6855275,21.125 4,21.125 L 20.46875,21.125 C 20.783223,21.125 20.96875,20.945671 20.96875,20.65625 L 20.96875,3 C 20.96875,2.7105794 20.758171,2.5 20.46875,2.5 L 4,2.5 z " />
-- <path
-- style="fill:#cc0000;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 7.9770722,7 L 7.9770722,17.002529 L 10.015316,17.002529 L 9.9655567,11.206846 L 14.876959,15.95387 L 17,18 L 17,8.0143877 L 14.995675,8.0143877 L 14.995675,13.760417 L 9.1049377,8.0476192 L 7.9770722,7 z "
-- id="rect1317"
-- sodipodi:nodetypes="ccccccccccc" />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/yahoo.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/yahoo.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/yahoo.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/yahoo.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,154 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="24"
-- height="24"
-- id="svg1307"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- version="1.0"
-- sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/22/scalable"
-- sodipodi:docname="yahoo.svg"
-- inkscape:export-filename="/home/hbons/GUI/Tango/Gaim Refresh/protocols/22/yahoo.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs1309">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient3150">
-- <stop
-- style="stop-color:#2e3436;stop-opacity:1;"
-- offset="0"
-- id="stop3152" />
-- <stop
-- style="stop-color:#2e3436;stop-opacity:0;"
-- offset="1"
-- id="stop3154" />
-- </linearGradient>
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3150"
-- id="radialGradient3156"
-- cx="10.748654"
-- cy="10.457643"
-- fx="10.748654"
-- fy="10.457643"
-- r="6.6449099"
-- gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient4123">
-- <stop
-- style="stop-color:#ff0000;stop-opacity:1;"
-- offset="0"
-- id="stop4125" />
-- <stop
-- style="stop-color:#ff0000;stop-opacity:0;"
-- offset="1"
-- id="stop4127" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient4123"
-- id="linearGradient4129"
-- x1="20.102123"
-- y1="10.489645"
-- x2="20.102123"
-- y2="3.0395992"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient4123"
-- id="linearGradient4131"
-- x1="9.7634506"
-- y1="11.499014"
-- x2="9.7634506"
-- y2="0.12942761"
-- gradientUnits="userSpaceOnUse" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="29.290175"
-- inkscape:cx="18.292625"
-- inkscape:cy="12.739723"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- inkscape:grid-bbox="true"
-- inkscape:document-units="px"
-- fill="#a40000"
-- showguides="true"
-- inkscape:guide-bbox="true"
-- inkscape:window-width="1268"
-- inkscape:window-height="971"
-- inkscape:window-x="6"
-- inkscape:window-y="25" />
-- <metadata
-- id="metadata1312">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- id="layer1"
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer">
-- <rect
-- style="opacity:0;fill:none;fill-opacity:1;stroke:#a40000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="rect3203"
-- width="0"
-- height="2.5118096"
-- x="6"
-- y="6.4881902" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.6;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path3140"
-- sodipodi:cx="10.748654"
-- sodipodi:cy="10.457643"
-- sodipodi:rx="6.6449099"
-- sodipodi:ry="2.3675451"
-- d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z"
-- transform="matrix(1.730648,0,0,1.300982,-7.102139,4.474929)" />
-- <path
-- style="opacity:1;fill:url(#linearGradient4131);fill-opacity:1.0;stroke:#a40000;stroke-width:0.99999958;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- d="M 0.49908419,5.4951356 L 0.49908419,7.5376225 L 3.3376273,7.5964463 L 8.515629,12.953307 L 8.515629,15.459996 L 5.4587364,15.459996 L 5.4587364,17.502482 L 13.56886,17.502482 L 13.56886,15.459996 L 10.463631,15.459996 L 10.463631,12.891414 L 14.972535,8.5279191 L 16.532174,8.5279191 L 16.532174,6.5473259 L 11.478943,6.5473259 L 11.478943,8.5279191 L 12.040413,8.5279191 L 9.8296564,10.446619 L 9.1979396,10.446619 L 5.9890137,7.5376225 L 9.5449908,7.5376225 L 9.5449908,5.4951356 L 0.49908419,5.4951356 z "
-- id="rect3219"
-- sodipodi:nodetypes="ccccccccccccccccccccccc" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:#ff0000;fill-opacity:1;stroke:#a40000;stroke-width:0.97808969;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path4110"
-- sodipodi:cx="16.860584"
-- sodipodi:cy="16.429377"
-- sodipodi:rx="1.3865612"
-- sodipodi:ry="1.5252173"
-- d="M 18.247145 16.429377 A 1.3865612 1.5252173 0 1 1 15.474023,16.429377 A 1.3865612 1.5252173 0 1 1 18.247145 16.429377 z"
-- transform="matrix(1.06013,0,0,0.986015,-0.904476,0.796501)" />
-- <path
-- style="fill:url(#linearGradient4129);fill-opacity:1.0;stroke:#a40000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 18.485372,6.4981503 L 22.514636,6.4981503 L 18.576821,12.500953 L 18.485372,6.4981503 z "
-- id="rect4112"
-- sodipodi:nodetypes="cccc" />
-- </g>
--</svg>
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/yahoo.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/yahoo.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/aim.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/aim.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/facebook.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/facebook.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/gadu-gadu.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/gadu-gadu.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/icq.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/icq.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/meanwhile.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/meanwhile.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/msn.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/msn.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/mxit.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/mxit.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/myspace.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/myspace.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/novell.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/novell.png differ
-Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/yahoo.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/yahoo.png differ
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/aim.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/aim.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/aim.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/aim.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,188 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="48"
-- height="48"
-- id="svg2"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- version="1.0"
-- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48"
-- sodipodi:docname="aim.svg"
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/aim.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs4">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2263">
-- <stop
-- style="stop-color:#edc100;stop-opacity:1;"
-- offset="0"
-- id="stop2265" />
-- <stop
-- style="stop-color:#edc100;stop-opacity:0;"
-- offset="1"
-- id="stop2267" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2255">
-- <stop
-- style="stop-color:#edc100;stop-opacity:1;"
-- offset="0"
-- id="stop2257" />
-- <stop
-- style="stop-color:#edc100;stop-opacity:0;"
-- offset="1"
-- id="stop2259" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient3150">
-- <stop
-- style="stop-color:#2e3436;stop-opacity:1;"
-- offset="0"
-- id="stop3152" />
-- <stop
-- style="stop-color:#2e3436;stop-opacity:0;"
-- offset="1"
-- id="stop3154" />
-- </linearGradient>
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3150"
-- id="radialGradient4330"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
-- cx="10.748654"
-- cy="10.457643"
-- fx="10.748654"
-- fy="10.457643"
-- r="6.6449099" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2255"
-- id="linearGradient2261"
-- x1="12.514956"
-- y1="18.690643"
-- x2="12.514956"
-- y2="3.9849093"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(1.943689,0,0,1.932352,0.678089,2.050925)" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2263"
-- id="linearGradient2269"
-- x1="10.555883"
-- y1="8.0642843"
-- x2="10.555883"
-- y2="1.4995424"
-- gradientUnits="userSpaceOnUse" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="12.865422"
-- inkscape:cx="46.678288"
-- inkscape:cy="27.286544"
-- inkscape:document-units="px"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- fill="#edd400"
-- showguides="true"
-- inkscape:guide-bbox="true"
-- inkscape:window-width="1268"
-- inkscape:window-height="971"
-- inkscape:window-x="6"
-- inkscape:window-y="21" />
-- <metadata
-- id="metadata7">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer"
-- id="layer1">
-- <path
-- style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.99999982;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- d="M 23.921379,18.772128 C 20.531101,16.831234 19.828661,25.427448 17.466079,29.485095 C 15.153694,33.456532 7.4937606,36.040098 7.4937606,36.040098 L 12.246433,45.509102 L 23.851631,34.738731 C 23.851631,34.738731 31.648476,39.799175 34.033545,45.317469 L 40.310948,39.242775 C 40.310948,39.242775 37.012166,32.72261 29.680284,28.21162 L 40.506226,26.642559 L 38.998349,19.157061 C 31.992149,20.83538 27.747274,20.962407 23.921379,18.772128 z "
-- id="path1324"
-- sodipodi:nodetypes="czccccccccs" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.72577804;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path1326"
-- sodipodi:cx="10.555883"
-- sodipodi:cy="4.0385542"
-- sodipodi:rx="5.074944"
-- sodipodi:ry="5.074944"
-- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
-- transform="matrix(1.37826,0,0,1.377401,12.95457,3.935583)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.25;fill:url(#radialGradient4330);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path3140"
-- sodipodi:cx="10.748654"
-- sodipodi:cy="10.457643"
-- sodipodi:rx="6.6449099"
-- sodipodi:ry="2.3675451"
-- d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z"
-- transform="matrix(3.310805,0,0,2.323084,-11.5867,18.20601)" />
-- <path
-- style="opacity:1;fill:url(#linearGradient2261);fill-opacity:1;stroke:#b49500;stroke-width:0.99999982;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- d="M 23.921379,18.772128 C 20.531101,16.831234 21.460943,23.017888 19.098361,27.075535 C 16.785976,31.046972 7.4937606,36.040098 7.4937606,36.040098 L 12.246433,45.509102 L 23.851631,34.738731 C 23.851631,34.738731 31.648476,39.799175 34.033545,45.317469 L 40.310948,39.242775 C 40.310948,39.242775 37.012166,32.72261 29.680284,28.21162 L 40.661681,26.564831 L 38.687438,18.690695 C 31.681238,20.369014 27.747274,20.962407 23.921379,18.772128 z "
-- id="path4275"
-- sodipodi:nodetypes="czccccccccs" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.97533494"
-- inkscape:original="M 22.84375 18.40625 C 20.718205 18.345643 21.161009 23.512059 19.09375 27.0625 C 16.781366 31.033937 7.5 36.03125 7.5 36.03125 L 12.25 45.5 L 23.84375 34.75 C 23.84375 34.75 31.646181 39.794206 34.03125 45.3125 L 40.3125 39.25 C 40.312501 39.25 37.019382 32.72974 29.6875 28.21875 L 40.65625 26.5625 L 38.6875 18.6875 C 31.681299 20.365819 27.732145 20.971529 23.90625 18.78125 C 23.482465 18.538638 23.147399 18.414908 22.84375 18.40625 z "
-- xlink:href="#path4275"
-- style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999988;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path4304"
-- inkscape:href="#path4275"
-- d="M 22.53125,19.15625 C 22.35655,19.185124 22.015713,19.423413 21.625,20.09375 C 21.234287,20.764087 20.848022,21.75407 20.46875,22.875 C 19.710206,25.11686 19.002281,27.842341 17.84375,29.84375 C 16.485288,32.190546 13.833524,33.858876 11.53125,35.0625 C 9.7758989,35.980194 8.9024732,36.291093 8.25,36.53125 L 12,44.09375 L 22.8125,34 C 23.141077,33.70262 23.62883,33.664114 24,33.90625 C 24,33.90625 26.045443,35.241847 28.375,37.28125 C 30.391732,39.046791 32.509362,41.396107 33.9375,43.96875 L 38.875,39.1875 C 38.425182,38.341062 35.513684,33.014709 28.875,28.90625 C 28.511738,28.695573 28.324082,28.276051 28.409163,27.864827 C 28.494244,27.453602 28.832963,27.142985 29.25,27.09375 L 39.1875,25.65625 L 38.03125,19.96875 C 31.456326,21.456721 26.979371,21.554763 23.03125,19.28125 C 22.754401,19.121827 22.666044,19.133971 22.53125,19.15625 z " />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:url(#linearGradient2269);fill-opacity:1;stroke:#b49500;stroke-width:0.72577804;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path4302"
-- sodipodi:cx="10.555883"
-- sodipodi:cy="4.0385542"
-- sodipodi:rx="5.074944"
-- sodipodi:ry="5.074944"
-- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
-- transform="matrix(1.37826,0,0,1.377401,13.96243,3.935583)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.5;fill:#fce94f;fill-opacity:1;stroke:#ffffff;stroke-width:0.84666103;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path4273"
-- sodipodi:cx="10.555883"
-- sodipodi:cy="4.0385542"
-- sodipodi:rx="5.074944"
-- sodipodi:ry="5.074944"
-- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
-- transform="matrix(1.181111,0,0,1.181111,16.03826,4.728084)" />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/gadu-gadu.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/gadu-gadu.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/gadu-gadu.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/gadu-gadu.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,215 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="48px"
-- height="48px"
-- id="svg1307"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48/scalable"
-- sodipodi:docname="gadu-gadu.svg"
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/gadu-gadu.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs1309">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2447">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2449" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2451" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient3150">
-- <stop
-- style="stop-color:#2e3436;stop-opacity:1;"
-- offset="0"
-- id="stop3152" />
-- <stop
-- style="stop-color:#2e3436;stop-opacity:0;"
-- offset="1"
-- id="stop3154" />
-- </linearGradient>
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3150"
-- id="radialGradient3156"
-- cx="10.748654"
-- cy="10.457643"
-- fx="10.748654"
-- fy="10.457643"
-- r="6.6449099"
-- gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2233">
-- <stop
-- style="stop-color:#eeeeec;stop-opacity:1;"
-- offset="0"
-- id="stop2235" />
-- <stop
-- style="stop-color:#eeeeec;stop-opacity:0;"
-- offset="1"
-- id="stop2237" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2233"
-- id="linearGradient2279"
-- gradientUnits="userSpaceOnUse"
-- x1="24.450865"
-- y1="5.1375499"
-- x2="24.450865"
-- y2="31.487988" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2447"
-- id="linearGradient2453"
-- x1="24.5"
-- y1="0.33943355"
-- x2="24.5"
-- y2="19.724688"
-- gradientUnits="userSpaceOnUse" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="15.004828"
-- inkscape:cx="40.53287"
-- inkscape:cy="23.900599"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- inkscape:grid-bbox="true"
-- inkscape:document-units="px"
-- fill="#ef2929"
-- showguides="true"
-- inkscape:guide-bbox="true"
-- inkscape:window-width="1268"
-- inkscape:window-height="972"
-- inkscape:window-x="6"
-- inkscape:window-y="21" />
-- <metadata
-- id="metadata1312">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- id="layer1"
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer">
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.5;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path3140"
-- sodipodi:cx="10.748654"
-- sodipodi:cy="10.457643"
-- sodipodi:rx="6.6449099"
-- sodipodi:ry="2.3675451"
-- d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z"
-- transform="matrix(3.160314,0,0,2.745459,-9.969125,9.788968)" />
-- <path
-- style="opacity:1;fill:#ef2929;fill-opacity:1;fill-rule:evenodd;stroke:#a40000;stroke-width:0.9999997;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- d="M 22.5,4.5130623 L 22.5,8.6366327 C 19.782905,9.0005399 17.277282,10.079925 15.21875,11.698071 L 12.0625,8.5116761 L 9.5,11.073287 L 12.6875,14.259683 C 11.068793,16.317502 9.9577835,18.791017 9.59375,21.50717 L 5.5,21.50717 L 5.5,25.505784 L 9.59375,25.505784 C 9.9535644,28.234089 11.062591,30.718808 12.6875,32.78451 L 9.5,35.970906 L 12.0625,38.501278 L 15.21875,35.346123 C 17.277282,36.964269 19.782905,38.043654 22.5,38.407561 L 22.5,42.499891 L 26.5,42.499891 L 26.5,38.407561 C 29.229107,38.042044 31.717452,36.944842 33.78125,35.314883 L 36.96875,38.501278 L 39.5,35.970906 L 36.3125,32.78451 C 37.936789,30.719597 39.014761,28.232873 39.375,25.505784 L 43.5,25.505784 L 43.5,21.50717 L 39.375,21.50717 C 39.010966,18.791018 37.931208,16.317502 36.3125,14.259683 L 39.5,11.073287 L 36.96875,8.5116761 L 33.78125,11.698071 L 33.75,11.698071 C 31.691468,10.079924 29.217095,9.0005401 26.5,8.6366327 L 26.5,4.5130623 L 22.5,4.5130623 z M 23.8125,11.354441 C 24.033452,11.344807 24.274977,11.354441 24.5,11.354441 C 31.700731,11.354441 36.65625,16.339482 36.65625,23.537717 C 36.656248,30.735953 31.700731,35.689753 24.5,35.689753 C 17.29927,35.689754 12.502002,30.735951 12.502002,23.537717 C 12.502002,16.564428 16.962974,11.653081 23.8125,11.354441 z "
-- id="path2394"
-- sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccssssc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-1"
-- inkscape:original="M 22.5 4.5 L 22.5 8.625 C 19.782905 8.988907 17.277282 10.069354 15.21875 11.6875 L 12.0625 8.5 L 9.5 11.0625 L 12.6875 14.25 C 11.068793 16.307819 9.9577835 18.783847 9.59375 21.5 L 5.5 21.5 L 5.5 25.5 L 9.59375 25.5 C 9.9535644 28.228306 11.062591 30.715548 12.6875 32.78125 L 9.5 35.96875 L 12.0625 38.5 L 15.21875 35.34375 C 17.277282 36.961896 19.782905 38.042343 22.5 38.40625 L 22.5 42.5 L 26.5 42.5 L 26.5 38.40625 C 29.229107 38.040732 31.717452 36.942459 33.78125 35.3125 L 36.96875 38.5 L 39.5 35.96875 L 36.3125 32.78125 C 37.936789 30.716335 39.014761 28.227089 39.375 25.5 L 43.5 25.5 L 43.5 21.5 L 39.375 21.5 C 39.010966 18.783848 37.931208 16.307819 36.3125 14.25 L 39.5 11.0625 L 36.96875 8.5 L 33.78125 11.6875 L 33.75 11.6875 C 31.691468 10.069353 29.217095 8.9889074 26.5 8.625 L 26.5 4.5 L 22.5 4.5 z M 23.8125 11.34375 C 24.033452 11.334116 24.274977 11.34375 24.5 11.34375 C 31.700731 11.34375 36.65625 16.333015 36.65625 23.53125 C 36.656248 30.729485 31.700731 35.6875 24.5 35.6875 C 17.29927 35.6875 12.5 30.729484 12.5 23.53125 C 12.5 16.55796 16.962974 11.64239 23.8125 11.34375 z "
-- xlink:href="#path2394"
-- style="opacity:0.2;fill:url(#linearGradient2453);fill-opacity:1.0;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.9999997;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2445"
-- inkscape:href="#path2394"
-- d="M 23.5,5.5 L 23.5,8.625 C 23.503929,9.1319208 23.127956,9.5616039 22.625,9.625 C 20.085855,9.9650737 17.762357,10.960594 15.84375,12.46875 C 15.44664,12.797268 14.864902,12.77021 14.5,12.40625 L 12.0625,9.9375 L 10.9375,11.0625 L 13.40625,13.53125 C 13.77021,13.896152 13.797268,14.47789 13.46875,14.875 C 11.953567,16.801212 10.932828,19.095048 10.59375,21.625 C 10.530354,22.127956 10.100671,22.503929 9.59375,22.5 L 6.5,22.5 L 6.5,24.5 L 9.59375,24.5 C 10.100671,24.496071 10.530354,24.872044 10.59375,25.375 C 10.929039,27.917339 11.948302,30.223346 13.46875,32.15625 C 13.797268,32.55336 13.77021,33.135098 13.40625,33.5 L 10.9375,35.96875 L 12.03125,37.09375 L 14.5,34.625 C 14.864902,34.26104 15.44664,34.233982 15.84375,34.5625 C 17.762357,36.070656 20.085855,37.066176 22.625,37.40625 C 23.127956,37.469646 23.503929,37.899329 23.5,38.40625 L 23.5,41.5 L 25.5,41.5 L 25.5,38.40625 C 25.496071,37.899329 25.872044,37.469646 26.375,37.40625 C 28.92215,37.065102 31.227806,36.054308 33.15625,34.53125 C 33.55336,34.202732 34.135098,34.22979 34.5,34.59375 L 36.96875,37.0625 L 38.0625,35.96875 L 35.59375,33.5 C 35.22979,33.135098 35.202732,32.55336 35.53125,32.15625 C 37.047015,30.229299 38.038333,27.923642 38.375,25.375 C 38.438396,24.872044 38.868079,24.496071 39.375,24.5 L 42.5,24.5 L 42.5,22.5 L 39.375,22.5 C 38.868079,22.503929 38.438396,22.127956 38.375,21.625 C 38.034921,19.087581 37.042567,16.796296 35.53125,14.875 C 35.202732,14.47789 35.22979,13.896152 35.59375,13.53125 L 38.09375,11.03125 L 36.96875,9.9375 L 34.5,12.40625 C 34.307701,12.592396 34.048815,12.693699 33.78125,12.6875 L 33.75,12.6875 C 33.522871,12.68767 33.302449,12.610522 33.125,12.46875 C 31.202527,10.957555 28.913145,9.9649402 26.375,9.625 C 25.872044,9.5616039 25.496071,9.1319208 25.5,8.625 L 25.5,5.5 L 23.5,5.5 z M 23.78125,10.34375 C 24.062872,10.331471 24.303519,10.34375 24.5,10.34375 C 32.162653,10.34375 37.65625,15.874058 37.65625,23.53125 C 37.656248,31.188442 32.15976,36.6875 24.5,36.6875 C 20.67012,36.6875 17.391923,35.341265 15.09375,33 C 12.795577,30.658735 11.5,27.35261 11.5,23.53125 C 11.5,16.131287 16.473536,10.662367 23.78125,10.34375 z " />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:#edd400;fill-opacity:1;fill-rule:evenodd;stroke:#a40000;stroke-width:1.08146787;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2198"
-- sodipodi:cx="24.450865"
-- sodipodi:cy="23.959385"
-- sodipodi:rx="14.03053"
-- sodipodi:ry="14.03053"
-- d="M 38.481395 23.959385 A 14.03053 14.03053 0 1 1 10.420335,23.959385 A 14.03053 14.03053 0 1 1 38.481395 23.959385 z"
-- transform="matrix(0.924879,0,0,0.924459,1.889957,1.34006)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:url(#linearGradient2279);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.12198293;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2277"
-- sodipodi:cx="24.450865"
-- sodipodi:cy="23.959385"
-- sodipodi:rx="14.03053"
-- sodipodi:ry="14.03053"
-- d="M 38.481395 23.959385 A 14.03053 14.03053 0 1 1 10.420335,23.959385 A 14.03053 14.03053 0 1 1 38.481395 23.959385 z"
-- transform="matrix(0.890914,0,0,0.891279,2.716374,2.14037)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2200"
-- sodipodi:cx="10.54341"
-- sodipodi:cy="-2.7068274"
-- sodipodi:rx="2.4204714"
-- sodipodi:ry="1.7230475"
-- d="M 12.963882 -2.7068274 A 2.4204714 1.7230475 0 1 1 8.1229389,-2.7068274 A 2.4204714 1.7230475 0 1 1 12.963882 -2.7068274 z"
-- transform="matrix(0.827565,0,0,0.87352,11.27774,22.85935)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2202"
-- sodipodi:cx="10.54341"
-- sodipodi:cy="-2.7068274"
-- sodipodi:rx="2.4204714"
-- sodipodi:ry="1.7230475"
-- d="M 12.963882 -2.7068274 A 2.4204714 1.7230475 0 1 1 8.1229389,-2.7068274 A 2.4204714 1.7230475 0 1 1 12.963882 -2.7068274 z"
-- transform="matrix(0.827567,0,0,0.87352,20.27772,22.86958)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#2e3436;stroke-width:4.5851903;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2204"
-- sodipodi:cx="24.450865"
-- sodipodi:cy="23.959385"
-- sodipodi:rx="14.03053"
-- sodipodi:ry="14.03053"
-- d="M 36.657066,30.877796 A 14.03053,14.03053 0 0 1 11.928959,30.288496"
-- transform="matrix(0.453563,0,0,0.419476,13.51464,14.26249)"
-- sodipodi:start="0.51564596"
-- sodipodi:end="2.6736"
-- sodipodi:open="true" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.5;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.75245398;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2465"
-- sodipodi:cx="26.658085"
-- sodipodi:cy="20.675463"
-- sodipodi:rx="9.863492"
-- sodipodi:ry="8.2640066"
-- d="M 36.521577 20.675463 A 9.863492 8.2640066 0 1 1 16.794593,20.675463 A 9.863492 8.2640066 0 1 1 36.521577 20.675463 z"
-- transform="matrix(1.216989,0,0,1.451287,-7.948546,-6.503855)" />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/google-talk.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/google-talk.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/google-talk.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/google-talk.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,261 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- id="svg2417"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- width="48"
-- height="48"
-- version="1.0"
-- sodipodi:docbase="/home/vinicius/tango-icon-theme-code/protocols/scalable"
-- sodipodi:docname="google-talk.svg"
-- inkscape:export-filename="/home/vinicius/tango-icon-theme-code/protocols/48x48/google-talk.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <metadata
-- id="metadata2422">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- <dc:title>Google Talk Icon</dc:title>
-- <dc:date>2006-12-03</dc:date>
-- <dc:creator>
-- <cc:Agent>
-- <dc:title>Vinicius Scopel Depizzol</dc:title>
-- </cc:Agent>
-- </dc:creator>
-- <dc:source>vdepizzol@gmail.com</dc:source>
-- <dc:subject>
-- <rdf:Bag>
-- <rdf:li>Google Talk</rdf:li>
-- <rdf:li>GTalk</rdf:li>
-- <rdf:li>VOIP</rdf:li>
-- <rdf:li>Protocol</rdf:li>
-- </rdf:Bag>
-- </dc:subject>
-- <cc:license
-- rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
-- </cc:Work>
-- <cc:License
-- rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
-- <cc:permits
-- rdf:resource="http://web.resource.org/cc/Reproduction" />
-- <cc:permits
-- rdf:resource="http://web.resource.org/cc/Distribution" />
-- <cc:requires
-- rdf:resource="http://web.resource.org/cc/Notice" />
-- <cc:requires
-- rdf:resource="http://web.resource.org/cc/Attribution" />
-- <cc:permits
-- rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
-- <cc:requires
-- rdf:resource="http://web.resource.org/cc/ShareAlike" />
-- </cc:License>
-- </rdf:RDF>
-- </metadata>
-- <defs
-- id="defs2420">
-- <linearGradient
-- id="linearGradient3299">
-- <stop
-- style="stop-color:#000000;stop-opacity:0.11764706;"
-- offset="0"
-- id="stop3301" />
-- <stop
-- style="stop-color:#000000;stop-opacity:0;"
-- offset="1"
-- id="stop3303" />
-- </linearGradient>
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3299"
-- id="radialGradient3305"
-- cx="15.993708"
-- cy="26.722889"
-- fx="15.993708"
-- fy="26.722889"
-- r="15.912521"
-- gradientTransform="matrix(1,0,0,0.295918,-3.769888e-16,18.8151)"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- id="linearGradient3527">
-- <stop
-- style="stop-color:#90ba1f;stop-opacity:1;"
-- offset="0"
-- id="stop3529" />
-- <stop
-- style="stop-color:#638205;stop-opacity:1;"
-- offset="1"
-- id="stop3531" />
-- </linearGradient>
-- <linearGradient
-- id="linearGradient3518">
-- <stop
-- style="stop-color:#e7d000;stop-opacity:1;"
-- offset="0"
-- id="stop3520" />
-- <stop
-- style="stop-color:#c4a000;stop-opacity:1;"
-- offset="1"
-- id="stop3522" />
-- </linearGradient>
-- <linearGradient
-- id="linearGradient3486">
-- <stop
-- style="stop-color:#ef2929;stop-opacity:1;"
-- offset="0"
-- id="stop3488" />
-- <stop
-- style="stop-color:#cc0000;stop-opacity:1;"
-- offset="1"
-- id="stop3490" />
-- </linearGradient>
-- <linearGradient
-- id="linearGradient3510">
-- <stop
-- style="stop-color:#3465a4;stop-opacity:1;"
-- offset="0"
-- id="stop3512" />
-- <stop
-- style="stop-color:#204a87;stop-opacity:1;"
-- offset="1"
-- id="stop3514" />
-- </linearGradient>
-- <linearGradient
-- id="linearGradient3286">
-- <stop
-- style="stop-color:#d1d1d1;stop-opacity:1;"
-- offset="0"
-- id="stop3288" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="1"
-- id="stop3290" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3527"
-- id="linearGradient4249"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(2.465389,0,0,2.513895,-105.5963,47.11115)"
-- x1="55.483334"
-- y1="-14.40625"
-- x2="55.483334"
-- y2="-7.9999866" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3518"
-- id="linearGradient4252"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(2.901968,0,0,2.518653,-127.7063,47.25387)"
-- x1="53.162479"
-- y1="-14.322747"
-- x2="53.162479"
-- y2="-9.9868765" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3486"
-- id="linearGradient4255"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(2.48585,0,0,2.48585,-103.0483,47.16833)"
-- x1="49.45462"
-- y1="-12.934268"
-- x2="49.45462"
-- y2="-8.0529032" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3510"
-- id="linearGradient4258"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(2.48585,0,0,2.48585,-100.3774,47.19573)"
-- x1="45.5"
-- y1="-14"
-- x2="45.5"
-- y2="-8.1156492" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3286"
-- id="linearGradient4262"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(2.99378,0,0,2.99378,9.552849e-2,-0.965622)"
-- x1="8"
-- y1="15"
-- x2="8"
-- y2="0.9916327" />
-- </defs>
-- <sodipodi:namedview
-- inkscape:window-height="714"
-- inkscape:window-width="1014"
-- inkscape:pageshadow="2"
-- inkscape:pageopacity="0"
-- borderopacity="1"
-- bordercolor="#666666"
-- pagecolor="#ffffff"
-- id="base"
-- showgrid="false"
-- showguides="true"
-- inkscape:guide-bbox="true"
-- inkscape:zoom="1"
-- inkscape:cx="27.558407"
-- inkscape:cy="20.353863"
-- inkscape:window-x="0"
-- inkscape:window-y="0"
-- inkscape:current-layer="svg2417"
-- showborder="false"
-- inkscape:showpageshadow="false" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:url(#radialGradient3305);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
-- id="path2424"
-- sodipodi:cx="15.993708"
-- sodipodi:cy="26.722889"
-- sodipodi:rx="15.912521"
-- sodipodi:ry="4.7088075"
-- d="M 31.906229,26.722889 A 15.912521,4.7088075 0 1 1 31.906148,26.707864"
-- sodipodi:start="0"
-- sodipodi:end="6.2799944"
-- sodipodi:open="true"
-- transform="matrix(1.45896,0,0,1.538545,0.742037,-1.869655)" />
-- <path
-- id="path3264"
-- d="M 21.80045,3.5250496 C 10.471905,4.3704822 1.592428,11.452408 1.592428,19.990844 C 1.592428,26.29506 6.3896918,31.807945 13.473996,34.585527 C 13.301077,37.113716 12.611393,40.274075 10.57377,42.444203 C 16.402876,42.263357 20.689781,39.28536 23.484452,36.456639 C 23.677129,36.460226 23.851935,36.456639 24.045787,36.456639 C 36.451938,36.456639 46.499142,29.098509 46.499142,19.990844 L 46.499142,19.897289 C 46.459634,10.808172 36.426737,3.5250496 24.045787,3.5250496 C 23.270404,3.5250496 22.555687,3.4686875 21.80045,3.5250496 z "
-- style="fill:url(#linearGradient4262);fill-opacity:1;fill-rule:nonzero;stroke:#797979;stroke-width:0.99999946;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90" />
-- <path
-- sodipodi:nodetypes="ccccccccccccccccc"
-- id="path3552"
-- d="M 14.063569,10.992619 L 10.975162,10.992619 L 10.975162,15.008301 L 9,15.008301 L 9,18.010155 L 10.975162,18.010155 L 10.975162,24.823081 C 10.975162,28.316382 16.413217,26.749332 16.906897,25.946127 L 16.765885,23.742745 C 16.14428,24.364355 14.063569,24.882059 14.063569,24.09267 L 14.063569,18.010155 L 16.089796,18.010155 L 16.089796,15.008301 L 14.063569,15.008301 L 14.063569,11.090553 L 14.063569,11.090553 L 14.063569,10.992619 z "
-- style="fill:url(#linearGradient4258);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
-- <path
-- style="fill:url(#linearGradient4255);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
-- d="M 20.513467,15.031036 C 20.138171,15.089956 19.656414,15.165467 19.228078,15.318859 C 17.702481,15.865192 16.671718,16.778263 16.671718,16.778263 L 17.928902,19.157272 C 19.392632,18.022338 22.111019,16.595753 21.828421,20.24551 C 16.134551,19.714196 14.746648,23.348506 16.160515,25.369297 C 17.612211,27.444158 20.173876,27.641863 21.329645,26.185476 C 21.514145,25.952987 21.740964,25.678231 21.873764,25.369297 C 22.016347,25.75349 22.226874,26.072865 22.417883,26.321505 C 22.574471,26.517581 23.312178,27.152657 24.004897,27.137684 C 24.806193,27.120365 25.583813,26.58185 26,25.958759 C 25.645136,26.22137 24.252362,25.650216 24.231613,24.779835 L 24.231613,18.29575 C 24.142462,16.667478 22.425687,14.730825 20.513467,15.031036 z M 21.193616,23.328851 C 21.034551,24.122851 19.396586,24.681233 18.790423,24.326402 C 17.894487,23.801947 19.229645,22.393776 20.377437,22.376643 C 21.417389,22.361119 21.33274,22.634384 21.193616,23.328851 z "
-- id="path3554"
-- sodipodi:nodetypes="cscccsscsscccccsss" />
-- <path
-- id="path3558"
-- d="M 29,11 L 26.098032,11 L 26.098032,27.104637 L 29,27.104637 L 29,11 z "
-- style="fill:url(#linearGradient4252);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
-- <path
-- sodipodi:nodetypes="ccccccccccccc"
-- id="path3560"
-- d="M 30,10.895363 L 30,19.851112 L 30,27 L 32.963722,27 L 32.963722,22.924045 L 36.561805,27.064163 L 38.705904,25.193137 L 34.676855,20.715264 L 38.705904,16.23739 L 36.754295,14.238037 L 32.968278,18.187047 C 32.968278,18.187047 32.963722,10.895363 32.963722,10.895363 L 30,10.895363 z "
-- style="fill:url(#linearGradient4249);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
-- <path
-- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
-- d="M 21.84375,4.03125 C 16.273135,4.4469767 11.295199,6.3799921 7.75,9.25 C 4.204801,12.120008 2.09375,15.904106 2.09375,20 C 2.093752,26.050562 6.709849,31.401486 13.65625,34.125 C 13.889662,34.247612 13.966606,34.430582 13.96875,34.625 C 13.8154,36.867085 13.233839,39.586592 11.6875,41.78125 C 16.756159,41.27394 20.580438,38.669315 23.125,36.09375 C 23.324492,35.928053 23.831229,35.96875 24.03125,35.96875 C 30.135475,35.96875 35.660367,34.1562 39.625,31.25 C 43.589633,28.3438 46,24.369973 46,20 L 46,19.90625 C 45.981043,15.545078 43.55655,11.604324 39.59375,8.71875 C 35.63095,5.8331761 30.123683,4.03125 24.03125,4.03125 C 23.381564,4.0312499 22.681539,3.982177 21.84375,4.03125 z M 24.03125,5.03125 C 29.927599,5.03125 35.264412,6.757119 39.03125,9.5 C 42.798088,12.242881 44.982638,15.911852 45,19.90625 L 45,20 C 45,24.002253 42.800008,27.674883 39.03125,30.4375 C 35.262492,33.200117 29.937773,34.96875 24.03125,34.96875 C 23.079654,34.946683 22.695929,35.117383 22.40625,35.40625 C 20.316957,37.520999 17.387178,39.593629 13.59375,40.46875 C 14.470139,38.520138 14.848653,36.443413 14.96875,34.6875 C 15.010593,33.903846 14.715478,33.607465 14.03125,33.1875 C 7.360656,30.572123 3.093751,25.543254 3.09375,20 C 3.09375,16.250753 5.042528,12.754344 8.40625,10.03125 C 11.769972,7.3081563 16.52295,5.4329977 21.90625,5.03125 C 22.667268,4.9737265 23.342191,5.0312499 24.03125,5.03125 z "
-- id="path6054"
-- sodipodi:nodetypes="csscccccsccssccsccscscccsscs" />
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/icq.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/icq.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/icq.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/icq.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,440 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="48"
-- height="48"
-- id="svg2"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- version="1.0"
-- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48"
-- sodipodi:docname="icq.svg"
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/icq.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs4">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2256">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2258" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2260" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2248">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2250" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2252" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2240">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2242" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2244" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2232">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2234" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2236" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2224">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2226" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2228" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2216">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2218" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2220" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2208">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2210" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2212" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2361">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2363" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2365" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2321">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2323" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2325" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient3150">
-- <stop
-- style="stop-color:#2e3436;stop-opacity:1;"
-- offset="0"
-- id="stop3152" />
-- <stop
-- style="stop-color:#2e3436;stop-opacity:0;"
-- offset="1"
-- id="stop3154" />
-- </linearGradient>
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3150"
-- id="radialGradient3156"
-- cx="10.748654"
-- cy="10.457643"
-- fx="10.748654"
-- fy="10.457643"
-- r="6.6449099"
-- gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2321"
-- id="linearGradient2327"
-- x1="11.787398"
-- y1="11.115861"
-- x2="12.185872"
-- y2="12.839791"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2361"
-- id="linearGradient2367"
-- x1="14.592834"
-- y1="24.232048"
-- x2="14.592834"
-- y2="31.007147"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2208"
-- id="linearGradient2214"
-- x1="28.089931"
-- y1="3.8865747"
-- x2="28.089931"
-- y2="15.058928"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2216"
-- id="linearGradient2222"
-- x1="36.696918"
-- y1="10.99979"
-- x2="36.696918"
-- y2="20.717306"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2224"
-- id="linearGradient2230"
-- x1="36.701996"
-- y1="20.379145"
-- x2="36.701996"
-- y2="29.063459"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2232"
-- id="linearGradient2238"
-- x1="17.892992"
-- y1="6.7056818"
-- x2="17.892992"
-- y2="16.46983"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2240"
-- id="linearGradient2246"
-- x1="12.732279"
-- y1="14.645196"
-- x2="12.732279"
-- y2="23.238768"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2248"
-- id="linearGradient2254"
-- x1="21.683891"
-- y1="24.981401"
-- x2="21.683891"
-- y2="36.415653"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2256"
-- id="linearGradient2262"
-- x1="30.265167"
-- y1="27.26486"
-- x2="30.265167"
-- y2="35.256603"
-- gradientUnits="userSpaceOnUse" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="14.778489"
-- inkscape:cx="38.03465"
-- inkscape:cy="24.512139"
-- inkscape:document-units="px"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- fill="#ef2929"
-- inkscape:window-width="1268"
-- inkscape:window-height="971"
-- inkscape:window-x="6"
-- inkscape:window-y="21" />
-- <metadata
-- id="metadata7">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer"
-- id="layer1">
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.5;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path3140"
-- sodipodi:cx="10.748654"
-- sodipodi:cy="10.457643"
-- sodipodi:rx="6.6449099"
-- sodipodi:ry="2.3675451"
-- d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z"
-- transform="matrix(3.009823,0,0,2.74546,-8.351546,7.855242)" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000048;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 26.367384,35.737238 C 24.85713,31.115741 25.395878,30.363552 27.387814,29.222534 C 29.379747,28.081519 30.462949,28.167777 33.584537,31.603121 C 35.536982,34.958339 35.504926,38.607457 33.513001,39.748468 C 31.521063,40.889489 28.319827,39.092453 26.367384,35.737238 z "
-- id="path2226"
-- sodipodi:nodetypes="cscsc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.95876986"
-- inkscape:original="M 28.75 28.625 C 28.319559 28.723691 27.872983 28.933496 27.375 29.21875 C 25.383064 30.359768 24.864746 31.128501 26.375 35.75 C 28.327443 39.105215 31.508063 40.891023 33.5 39.75 C 35.491925 38.608989 35.546194 34.948968 33.59375 31.59375 C 31.252559 29.017242 30.041322 28.328926 28.75 28.625 z "
-- xlink:href="#path2226"
-- style="opacity:0.4;fill:url(#linearGradient2262);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2242"
-- inkscape:href="#path2226"
-- d="M 28.96875,26.5 C 28.686015,26.564825 28.303156,26.736844 27.84375,27 C 27.368858,27.272027 27.042376,27.491026 26.84375,27.6875 C 26.645124,27.883974 26.558141,28.035355 26.5,28.3125 C 26.386493,28.853563 26.554045,30.085975 27.25,32.25 C 28.145595,33.765674 29.317595,34.913452 30.40625,35.53125 C 31.510083,36.157661 32.416733,36.195758 33.03125,35.84375 C 33.64681,35.491146 34.046689,34.69972 34.0625,33.4375 C 34.077874,32.210233 33.659976,30.628765 32.8125,29.125 C 31.711537,27.921881 30.874722,27.139693 30.28125,26.78125 C 29.672583,26.41363 29.393014,26.402725 28.96875,26.5 z "
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:0.99999982;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 33.709491,31.278338 C 29.169302,28.745112 29.065713,27.592023 29.859889,24.733701 C 30.654065,21.875391 31.593198,20.926512 36.586936,20.922121 C 40.576342,21.952999 43.16957,25.109445 42.375396,27.967758 C 41.581221,30.826078 37.6989,32.309217 33.709491,31.278338 z "
-- id="path2216"
-- sodipodi:nodetypes="cscsc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.98264426"
-- inkscape:original="M 36.59375 20.9375 C 31.600012 20.941891 30.669177 21.860439 29.875 24.71875 C 29.080824 27.577072 29.17856 28.748025 33.71875 31.28125 C 37.708159 32.312129 41.580824 30.82707 42.375 27.96875 C 43.169174 25.110437 40.583155 21.968378 36.59375 20.9375 z "
-- xlink:href="#path2216"
-- style="opacity:0.4;fill:url(#linearGradient2230);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2238"
-- inkscape:href="#path2216"
-- d="M 36.4375,18.8125 C 34.127551,18.828525 32.839067,19.094363 32.1875,19.5 C 31.517812,19.916918 31.190595,20.545455 30.8125,21.90625 C 30.427461,23.292046 30.362754,23.987827 30.6875,24.625 C 31.003678,25.245362 31.967431,26.095761 34.0625,27.28125 C 35.838582,27.720407 37.581667,27.600958 38.90625,27.09375 C 40.254639,26.577426 41.138951,25.730758 41.4375,24.65625 C 41.735829,23.582532 41.424738,22.405518 40.53125,21.3125 C 39.654391,20.239825 38.199379,19.288753 36.4375,18.8125 z "
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 36.67848,22.648043 C 32.052133,24.231706 31.299156,23.66677 30.15694,21.57801 C 29.014732,19.489253 29.101081,18.3534 32.540028,15.08008 C 35.898764,13.032731 39.551708,13.066339 40.693916,15.155093 C 41.836132,17.243854 40.037215,20.600694 36.67848,22.648043 z "
-- id="path2224"
-- sodipodi:nodetypes="cscsc" />
-- <path
-- style="fill:#ef2929;fill-opacity:1;stroke:#a40000;stroke-width:1.00000167;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 15.680976,33.623016 C 11.05302,35.149988 10.299782,34.605272 9.1571703,32.591284 C 8.0145636,30.577295 8.100941,29.482102 11.541085,26.325956 C 14.900987,24.351896 18.555202,24.3843 19.697807,26.398287 C 20.840426,28.412273 19.040877,31.648952 15.680976,33.623016 z "
-- id="path2228"
-- sodipodi:nodetypes="cscsc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-1.0000435"
-- inkscape:original="M 16.4375 24.875 C 14.961133 24.861908 13.211201 25.32547 11.53125 26.3125 C 8.091106 29.468646 8.0136433 30.579759 9.15625 32.59375 C 10.298862 34.607738 11.059544 35.151972 15.6875 33.625 C 19.047401 31.650936 20.830119 28.420236 19.6875 26.40625 C 19.116197 25.399256 17.913867 24.888092 16.4375 24.875 z "
-- xlink:href="#path2228"
-- style="opacity:0.35;fill:url(#linearGradient2367);fill-opacity:1;stroke:#ffffff;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-- id="path2244"
-- inkscape:href="#path2228"
-- d="M 16.4375,25.5625 C 15.225911,25.551756 13.660678,25.986763 12.15625,26.84375 C 10.550146,28.330129 9.7557904,29.328548 9.5625,29.90625 C 9.3649665,30.496634 9.5025865,30.849414 10.03125,31.78125 C 10.302942,32.260138 10.523169,32.613015 10.71875,32.8125 C 10.914331,33.011985 11.040068,33.097389 11.3125,33.15625 C 11.836378,33.269438 13.116625,33.081343 15.21875,32.40625 C 16.739932,31.503646 17.889523,30.32189 18.5,29.21875 C 19.115832,28.105933 19.160409,27.206976 18.8125,26.59375 C 18.466678,25.984194 17.687878,25.573588 16.4375,25.5625 z "
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- transform="translate(-3.261295e-4,1.945628e-4)" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 15.781196,31.980797 C 18.406839,27.241987 19.600601,27.133027 22.558995,27.959412 C 25.517377,28.785792 26.498997,29.764879 26.5,34.97494 C 25.429993,39.137961 22.160569,41.845948 19.202184,41.019566 C 16.24379,40.193181 14.711189,36.143816 15.781196,31.980797 z "
-- id="path2218"
-- sodipodi:nodetypes="cscsc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-1.0089091"
-- inkscape:original="M 20.625 27.5625 C 18.918105 27.466646 17.750483 28.414643 15.78125 31.96875 C 14.711243 36.131769 16.229105 40.204865 19.1875 41.03125 C 22.145885 41.857632 25.429993 39.13177 26.5 34.96875 C 26.498997 29.758689 25.520883 28.79513 22.5625 27.96875 C 21.822902 27.762154 21.193965 27.594451 20.625 27.5625 z "
-- xlink:href="#path2218"
-- style="opacity:0.4;fill:url(#linearGradient2254);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2240"
-- inkscape:href="#path2218"
-- d="M 20.5625,25.5 C 19.907811,25.463235 19.561004,25.566238 18.96875,26.09375 C 18.39939,26.600871 17.659523,27.663233 16.75,29.28125 C 16.300255,31.130934 16.385773,32.955321 16.90625,34.34375 C 17.438569,35.763767 18.360161,36.690332 19.46875,37 C 20.577929,37.309833 21.771436,36.972415 22.90625,36.03125 C 24.020697,35.106976 25.004678,33.595596 25.5,31.75 C 25.485662,29.33285 25.202556,27.963789 24.78125,27.28125 C 24.348724,26.580535 23.69033,26.268606 22.28125,25.875 C 21.548137,25.670215 20.975703,25.523204 20.5625,25.5 z "
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 22.589636,12.085809 C 24.174724,16.906782 23.609284,17.691436 21.518638,18.881701 C 19.427991,20.071964 18.291112,19.981984 15.014841,16.398361 C 12.965643,12.898328 12.999283,9.0917088 15.089923,7.9014452 C 17.180566,6.7111801 20.540438,8.5857754 22.589636,12.085809 z "
-- id="path2222"
-- sodipodi:nodetypes="cscsc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.96927398"
-- inkscape:original="M 16.84375 7.5625 C 16.202747 7.4994497 15.616411 7.6086837 15.09375 7.90625 C 13.00311 9.0965136 12.950802 12.906217 15 16.40625 C 18.276271 19.989873 19.440602 20.065263 21.53125 18.875 C 23.621896 17.684735 24.178838 16.914723 22.59375 12.09375 C 21.056852 9.4687248 18.76676 7.7516509 16.84375 7.5625 z "
-- xlink:href="#path2222"
-- style="opacity:0.4;fill:url(#linearGradient2238);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2232"
-- inkscape:href="#path2222"
-- d="M 16.75,5.46875 C 16.27484,5.4220124 15.902933,5.4936816 15.5625,5.6875 C 14.90056,6.0643619 14.484412,6.9299953 14.46875,8.25 C 14.453381,9.5453187 14.903286,11.163341 15.8125,12.75 C 17.344427,14.407623 18.369904,15.229192 19,15.4375 C 19.647022,15.651404 20.092056,15.52125 21.0625,14.96875 C 21.562192,14.684261 21.911138,14.459507 22.125,14.25 C 22.338862,14.040493 22.436992,13.887548 22.5,13.59375 C 22.621375,13.027792 22.42463,11.70151 21.71875,9.5 C 20.300551,7.1027674 18.170695,5.6084922 16.75,5.46875 z "
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- transform="translate(0,6.766591e-2)" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000072;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 15.110245,15.90519 C 19.82436,18.526878 19.931835,19.720374 19.106984,22.678924 C 18.282136,25.637465 17.306916,26.619664 12.121668,26.624562 C 7.9793465,25.557832 5.2869063,22.290944 6.1117518,19.332403 C 6.9366004,16.373851 10.967924,14.838461 15.110245,15.90519 z "
-- id="path2220"
-- sodipodi:nodetypes="cscsc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-1.0062078"
-- inkscape:original="M 12.0625 15.5625 C 9.1424837 15.682984 6.7436363 17.124836 6.125 19.34375 C 5.3001545 22.302291 7.9826786 25.558271 12.125 26.625 C 17.310248 26.620102 18.268903 25.64604 19.09375 22.6875 C 19.918601 19.72895 19.839115 18.527938 15.125 15.90625 C 14.08942 15.639568 13.035839 15.522339 12.0625 15.5625 z "
-- xlink:href="#path2220"
-- style="opacity:0.4;fill:url(#linearGradient2246);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2234"
-- inkscape:href="#path2220"
-- d="M 12.09375,13.5 C 9.4814409,13.607788 7.5619569,14.883144 7.09375,16.5625 C 6.7827532,17.677978 7.1032888,18.873814 8.03125,20 C 8.9425567,21.105974 10.44513,22.068869 12.28125,22.5625 C 14.685442,22.546282 16.040043,22.264255 16.71875,21.84375 C 17.415725,21.411927 17.731987,20.753401 18.125,19.34375 C 18.525721,17.906458 18.614647,17.219888 18.28125,16.5625 C 17.956369,15.921903 16.929755,15.04136 14.75,13.8125 C 13.845755,13.591694 12.918322,13.465977 12.09375,13.5 z "
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-1.0066811"
-- inkscape:original="M 37.4375 13.5625 C 35.961646 13.548922 34.210618 14.070075 32.53125 15.09375 C 29.092303 18.36707 29.014042 19.473742 30.15625 21.5625 C 31.298466 23.65126 32.061155 24.239913 36.6875 22.65625 C 40.046235 20.608901 41.829716 17.245011 40.6875 15.15625 C 40.116396 14.111873 38.913354 13.576078 37.4375 13.5625 z "
-- xlink:href="#path2224"
-- style="opacity:0.4;fill:url(#linearGradient2222);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2236"
-- inkscape:href="#path2224"
-- d="M 37.4375,11.5 C 36.209007,11.488698 34.640843,11.934525 33.125,12.84375 C 31.572994,14.343465 30.790495,15.387459 30.59375,16 C 30.38941,16.636186 30.501711,17.062882 31.03125,18.03125 C 31.303727,18.529526 31.551384,18.882242 31.75,19.09375 C 31.948616,19.305258 32.078397,19.376294 32.34375,19.4375 C 32.849897,19.554247 34.121629,19.37131 36.1875,18.6875 C 37.705568,17.753005 38.884734,16.530737 39.5,15.375 C 40.120629,14.209188 40.168638,13.213767 39.8125,12.5625 C 39.457388,11.913107 38.674773,11.511383 37.4375,11.5 z "
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000048;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 33.125387,15.014401 C 30.26869,19.896731 28.973236,20.010902 25.764644,19.165247 C 22.556047,18.319592 21.492567,17.31342 21.500039,11.950433 C 22.667874,7.6634206 26.219761,4.8704358 29.428357,5.7160909 C 32.636953,6.5617466 34.293217,10.72739 33.125387,15.014401 z "
-- id="path2192"
-- sodipodi:nodetypes="cscsc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.99950546"
-- inkscape:original="M 27 5.71875 C 24.592663 6.34847 22.375877 8.7222409 21.5 11.9375 C 21.492528 17.300487 22.541402 18.310595 25.75 19.15625 C 28.958592 20.001905 30.268305 19.88233 33.125 15 C 34.29283 10.712989 32.646097 6.5644059 29.4375 5.71875 C 28.635351 5.5073362 27.802446 5.5088433 27 5.71875 z "
-- xlink:href="#path2192"
-- style="opacity:0.4;fill:url(#linearGradient2214);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2230"
-- inkscape:href="#path2192"
-- d="M 27.25,3.625 C 25.314633,4.1312603 23.314958,6.1607857 22.5,9.03125 C 22.510826,11.522864 22.789343,12.909624 23.25,13.625 C 23.722547,14.358839 24.464582,14.720327 26,15.125 C 27.560661,15.536327 28.366368,15.654754 29.125,15.28125 C 29.867191,14.91584 30.838854,13.842149 32.1875,11.5625 C 32.678344,9.6587072 32.56307,7.7926235 32,6.375 C 31.424078,4.9250185 30.443053,3.9559128 29.1875,3.625 C 28.551361,3.4573398 27.889759,3.4576495 27.25,3.625 z "
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:#edd400;fill-opacity:1;stroke:#c4a000;stroke-width:0.21428883;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path1317"
-- sodipodi:cx="12.075002"
-- sodipodi:cy="12.360133"
-- sodipodi:rx="1.1966218"
-- sodipodi:ry="1.4141895"
-- d="M 13.271623 12.360133 A 1.1966218 1.4141895 0 1 1 10.87838,12.360133 A 1.1966218 1.4141895 0 1 1 13.271623 12.360133 z"
-- transform="matrix(4.891864,1.290148,-1.13072,4.153499,-20.5947,-43.34178)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.4;fill:url(#linearGradient2327);fill-opacity:1;stroke:#ffffff;stroke-width:0.25782824;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2319"
-- sodipodi:cx="12.075002"
-- sodipodi:cy="12.360133"
-- sodipodi:rx="1.1966218"
-- sodipodi:ry="1.4141895"
-- d="M 13.271623 12.360133 A 1.1966218 1.4141895 0 1 1 10.87838,12.360133 A 1.1966218 1.4141895 0 1 1 13.271623 12.360133 z"
-- transform="matrix(4.068634,1.071527,-0.940435,3.449674,-13.02699,-32.06442)" />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/meanwhile.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/meanwhile.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/meanwhile.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/meanwhile.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,174 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="48"
-- height="48"
-- id="svg2"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- version="1.0"
-- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48"
-- sodipodi:docname="meanwhile.svg"
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/meanwhile.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs4">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2195">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2197" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2199" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2230">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2232" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2234" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient3150">
-- <stop
-- style="stop-color:#2e3436;stop-opacity:1;"
-- offset="0"
-- id="stop3152" />
-- <stop
-- style="stop-color:#2e3436;stop-opacity:0;"
-- offset="1"
-- id="stop3154" />
-- </linearGradient>
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3150"
-- id="radialGradient4330"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
-- cx="10.748654"
-- cy="10.457643"
-- fx="10.748654"
-- fy="10.457643"
-- r="6.6449099" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2230"
-- id="linearGradient2236"
-- x1="10.177145"
-- y1="-1.3535745"
-- x2="10.177145"
-- y2="8.1371298"
-- gradientUnits="userSpaceOnUse" />
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2195"
-- id="radialGradient2211"
-- cx="30.5625"
-- cy="23.172834"
-- fx="30.5625"
-- fy="23.172834"
-- r="23.5"
-- gradientTransform="matrix(1.330958,-1.200379e-32,1.144509e-32,1.269011,-10.11491,-9.053927)"
-- gradientUnits="userSpaceOnUse" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="16.976026"
-- inkscape:cx="38.972041"
-- inkscape:cy="25.781032"
-- inkscape:document-units="px"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- fill="#f57900"
-- showguides="true"
-- inkscape:guide-bbox="true"
-- inkscape:window-width="1268"
-- inkscape:window-height="971"
-- inkscape:window-x="6"
-- inkscape:window-y="21" />
-- <metadata
-- id="metadata7">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer"
-- id="layer1">
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.3;fill:url(#radialGradient4330);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path3140"
-- sodipodi:cx="10.748654"
-- sodipodi:cy="10.457643"
-- sodipodi:rx="6.6449099"
-- sodipodi:ry="2.3675451"
-- d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z"
-- transform="matrix(3.583369,0,0,3.000545,-14.70523,9.779617)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:1;fill:#f57900;fill-opacity:1;stroke:#ce5c00;stroke-width:0.67679459;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path4302"
-- sodipodi:cx="10.555883"
-- sodipodi:cy="4.0385542"
-- sodipodi:rx="5.074944"
-- sodipodi:ry="5.074944"
-- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
-- transform="matrix(1.477556,0,0,1.477551,8.403577,4.033323)" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.6;fill:url(#linearGradient2236);fill-opacity:1;stroke:#ffffff;stroke-width:0.78084576;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path4273"
-- sodipodi:cx="10.555883"
-- sodipodi:cy="4.0385542"
-- sodipodi:rx="5.074944"
-- sodipodi:ry="5.074944"
-- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
-- transform="matrix(1.280662,0,0,1.280662,10.48149,4.827989)" />
-- <path
-- style="fill:#f57900;fill-opacity:1;stroke:#ce5c00;stroke-width:1.00000119;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 34.49131,8.6205284 C 34.49131,13.938683 32.849731,20.518688 23.898198,20.518688 C 15.00451,20.518688 13.526711,13.679495 13.526711,8.6600767 L 5.4949228,9.8762415 C 5.4949228,23.237275 17.664236,26.553794 17.664236,26.553794 C 17.664236,26.553794 9.1712538,34.298165 9.1712538,44.405547 L 19.237281,44.498262 C 19.237281,44.498262 21.456328,35.564348 25.010569,35.564348 C 28.652494,35.564348 30.6887,44.471546 30.6887,44.471546 L 40.362294,44.503507 C 40.362294,33.010164 30.381957,26.578174 30.381957,26.578174 C 30.381957,26.578174 42.614757,23.170121 42.614757,9.5035195 L 34.49131,8.6205284 z "
-- id="rect2213"
-- sodipodi:nodetypes="czccccczccccc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.9525249"
-- inkscape:original="M 34.5 8.625 C 34.5 13.943155 32.857783 20.53125 23.90625 20.53125 C 15.012563 20.53125 13.53125 13.675668 13.53125 8.65625 L 5.5 9.875 C 5.5000002 23.236033 17.65625 26.5625 17.65625 26.5625 C 17.65625 26.562499 9.15625 34.298868 9.15625 44.40625 L 19.25 44.5 C 19.249999 44.500002 21.445759 35.5625 25 35.5625 C 28.641925 35.562502 30.6875 44.46875 30.6875 44.46875 L 40.375 44.5 C 40.375001 33.006658 30.375 26.59375 30.375 26.59375 C 30.375001 26.593749 42.625 23.166602 42.625 9.5 L 34.5 8.625 z "
-- xlink:href="#rect2213"
-- style="opacity:0.6;fill:url(#radialGradient2211);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2220"
-- inkscape:href="#rect2213"
-- d="M 45.40625,11.75 C 45.26383,14.467634 44.656918,17.754917 42.6875,20.65625 C 40.459732,23.938183 36.552927,26.5 30.5,26.5 C 24.488156,26.5 20.637234,23.994802 18.4375,20.75 C 16.4845,17.869153 15.883719,14.581533 15.75,11.84375 L 7.5625,13.15625 C 7.8022289,20.855399 11.189172,25.378007 14.65625,28.03125 C 18.250337,30.781689 21.8125,31.5 21.8125,31.5 C 22.153479,31.568346 22.430121,31.817069 22.53422,32.148884 C 22.638319,32.4807 22.553332,32.842875 22.3125,33.09375 C 22.3125,33.09375 12.834342,43.464627 12.34375,55.4375 L 23.625,55.5625 C 23.775583,54.968024 24.284703,52.850143 25.46875,50.125 C 26.139238,48.581838 26.957479,47.047605 27.96875,45.8125 C 28.980021,44.577395 30.249533,43.59375 31.8125,43.59375 C 33.392834,43.59375 34.682884,44.544922 35.6875,45.78125 C 36.692116,47.017578 37.481015,48.583576 38.125,50.125 C 39.262583,52.847886 39.73782,54.93884 39.875,55.53125 L 50.59375,55.5625 C 49.991815,42.90975 37.8125,33.21875 37.8125,33.21875 C 37.516383,32.984647 37.386427,32.597781 37.481159,32.232384 C 37.575892,31.866987 37.877442,31.591993 38.25,31.53125 C 38.25,31.53125 42.11079,30.902899 45.96875,28.21875 C 49.692789,25.627775 53.310428,21.149688 53.5625,13.28125 L 45.40625,11.75 z " />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/msn.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/msn.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/msn.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/msn.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,174 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="48"
-- height="48"
-- id="svg2"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- version="1.0"
-- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48"
-- sodipodi:docname="msn.svg"
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/msn.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs4">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient3816">
-- <stop
-- style="stop-color:#000000;stop-opacity:1;"
-- offset="0"
-- id="stop3818" />
-- <stop
-- style="stop-color:#000000;stop-opacity:0;"
-- offset="1"
-- id="stop3820" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2228">
-- <stop
-- style="stop-color:#f56600;stop-opacity:1;"
-- offset="0"
-- id="stop2230" />
-- <stop
-- style="stop-color:#f56600;stop-opacity:0;"
-- offset="1"
-- id="stop2232" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2219">
-- <stop
-- style="stop-color:#3465a4;stop-opacity:1;"
-- offset="0"
-- id="stop2221" />
-- <stop
-- style="stop-color:#3465a4;stop-opacity:0;"
-- offset="1"
-- id="stop2223" />
-- </linearGradient>
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3816"
-- id="radialGradient1358"
-- gradientUnits="userSpaceOnUse"
-- cx="31.112698"
-- cy="19.008621"
-- fx="31.112698"
-- fy="19.008621"
-- r="8.6620579"
-- gradientTransform="matrix(1.904859,0,0,0.57723,-32.76529,27.09015)" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2219"
-- id="linearGradient1360"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(1.427299,0,0,1.408267,0.332861,3.39912)"
-- x1="10.329217"
-- y1="14.96656"
-- x2="16.580788"
-- y2="20.092552" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2228"
-- id="linearGradient1362"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(1.489007,0,0,1.428565,1.731241,3.002037)"
-- x1="20.998175"
-- y1="11.741063"
-- x2="18.544895"
-- y2="23.366545" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="14.778489"
-- inkscape:cx="32.469518"
-- inkscape:cy="22.977647"
-- inkscape:document-units="px"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- fill="#edd400"
-- showguides="true"
-- inkscape:guide-bbox="true"
-- inkscape:window-width="1268"
-- inkscape:window-height="971"
-- inkscape:window-x="6"
-- inkscape:window-y="21" />
-- <metadata
-- id="metadata7">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer"
-- id="layer1">
-- <path
-- style="opacity:0.4;color:#000000;fill:url(#radialGradient1358);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-- d="M 43.00001,38.062496 C 43.00001,40.822496 35.608012,43.062496 26.500013,43.062496 C 17.392013,43.062496 10.000014,40.822496 10.000014,38.062496 C 10.000014,35.302496 17.392013,33.062496 26.500013,33.062496 C 35.608012,33.062496 43.00001,35.302496 43.00001,38.062496 z "
-- id="path4318" />
-- <path
-- style="fill:#edd400;fill-opacity:1;stroke:#c4a000;stroke-width:1.00000083;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 34.662639,20.335823 C 39.495137,21.781376 40.098879,38.560591 34.609432,38.560591 C 29.18649,38.560591 17.111515,15.085731 34.662639,20.335823 z "
-- id="rect2194" />
-- <path
-- style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.00000024;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 29.5,20.59375 C 28.488762,20.699063 27.850577,20.9863 27.40625,21.40625 C 26.961923,21.8262 26.695785,22.399576 26.5625,23.15625 C 26.295929,24.669599 26.724448,26.888006 27.625,29.09375 C 28.525552,31.299494 29.853318,33.518217 31.21875,35.125 C 32.584182,36.731783 34.047656,37.59375 34.625,37.59375 C 35.065414,37.59375 35.396266,37.452251 35.75,37.125 C 36.103734,36.797749 36.436723,36.267837 36.71875,35.5625 C 37.282805,34.151825 37.566795,32.092358 37.53125,30 C 37.495705,27.907642 37.16426,25.762788 36.5625,24.125 C 35.96074,22.487212 35.097603,21.497403 34.375,21.28125 C 32.261511,20.64904 30.658881,20.473061 29.5,20.59375 z "
-- id="path2259" />
-- <path
-- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 24.98559,40.707419 C 20.31754,40.707419 7.959768,29.343494 17.418553,22.824249 C 26.869109,16.310672 29.725145,40.707419 24.98559,40.707419 z "
-- id="rect2201" />
-- <path
-- style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999911;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 20.429472,22.564494 C 19.813992,22.53919 18.946491,22.754031 17.792299,23.48193 C 15.396153,24.993077 14.598274,26.486625 14.509287,28.117394 C 14.420299,29.74816 15.197952,31.630592 16.500622,33.380577 C 17.803294,35.130559 19.637587,36.743254 21.398232,37.871181 C 23.158877,38.999109 24.734359,39.505165 25.355011,39.505165 C 25.714095,39.505165 25.973542,38.578409 26.134382,37.774606 C 26.456061,36.166999 26.487926,33.806821 26.080561,31.449134 C 25.673198,29.091442 24.821426,26.682961 23.766308,25.027083 C 22.711189,23.371206 21.583796,22.611947 20.429472,22.564494 z "
-- id="path2254" />
-- <path
-- style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 38.290982,9.1309894 C 35.842841,9.5672523 32.283411,12.929344 29.603482,16.28724 C 27.08796,19.439138 25.478582,22.11333 25.259732,22.47474 L 28.572232,30.03724 C 34.665525,29.832673 38.559865,27.128092 38.853482,26.91224 C 39.014293,26.551466 40.549044,23.055678 41.478482,19.03724 C 41.967713,16.922043 42.260097,14.730906 42.072232,12.97474 C 41.884367,11.218574 41.30548,10.015388 40.103482,9.3809894 C 39.532517,9.0796416 38.992058,9.0060564 38.290982,9.1309894 z "
-- id="path2245" />
-- <path
-- style="fill:url(#linearGradient1360);fill-opacity:1;stroke:#204a87;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 2.9244668,13.205506 C 5.4909473,8.9616426 31.868508,26.916697 20.798169,29.292473 C 9.7422309,31.665159 0.38413836,17.406122 2.9244668,13.205506 z "
-- id="rect2197" />
-- <path
-- style="opacity:0.2;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999905;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 4.0077208,17.150417 C 4.6613048,18.933996 5.9435775,21.021975 7.6235197,22.895457 C 10.983405,26.64242 15.833733,29.401717 20.89796,28.310863 C 21.928379,28.088904 22.232928,27.802155 22.334374,27.651594 C 22.435813,27.501039 22.52111,27.289844 22.334374,26.709786 C 21.960899,25.54967 20.384396,23.482994 18.173725,21.529832 C 15.963059,19.576669 13.153701,17.6285 10.545878,16.161517 C 7.9380537,14.694536 5.1976761,13.680027 3.975949,13.563989 C 3.3254548,13.502207 3.3541371,15.366838 4.0077208,17.150417 z "
-- id="path2249" />
-- <path
-- style="fill:url(#linearGradient1362);fill-opacity:1;stroke:#ce5d00;stroke-width:1.00000048;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 23.497613,20.84222 C 23.497613,20.84222 33.747199,3.7130144 39.940221,6.9816102 C 46.183621,10.276795 39.032218,26.044415 39.032218,26.044415 C 39.032218,26.044415 34.34592,29.558038 27.298467,29.558038 L 23.497613,20.84222 z "
-- id="rect1317" />
-- <path
-- style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 37.65625,7.5937494 C 35.207156,8.0301823 31.648755,11.392008 28.96875,14.75 C 26.453156,17.901987 24.843855,20.576081 24.625,20.9375 L 27.9375,28.5 C 34.029365,28.295478 37.922857,25.592475 38.21875,25.375 C 38.379566,25.014217 39.91427,21.518622 40.84375,17.5 C 41.333003,15.384706 41.625396,13.193957 41.4375,11.4375 C 41.249604,9.6810425 40.671312,8.4784456 39.46875,7.8437494 C 38.897466,7.5422332 38.357596,7.4687683 37.65625,7.5937494 z "
-- id="path1328" />
-- <path
-- style="fill:#75507b;fill-opacity:1;stroke:#5c3566;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 25.75715,25.780775 C 27.420525,29.605605 28.313593,33.06003 27.750608,33.491546 C 27.187623,33.923061 25.380722,31.169067 23.717348,27.344236 C 22.053974,23.519407 21.160905,20.064982 21.72389,19.633467 C 22.286875,19.201951 24.093776,21.955945 25.75715,25.780775 z "
-- id="path2192" />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/mxit.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/mxit.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/mxit.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/mxit.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,24 +0,0 @@
--<?xml version="1.0" encoding="utf-8"?>
--<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
--<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
--<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-- width="48px" height="48px" viewBox="0 0 48 48" enable-background="new 0 0 48 48" xml:space="preserve">
--<image overflow="visible" width="34" height="39" xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/7AARRHVja3kAAQAEAAAAHgAA/+4AIUFkb2JlAGTAAAAAAQMA
--EAMCAwYAAAH0AAACSgAAA6n/2wCEABALCwsMCxAMDBAXDw0PFxsUEBAUGx8XFxcXFx8eFxoaGhoX
--Hh4jJSclIx4vLzMzLy9AQEBAQEBAQEBAQEBAQEABEQ8PERMRFRISFRQRFBEUGhQWFhQaJhoaHBoa
--JjAjHh4eHiMwKy4nJycuKzU1MDA1NUBAP0BAQEBAQEBAQEBAQP/CABEIACgAIwMBIgACEQEDEQH/
--xACyAAEAAwEBAAAAAAAAAAAAAAAAAQMFBAIBAAMBAQAAAAAAAAAAAAAAAAABAgMEEAABBAECBgMB
--AAAAAAAAAAABAAIDBAUREyESIhQVRRAjNQYRAAEDAgMDBwgLAAAAAAAAAAERAgMAEiETBDFRIkFh
--cUIUhcWhMlKDs9M01GKSIzNzwyRkhJQVEgABAwAGCQUAAAAAAAAAAAAAARECIUFRYYESEDFxodEy
--QoKicjNDNIT/2gAMAwEAAhEDEQAAANWbtDvwx51+eStam/NlFqUEyBo7eck8dAFoyr//2gAIAQIA
--AQUAe+RpEry7QJ4POA4FDeR3V9q//9oACAEDAAEFAAAUWjRDTTh8dC6V0r//2gAIAQEAAQUAiihn
--hNOsu1rBMr0HLks9hi7UdSE5ytyx5evM/J6dx6rCcInfp3ON2+CZfVY1z46RMm9IHyveZpW+q8Vc
--rtkr51qbF/QEx0s04eCg2//aAAgBAgIGPwBoxWSbRIyisXvNSfZsJrbFYkFblRlP1FOTHK+J8fid
--XuefE//aAAgBAwIGPwCmTDpJzsE9Tkrzs0VlXLuP/9oACAEBAQY/AIZ54GanU6mJk8sksTZnEyNa
--9Be11rW3IAMK+ChH8SP3dY6KH+pH7uvhNORy2wxscOhzGtc01n9rmvzP85bup2zs2b+JZ1q0csgJ
--adHC3hRVMcR5SN1XWSIqLw7fr0GNa8KQ242oC7Aea4moCAFc14cd4FqV3n4lWjP7KL2cNXfT/Kph
--3ZPtDUL0Nrbmk7i61K7z8SrQyNAd+khaQSm2OPmO6s5G3XXWrgllm1KLyjCjbUN2LSXLsFBha0BW
--kkOJ80g7Leau8vEqy9HPEdO0/ZRTxOe6NvoNeyWPhHIow31wt0rvVS/MVjHph6qX5iuKXTQr1mwv
--Lhzi+dwXpFZWdNZk5SX9fMzs/Z95fivkr//Z" transform="matrix(0.9999 0 0 0.9999 7.0146 6.0142)">
--</image>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/novell.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/novell.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/novell.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/novell.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,167 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="48"
-- height="48"
-- id="svg2"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- version="1.0"
-- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/scalable"
-- sodipodi:docname="novell.svg"
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/groupwise.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs4">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2190">
-- <stop
-- style="stop-color:#d3d7cf;stop-opacity:1;"
-- offset="0"
-- id="stop2192" />
-- <stop
-- style="stop-color:#d3d7cf;stop-opacity:0;"
-- offset="1"
-- id="stop2194" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2238">
-- <stop
-- style="stop-color:#eeeeec;stop-opacity:1;"
-- offset="0"
-- id="stop2240" />
-- <stop
-- style="stop-color:#eeeeec;stop-opacity:0;"
-- offset="1"
-- id="stop2242" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient3150">
-- <stop
-- style="stop-color:#2e3436;stop-opacity:1;"
-- offset="0"
-- id="stop3152" />
-- <stop
-- style="stop-color:#2e3436;stop-opacity:0;"
-- offset="1"
-- id="stop3154" />
-- </linearGradient>
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3150"
-- id="radialGradient3156"
-- cx="10.748654"
-- cy="10.457643"
-- fx="10.748654"
-- fy="10.457643"
-- r="6.6449099"
-- gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2238"
-- id="linearGradient2244"
-- x1="11.76915"
-- y1="3.4633243"
-- x2="11.76915"
-- y2="11.990735"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(1.888889,0,0,1.818182,2.77778,1.26862)" />
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2190"
-- id="radialGradient2196"
-- cx="4.3022962"
-- cy="7.5011024"
-- fx="4.3022962"
-- fy="7.5011024"
-- r="8.5"
-- gradientTransform="matrix(-2.567716,2.567716,-2.581797,-2.581795,54.64024,19.71367)"
-- gradientUnits="userSpaceOnUse" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="12.865422"
-- inkscape:cx="44.509337"
-- inkscape:cy="25.527163"
-- inkscape:document-units="px"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- fill="#00ffff"
-- inkscape:window-width="1268"
-- inkscape:window-height="971"
-- inkscape:window-x="6"
-- inkscape:window-y="21" />
-- <metadata
-- id="metadata7">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer"
-- id="layer1">
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.5;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path3140"
-- sodipodi:cx="10.748654"
-- sodipodi:cy="10.457643"
-- sodipodi:rx="6.6449099"
-- sodipodi:ry="2.3675451"
-- d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z"
-- transform="matrix(2.934577,0,0,2.111893,-7.042754,16.91046)" />
-- <rect
-- style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:#888a85;stroke-width:0.9999997;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="rect1326"
-- width="33.012436"
-- height="35.008015"
-- x="7.4937739"
-- y="5.4919853"
-- ry="4.0986137"
-- rx="4.0986137" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.99578816"
-- inkscape:original="M 11.59375 5.5 C 9.323118 5.5 7.5 7.323118 7.5 9.59375 L 7.5 36.40625 C 7.5 38.676882 9.3231175 40.5 11.59375 40.5 L 36.40625 40.5 C 38.676882 40.5 40.5 38.676882 40.5 36.40625 L 40.5 9.59375 C 40.5 7.323118 38.676882 5.5 36.40625 5.5 L 11.59375 5.5 z "
-- xlink:href="#rect1326"
-- style="opacity:1;fill:url(#radialGradient2196);fill-opacity:1;stroke:#ffffff;stroke-width:1.00000048;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2201"
-- inkscape:href="#rect1326"
-- d="M 9.5,5.5 C 8.9264847,5.5 8.5,5.9264831 8.5,6.5 L 8.5,37.5 C 8.5,38.073517 8.9264835,38.499999 9.5,38.5 L 38.5,38.5 C 39.073514,38.5 39.5,38.073514 39.5,37.5 L 39.5,6.5 C 39.5,5.9264836 39.073514,5.5 38.5,5.5 L 9.5,5.5 z " />
-- <path
-- style="fill:#cc0000;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 16,13.995893 L 16,32.182309 L 19.840233,32.182309 L 19.746482,21.644702 L 29.000001,30.275655 L 33,33.995893 L 33,15.840234 L 29.223673,15.840234 L 29.223673,26.287561 L 18.124999,15.900655 L 16,13.995893 z "
-- id="rect1317"
-- sodipodi:nodetypes="ccccccccccc" />
-- <path
-- style="fill:url(#linearGradient2244);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-- d="M 16,13.995893 L 16,32.182309 L 19.840234,32.182309 L 19.746482,21.644702 L 29.000001,30.275655 L 33,33.995893 L 33,15.840234 L 29.223673,15.840234 L 29.223673,26.287561 L 18.124999,15.900655 L 16,13.995893 z "
-- id="path2228"
-- sodipodi:nodetypes="ccccccccccc" />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/yahoo.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/yahoo.svg
---- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/yahoo.svg 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/yahoo.svg 1969-12-31 21:00:00.000000000 -0300
-@@ -1,174 +0,0 @@
--<?xml version="1.0" encoding="UTF-8" standalone="no"?>
--<!-- Created with Inkscape (http://www.inkscape.org/) -->
--<svg
-- xmlns:dc="http://purl.org/dc/elements/1.1/"
-- xmlns:cc="http://creativecommons.org/ns#"
-- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:svg="http://www.w3.org/2000/svg"
-- xmlns="http://www.w3.org/2000/svg"
-- xmlns:xlink="http://www.w3.org/1999/xlink"
-- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-- width="48"
-- height="48"
-- id="svg1307"
-- sodipodi:version="0.32"
-- inkscape:version="0.46"
-- version="1.0"
-- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48"
-- sodipodi:docname="yahoo.svg"
-- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/yahoo.png"
-- inkscape:export-xdpi="90"
-- inkscape:export-ydpi="90"
-- inkscape:output_extension="org.inkscape.output.svg.inkscape">
-- <defs
-- id="defs1309">
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient2211">
-- <stop
-- style="stop-color:#ffffff;stop-opacity:1;"
-- offset="0"
-- id="stop2213" />
-- <stop
-- style="stop-color:#ffffff;stop-opacity:0;"
-- offset="1"
-- id="stop2215" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient3150">
-- <stop
-- style="stop-color:#2e3436;stop-opacity:1;"
-- offset="0"
-- id="stop3152" />
-- <stop
-- style="stop-color:#2e3436;stop-opacity:0;"
-- offset="1"
-- id="stop3154" />
-- </linearGradient>
-- <radialGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient3150"
-- id="radialGradient3156"
-- cx="10.748654"
-- cy="10.457643"
-- fx="10.748654"
-- fy="10.457643"
-- r="6.6449099"
-- gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
-- gradientUnits="userSpaceOnUse" />
-- <linearGradient
-- inkscape:collect="always"
-- id="linearGradient4123">
-- <stop
-- style="stop-color:#ff0000;stop-opacity:1;"
-- offset="0"
-- id="stop4125" />
-- <stop
-- style="stop-color:#ff0000;stop-opacity:0;"
-- offset="1"
-- id="stop4127" />
-- </linearGradient>
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient4123"
-- id="linearGradient2206"
-- gradientUnits="userSpaceOnUse"
-- gradientTransform="matrix(1.871443,0,0,1.871443,1.990827,1.339082)"
-- x1="9.7634506"
-- y1="11.499014"
-- x2="9.7634506"
-- y2="0.12942761" />
-- <linearGradient
-- inkscape:collect="always"
-- xlink:href="#linearGradient2211"
-- id="linearGradient2217"
-- x1="36.249207"
-- y1="7.6495404"
-- x2="36.249207"
-- y2="23.063982"
-- gradientUnits="userSpaceOnUse" />
-- </defs>
-- <sodipodi:namedview
-- id="base"
-- pagecolor="#ffffff"
-- bordercolor="#666666"
-- borderopacity="1.0"
-- inkscape:pageopacity="0.0"
-- inkscape:pageshadow="2"
-- inkscape:zoom="11.098901"
-- inkscape:cx="49.54817"
-- inkscape:cy="29.700698"
-- inkscape:current-layer="layer1"
-- showgrid="true"
-- inkscape:grid-bbox="true"
-- inkscape:document-units="px"
-- fill="#a40000"
-- showguides="true"
-- inkscape:guide-bbox="true"
-- inkscape:window-width="1268"
-- inkscape:window-height="971"
-- inkscape:window-x="6"
-- inkscape:window-y="21" />
-- <metadata
-- id="metadata1312">
-- <rdf:RDF>
-- <cc:Work
-- rdf:about="">
-- <dc:format>image/svg+xml</dc:format>
-- <dc:type
-- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-- </cc:Work>
-- </rdf:RDF>
-- </metadata>
-- <g
-- id="layer1"
-- inkscape:label="Layer 1"
-- inkscape:groupmode="layer">
-- <rect
-- style="opacity:0;fill:none;fill-opacity:1;stroke:#a40000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="rect3203"
-- width="0"
-- height="2.5118096"
-- x="6"
-- y="6.4881902" />
-- <path
-- sodipodi:type="arc"
-- style="opacity:0.6;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path3140"
-- sodipodi:cx="10.748654"
-- sodipodi:cy="10.457643"
-- sodipodi:rx="6.6449099"
-- sodipodi:ry="2.3675451"
-- d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z"
-- transform="matrix(3.163562,0,0,2.111892,-10.02562,12.91459)" />
-- <path
-- style="opacity:1;fill:#ff0000;fill-opacity:1;stroke:#a40000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- d="M 36.593752,13.5 L 36.750002,24.71875 L 44.125002,13.5 L 36.593752,13.5 z M 33.406252,30.34375 C 32.052922,30.519922 31.000003,31.724054 31.000002,33.15625 C 31.000002,34.70982 32.231505,35.96875 33.750002,35.96875 C 35.268499,35.96875 36.500002,34.70982 36.500002,33.15625 C 36.500002,31.60268 35.268499,30.343751 33.750002,30.34375 C 33.631369,30.34375 33.520941,30.32882 33.406252,30.34375 z "
-- id="path4110" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-1.0402364"
-- inkscape:original="M 36.59375 13.5 L 36.75 24.71875 L 44.125 13.5 L 36.59375 13.5 z M 33.40625 30.34375 C 32.052918 30.519922 31.000001 31.724054 31 33.15625 C 31 34.70982 32.231503 35.96875 33.75 35.96875 C 35.268495 35.96875 36.5 34.70982 36.5 33.15625 C 36.499998 31.60268 35.268497 30.343751 33.75 30.34375 C 33.631365 30.34375 33.520939 30.32882 33.40625 30.34375 z "
-- xlink:href="#path4110"
-- style="opacity:0.35;fill:url(#linearGradient2217);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2209"
-- inkscape:href="#path4110"
-- d="M 37.625,15.0625 L 37.71875,21.875 L 42.1875,15.0625 L 37.625,15.0625 z M 33.53125,31.90625 C 32.711111,32.013013 32.031251,32.765143 32.03125,33.6875 C 32.031249,34.691344 32.806451,35.46875 33.75,35.46875 C 34.693551,35.46875 35.46875,34.691346 35.46875,33.6875 C 35.468751,32.683656 34.69355,31.906251 33.75,31.90625 C 33.544091,31.90625 33.473148,31.913814 33.53125,31.90625 z " />
-- <path
-- style="opacity:1;fill:url(#linearGradient2206);fill-opacity:1;stroke:#a40000;stroke-width:0.99999976;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- d="M 2.6545432,11.532816 L 4.353345,15.445312 L 7.741467,15.555398 L 17.47685,25.310159 L 17.4318,31.506326 L 12.428056,31.384739 L 11.665952,34.499424 L 27.339128,34.54589 L 26.551973,31.519888 L 21.572919,31.603085 L 21.572919,25.191498 L 28.209096,17.523843 L 31.468823,17.433744 L 32.573193,13.532585 L 23.168883,13.473142 L 21.694773,17.410562 L 23.776066,17.4644 L 19.977012,20.889333 L 13.198929,15.445312 L 17.758833,15.445312 L 20.124034,11.577865 L 2.6545432,11.532816 z "
-- id="rect3219"
-- sodipodi:nodetypes="cccccccccccccccccccccc" />
-- <path
-- sodipodi:type="inkscape:offset"
-- inkscape:radius="-0.98856229"
-- inkscape:original="M 2.65625 11.53125 L 4.34375 15.4375 L 7.75 15.5625 L 17.46875 25.3125 L 17.4375 31.5 L 12.4375 31.375 L 11.65625 34.5 L 27.34375 34.53125 L 26.5625 31.53125 L 21.5625 31.59375 L 21.5625 25.1875 L 28.21875 17.53125 L 31.46875 17.4375 L 32.5625 13.53125 L 23.15625 13.46875 L 21.6875 17.40625 L 23.78125 17.46875 L 19.96875 20.875 L 13.1875 15.4375 L 17.75 15.4375 L 20.125 11.5625 L 2.65625 11.53125 z "
-- xlink:href="#rect3219"
-- style="opacity:0.35;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999976;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-- id="path2204"
-- inkscape:href="#rect3219"
-- d="M 4.15625,13.0625 L 5,15 L 7.78125,15.09375 C 8.0317447,15.110809 8.266366,15.222533 8.4375,15.40625 L 18.15625,25.15625 C 18.347286,25.335037 18.45966,25.58226 18.46875,25.84375 L 18.4375,32.03125 C 18.44087,32.30297 18.33225,32.564099 18.137167,32.75327 C 17.942084,32.942442 17.677738,33.042977 17.40625,33.03125 L 13.21875,32.9375 L 12.9375,34.03125 L 26.0625,34.0625 L 25.78125,33.0625 L 21.5625,33.125 C 21.296354,33.12807 21.040212,33.0237 20.852006,32.835494 C 20.6638,32.647288 20.55943,32.391146 20.5625,32.125 L 20.5625,25.71875 C 20.562717,25.476777 20.651667,25.243286 20.8125,25.0625 L 27.46875,17.40625 C 27.649517,17.19593 27.910308,17.071204 28.1875,17.0625 L 30.71875,17 L 31.28125,15.0625 L 23.84375,15 L 23.125,16.96875 L 23.8125,17 C 24.228223,17.002399 24.598033,17.264612 24.737859,17.656122 C 24.877684,18.047632 24.757648,18.48479 24.4375,18.75 L 20.625,22.15625 C 20.263408,22.479557 19.720674,22.492795 19.34375,22.1875 L 12.5625,16.75 C 12.215365,16.491727 12.076498,16.037735 12.219751,15.629463 C 12.363005,15.221191 12.755094,14.953499 13.1875,14.96875 L 17.1875,14.96875 L 18.34375,13.09375 L 4.15625,13.0625 z " />
-- </g>
--</svg>
-diff -Nur pidgin-2.10.7/pidgin/plugins/cap/Makefile.in pidgin-2.10.7-nonprism/pidgin/plugins/cap/Makefile.in
---- pidgin-2.10.7/pidgin/plugins/cap/Makefile.in 2013-02-11 07:17:24.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/cap/Makefile.in 2013-08-16 23:57:24.360620508 -0300
-@@ -185,8 +185,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -248,8 +246,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/pidgin/plugins/cap/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/plugins/cap/Makefile.mingw
---- pidgin-2.10.7/pidgin/plugins/cap/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/cap/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,82 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for cap plugin.
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = cap
--
--# This is where sqlite3.[ch] from the sqlite "amalgamation" archive were extracted to
--# This is available from http://www.sqlite.org/download.html
--SQLITE_TOP ?= $(WIN32_DEV_TOP)/sqlite-3.4.1
--
--##
--## INCLUDE PATHS
--##
--INCLUDE_PATHS += -I. \
-- -I$(SQLITE_TOP) \
-- -I$(GTK_TOP)/include \
-- -I$(GTK_TOP)/include/gtk-2.0 \
-- -I$(GTK_TOP)/include/glib-2.0 \
-- -I$(GTK_TOP)/include/pango-1.0 \
-- -I$(GTK_TOP)/include/atk-1.0 \
-- -I$(GTK_TOP)/include/cairo \
-- -I$(GTK_TOP)/lib/glib-2.0/include \
-- -I$(GTK_TOP)/lib/gtk-2.0/include \
-- -I$(PURPLE_TOP) \
-- -I$(PURPLE_TOP)/win32 \
-- -I$(PIDGIN_TOP) \
-- -I$(PIDGIN_TOP)/win32 \
-- -I$(PIDGIN_TREE_TOP)
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP) \
-- -L$(PIDGIN_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = cap.c \
-- $(SQLITE_TOP)/sqlite3.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = -lgtk-win32-2.0 \
-- -lglib-2.0 \
-- -lgdk-win32-2.0 \
-- -lgobject-2.0 \
-- -lintl \
-- -lpurple \
-- -lpidgin
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll
--
--install: $(PIDGIN_INSTALL_PLUGINS_DIR) all
-- cp $(TARGET).dll $(PIDGIN_INSTALL_PLUGINS_DIR)
--
--$(OBJECTS): $(PIDGIN_CONFIG_H)
--
--$(TARGET).dll: $(PURPLE_DLL).a $(PIDGIN_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -rf $(OBJECTS)
-- rm -rf $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/pidgin/plugins/disco/Makefile.in pidgin-2.10.7-nonprism/pidgin/plugins/disco/Makefile.in
---- pidgin-2.10.7/pidgin/plugins/disco/Makefile.in 2013-02-11 07:17:24.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/disco/Makefile.in 2013-08-16 23:57:28.064067349 -0300
-@@ -186,8 +186,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -249,8 +247,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/pidgin/plugins/disco/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/plugins/disco/Makefile.mingw
---- pidgin-2.10.7/pidgin/plugins/disco/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/disco/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,79 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for xmppdisco plugin.
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = xmppdisco
--
--##
--## INCLUDE PATHS
--##
--INCLUDE_PATHS += -I. \
-- -I$(GTK_TOP)/include \
-- -I$(GTK_TOP)/include/gtk-2.0 \
-- -I$(GTK_TOP)/include/glib-2.0 \
-- -I$(GTK_TOP)/include/pango-1.0 \
-- -I$(GTK_TOP)/include/atk-1.0 \
-- -I$(GTK_TOP)/include/cairo \
-- -I$(GTK_TOP)/lib/glib-2.0/include \
-- -I$(GTK_TOP)/lib/gtk-2.0/include \
-- -I$(PURPLE_TOP) \
-- -I$(PURPLE_TOP)/win32 \
-- -I$(PIDGIN_TOP) \
-- -I$(PIDGIN_TOP)/win32 \
-- -I$(PIDGIN_TREE_TOP)
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP) \
-- -L$(PIDGIN_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = xmppdisco.c \
-- gtkdisco.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = -lgtk-win32-2.0 \
-- -lglib-2.0 \
-- -lgdk-win32-2.0 \
-- -lgobject-2.0 \
-- -lpango-1.0 \
-- -lgdk_pixbuf-2.0 \
-- -lintl \
-- -lpurple \
-- -lpidgin
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll
--
--install: $(PIDGIN_INSTALL_PLUGINS_DIR) all
-- cp $(TARGET).dll $(PIDGIN_INSTALL_PLUGINS_DIR)
--
--$(OBJECTS): $(PIDGIN_CONFIG_H)
--
--$(TARGET).dll: $(PURPLE_DLL).a $(PIDGIN_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -rf $(OBJECTS)
-- rm -rf $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
diff -Nur pidgin-2.10.7/pidgin/plugins/disco/xmppdisco.c pidgin-2.10.7-nonprism/pidgin/plugins/disco/xmppdisco.c
--- pidgin-2.10.7/pidgin/plugins/disco/xmppdisco.c 2013-02-11 07:16:54.000000000 -0200
+++ pidgin-2.10.7-nonprism/pidgin/plugins/disco/xmppdisco.c 2013-08-16 23:39:46.921427463 -0300
@@ -162747,37 +4387,6 @@ diff -Nur pidgin-2.10.7/pidgin/plugins/disco/xmppdisco.c pidgin-2.10.7-nonprism/
{ "xmpp", "jabber" }, /* prpl-jabber (mentioned in case the prpl is renamed so this line will match) */
{ NULL, NULL }
};
-@@ -388,8 +385,7 @@
-
- if (item_data->parent->type == XMPP_DISCO_SERVICE_TYPE_CHAT) {
- /* This is a hacky first-order approximation. Any MUC
-- * component that has a >1 level hierarchy (a Yahoo MUC
-- * transport component probably does) will violate this.
-+ * component that has a >1 level hierarchy will violate this.
- *
- * On the other hand, this is better than querying all the
- * chats at conference.jabber.org to enumerate them.
-diff -Nur pidgin-2.10.7/pidgin/plugins/gestures/Makefile.in pidgin-2.10.7-nonprism/pidgin/plugins/gestures/Makefile.in
---- pidgin-2.10.7/pidgin/plugins/gestures/Makefile.in 2013-02-11 07:17:24.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/gestures/Makefile.in 2013-08-16 23:57:32.194193933 -0300
-@@ -187,8 +187,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -250,8 +248,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
diff -Nur pidgin-2.10.7/pidgin/plugins/gevolution/add_buddy_dialog.c pidgin-2.10.7-nonprism/pidgin/plugins/gevolution/add_buddy_dialog.c
--- pidgin-2.10.7/pidgin/plugins/gevolution/add_buddy_dialog.c 2013-02-11 07:16:54.000000000 -0200
+++ pidgin-2.10.7-nonprism/pidgin/plugins/gevolution/add_buddy_dialog.c 2013-08-16 21:26:56.293625899 -0300
@@ -162924,27 +4533,6 @@ diff -Nur pidgin-2.10.7/pidgin/plugins/gevolution/gevo-util.c pidgin-2.10.7-nonp
}
return mail;
-diff -Nur pidgin-2.10.7/pidgin/plugins/gevolution/Makefile.in pidgin-2.10.7-nonprism/pidgin/plugins/gevolution/Makefile.in
---- pidgin-2.10.7/pidgin/plugins/gevolution/Makefile.in 2013-02-11 07:17:24.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/gevolution/Makefile.in 2013-08-16 23:57:35.817638327 -0300
-@@ -190,8 +190,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -253,8 +251,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
diff -Nur pidgin-2.10.7/pidgin/plugins/gevolution/new_person_dialog.c pidgin-2.10.7-nonprism/pidgin/plugins/gevolution/new_person_dialog.c
--- pidgin-2.10.7/pidgin/plugins/gevolution/new_person_dialog.c 2013-02-11 07:16:54.000000000 -0200
+++ pidgin-2.10.7-nonprism/pidgin/plugins/gevolution/new_person_dialog.c 2013-08-16 21:23:26.207116339 -0300
@@ -162970,8004 +4558,6 @@ diff -Nur pidgin-2.10.7/pidgin/plugins/gevolution/new_person_dialog.c pidgin-2.1
if (field > 0)
{
-diff -Nur pidgin-2.10.7/pidgin/plugins/Makefile.in pidgin-2.10.7-nonprism/pidgin/plugins/Makefile.in
---- pidgin-2.10.7/pidgin/plugins/Makefile.in 2013-02-11 07:17:24.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/Makefile.in 2013-08-16 23:57:14.680323828 -0300
-@@ -393,8 +393,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -456,8 +454,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/pidgin/plugins/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/plugins/Makefile.mingw
---- pidgin-2.10.7/pidgin/plugins/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,118 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of Pidgin Plugins
--#
--
--PIDGIN_TREE_TOP := ../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--DISCO_PLUGIN := ./disco
--GTKPERL_PLUGIN := ./perl
--TICKER_PLUGIN := ./ticker
--TRANSPARENCY_PLUGIN := ./win32/transparency
--WINPREFS_PLUGIN := ./win32/winprefs
--
--.SUFFIXES:
--.SUFFIXES: .c .dll
--
--##
--## INCLUDE PATHS
--##
--INCLUDE_PATHS += \
-- -I$(GTK_TOP)/include \
-- -I$(GTK_TOP)/include/gtk-2.0 \
-- -I$(GTK_TOP)/include/glib-2.0 \
-- -I$(GTK_TOP)/include/pango-1.0 \
-- -I$(GTK_TOP)/include/atk-1.0 \
-- -I$(GTK_TOP)/include/cairo \
-- -I$(GTK_TOP)/lib/glib-2.0/include \
-- -I$(GTK_TOP)/lib/gtk-2.0/include \
-- -I$(PIDGIN_TREE_TOP) \
-- -I$(PURPLE_TOP) \
-- -I$(PURPLE_TOP)/win32 \
-- -I$(PIDGIN_TOP) \
-- -I$(PIDGIN_TOP)/win32
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP) \
-- -L$(PIDGIN_TOP)
--
--##
--## LIBRARIES
--##
--LIBS = -lgtk-win32-2.0 \
-- -lglib-2.0 \
-- -lgdk-win32-2.0 \
-- -lgobject-2.0 \
-- -lgmodule-2.0 \
-- -lgdk_pixbuf-2.0 \
-- -lpango-1.0 \
-- -lcairo \
-- -lintl \
-- -lws2_32 \
-- -lpurple \
-- -lpidgin
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all clean plugins install
--
--all: plugins
-- $(MAKE) -C $(DISCO_PLUGIN) -f $(MINGW_MAKEFILE)
-- $(MAKE) -C $(GTKPERL_PLUGIN) -f $(MINGW_MAKEFILE)
-- $(MAKE) -C $(TICKER_PLUGIN) -f $(MINGW_MAKEFILE)
-- $(MAKE) -C $(TRANSPARENCY_PLUGIN) -f $(MINGW_MAKEFILE)
-- $(MAKE) -C $(WINPREFS_PLUGIN) -f $(MINGW_MAKEFILE)
--
--install: all $(PIDGIN_INSTALL_PLUGINS_DIR)
-- $(MAKE) -C $(DISCO_PLUGIN) -f $(MINGW_MAKEFILE) install
-- $(MAKE) -C $(GTKPERL_PLUGIN) -f $(MINGW_MAKEFILE) install
-- $(MAKE) -C $(TICKER_PLUGIN) -f $(MINGW_MAKEFILE) install
-- $(MAKE) -C $(TRANSPARENCY_PLUGIN) -f $(MINGW_MAKEFILE) install
-- $(MAKE) -C $(WINPREFS_PLUGIN) -f $(MINGW_MAKEFILE) install
-- cp *.dll $(PIDGIN_INSTALL_PLUGINS_DIR)
--
--THEMEEDIT_SRC = themeedit.c themeedit-icon.c
--THEMEEDIT_OBJECTS = $(THEMEEDIT_SRC:%.c=%.o)
--
--themeedit.dll: $(THEMEEDIT_OBJECTS)
-- $(CC) -shared $(THEMEEDIT_OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $@
--
--%.dll: %.c $(PURPLE_CONFIG_H) $(PURPLE_VERSION_H)
-- $(CC) $(CFLAGS) $(DEFINES) $(INCLUDE_PATHS) -o $@.o -c $<
-- $(CC) -shared $@.o $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $@
--
--
--include $(PIDGIN_COMMON_RULES)
--
--plugins: \
-- convcolors.dll \
-- extplacement.dll \
-- gtkbuddynote.dll \
-- history.dll \
-- iconaway.dll \
-- markerline.dll \
-- notify.dll \
-- pidginrc.dll \
-- relnot.dll \
-- sendbutton.dll \
-- spellchk.dll \
-- themeedit.dll \
-- timestamp_format.dll \
-- timestamp.dll \
-- xmppconsole.dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -f *.o *.dll
-- $(MAKE) -C $(DISCO_PLUGIN) -f $(MINGW_MAKEFILE) clean
-- $(MAKE) -C $(GTKPERL_PLUGIN) -f $(MINGW_MAKEFILE) clean
-- $(MAKE) -C $(TICKER_PLUGIN) -f $(MINGW_MAKEFILE) clean
-- $(MAKE) -C $(TRANSPARENCY_PLUGIN) -f $(MINGW_MAKEFILE) clean
-- $(MAKE) -C $(WINPREFS_PLUGIN) -f $(MINGW_MAKEFILE) clean
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/pidgin/plugins/musicmessaging/Makefile.in pidgin-2.10.7-nonprism/pidgin/plugins/musicmessaging/Makefile.in
---- pidgin-2.10.7/pidgin/plugins/musicmessaging/Makefile.in 2013-02-11 07:17:24.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/musicmessaging/Makefile.in 2013-08-16 23:57:39.504417995 -0300
-@@ -193,8 +193,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -256,8 +254,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/pidgin/plugins/perl/common/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/plugins/perl/common/Makefile.mingw
---- pidgin-2.10.7/pidgin/plugins/perl/common/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/perl/common/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,113 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for Pidgin perl module.
--#
--
--PIDGIN_TREE_TOP := ../../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--GCCWARNINGS += -Wno-comment -Wno-unused -Wno-nested-externs
--
--DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES))
--
--TARGET = Pidgin
--
--##
--## INCLUDE PATHS
--##
--INCLUDE_PATHS = -I. \
-- -I$(PIDGIN_TREE_TOP) \
-- -I$(PURPLE_TOP) \
-- -I$(PURPLE_TOP)/win32 \
-- -I$(PIDGIN_TOP) \
-- -I$(PIDGIN_TOP)/win32 \
-- -I$(GTK_TOP)/include \
-- -I$(GTK_TOP)/include/atk-1.0 \
-- -I$(GTK_TOP)/include/cairo \
-- -I$(GTK_TOP)/include/glib-2.0 \
-- -I$(GTK_TOP)/include/gtk-2.0 \
-- -I$(GTK_TOP)/include/pango-1.0 \
-- -I$(GTK_TOP)/lib/glib-2.0/include \
-- -I$(GTK_TOP)/lib/gtk-2.0/include \
-- -I$(PERL_LIB_TOP)/CORE
--
--LIB_PATHS += -L$(PERL_LIB_TOP) \
-- -L$(PURPLE_TOP) \
-- -L$(PIDGIN_TOP) \
-- -L$(PURPLE_PERL_TOP) \
-- -L$(GTK_TOP)/lib
--
--##
--## SOURCES, OBJECTS
--##
--XS_FILES = \
-- Pidgin.xs \
-- GtkAccount.xs \
-- GtkBlist.xs \
-- GtkConn.xs \
-- GtkConv.xs \
-- GtkConvWin.xs \
-- GtkDebug.xs \
-- GtkDialogs.xs \
-- GtkFt.xs \
-- GtkIMHtml.xs \
-- GtkIMHtmlToolbar.xs \
-- GtkLog.xs \
-- GtkMenuTray.xs \
-- GtkPlugin.xs \
-- GtkPluginPref.xs \
-- GtkPounce.xs \
-- GtkPrefs.xs \
-- GtkPrivacy.xs \
-- GtkRoomlist.xs \
-- GtkSavedStatuses.xs \
-- GtkSound.xs \
-- GtkStatusBox.xs \
-- GtkThemes.xs \
-- GtkUtils.xs
--
--
--C_FILES = $(XS_FILES:%.xs=%.c)
--OBJECTS = $(C_FILES:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = -lperl510 \
-- -lperl \
-- -lpurple \
-- -lpidgin \
-- -lglib-2.0
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGETS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll
--
--$(PURPLE_INSTALL_PERL_DIR)/Purple.pm:
-- $(MAKE) -C $(PURPLE_PERL_TOP)/common -f $(MINGW_MAKEFILE) install
--
--install: all $(PURPLE_INSTALL_PERL_DIR)/Purple.pm
-- rm -f $(PIDGIN_INSTALL_PERL_DIR)/$(TARGET).dll $(PIDGIN_INSTALL_PERL_DIR)/auto/Pidgin/$(TARGET).pm
-- mkdir -p $(PIDGIN_INSTALL_PERL_DIR)
-- cp $(TARGET).pm $(PIDGIN_INSTALL_PERL_DIR)
-- mkdir -p $(PIDGIN_INSTALL_PERL_DIR)/auto/Pidgin
-- cp $(TARGET).dll $(PIDGIN_INSTALL_PERL_DIR)/auto/Pidgin
--
--$(C_FILES): $(PIDGIN_CONFIG_H)
--
--$(TARGET).dll: $(PIDGIN_DLL).a $(PURPLE_PERL_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(DLL_LD_FLAGS) $(LIBS) -o $(TARGET).dll
--
--##
--## CLEAN
--##
--clean:
-- rm -f *.o $(C_FILES) $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/pidgin/plugins/perl/Makefile.in pidgin-2.10.7-nonprism/pidgin/plugins/perl/Makefile.in
---- pidgin-2.10.7/pidgin/plugins/perl/Makefile.in 2013-02-11 07:17:24.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/perl/Makefile.in 2013-08-16 23:57:43.767882012 -0300
-@@ -121,8 +121,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -184,8 +182,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/pidgin/plugins/perl/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/plugins/perl/Makefile.mingw
---- pidgin-2.10.7/pidgin/plugins/perl/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/perl/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,25 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for perl plugin loader plugin.
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all:
-- $(MAKE) -C ./common -f $(MINGW_MAKEFILE)
--
--install: all $(PIDGIN_INSTALL_PLUGINS_DIR)
-- $(MAKE) -C ./common -f $(MINGW_MAKEFILE) install
--
--##
--## CLEAN RULES
--##
--clean:
-- $(MAKE) -C ./common -f $(MINGW_MAKEFILE) clean
-diff -Nur pidgin-2.10.7/pidgin/plugins/ticker/Makefile.in pidgin-2.10.7-nonprism/pidgin/plugins/ticker/Makefile.in
---- pidgin-2.10.7/pidgin/plugins/ticker/Makefile.in 2013-02-11 07:17:24.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/ticker/Makefile.in 2013-08-16 23:56:58.146483798 -0300
-@@ -185,8 +185,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -248,8 +246,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/pidgin/plugins/ticker/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/plugins/ticker/Makefile.mingw
---- pidgin-2.10.7/pidgin/plugins/ticker/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/ticker/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,77 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for ticker plugin.
--#
--
--PIDGIN_TREE_TOP := ../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = ticker
--
--##
--## INCLUDE PATHS
--##
--INCLUDE_PATHS += -I. \
-- -I$(GTK_TOP)/include \
-- -I$(GTK_TOP)/include/gtk-2.0 \
-- -I$(GTK_TOP)/include/glib-2.0 \
-- -I$(GTK_TOP)/include/pango-1.0 \
-- -I$(GTK_TOP)/include/atk-1.0 \
-- -I$(GTK_TOP)/include/cairo \
-- -I$(GTK_TOP)/lib/glib-2.0/include \
-- -I$(GTK_TOP)/lib/gtk-2.0/include \
-- -I$(PURPLE_TOP) \
-- -I$(PURPLE_TOP)/win32 \
-- -I$(PIDGIN_TOP) \
-- -I$(PIDGIN_TOP)/win32 \
-- -I$(PIDGIN_TREE_TOP)
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP) \
-- -L$(PIDGIN_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = ticker.c \
-- gtkticker.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = -lgtk-win32-2.0 \
-- -lglib-2.0 \
-- -lgdk-win32-2.0 \
-- -lgobject-2.0 \
-- -lintl \
-- -lpurple \
-- -lpidgin
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll
--
--install: $(PIDGIN_INSTALL_PLUGINS_DIR) all
-- cp $(TARGET).dll $(PIDGIN_INSTALL_PLUGINS_DIR)
--
--$(OBJECTS): $(PIDGIN_CONFIG_H)
--
--$(TARGET).dll: $(PURPLE_DLL).a $(PIDGIN_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -rf $(OBJECTS)
-- rm -rf $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/pidgin/plugins/win32/transparency/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/plugins/win32/transparency/Makefile.mingw
---- pidgin-2.10.7/pidgin/plugins/win32/transparency/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/win32/transparency/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,76 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32trans plugin.
--#
--
--PIDGIN_TREE_TOP := ../../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = win2ktrans
--DEFINES += -D_WIN32_WINNT=0x0500
--
--##
--## INCLUDE PATHS
--##
--INCLUDE_PATHS += -I. \
-- -I$(GTK_TOP)/include \
-- -I$(GTK_TOP)/include/gtk-2.0 \
-- -I$(GTK_TOP)/include/glib-2.0 \
-- -I$(GTK_TOP)/include/pango-1.0 \
-- -I$(GTK_TOP)/include/atk-1.0 \
-- -I$(GTK_TOP)/include/cairo \
-- -I$(GTK_TOP)/lib/glib-2.0/include \
-- -I$(GTK_TOP)/lib/gtk-2.0/include \
-- -I$(PURPLE_TOP) \
-- -I$(PURPLE_TOP)/win32 \
-- -I$(PIDGIN_TOP) \
-- -I$(PIDGIN_TOP)/win32 \
-- -I$(PIDGIN_TREE_TOP)
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP) \
-- -L$(PIDGIN_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = win2ktrans.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = -lgtk-win32-2.0 \
-- -lglib-2.0 \
-- -lgdk-win32-2.0 \
-- -lgmodule-2.0 \
-- -lgobject-2.0 \
-- -lintl \
-- -lpidgin \
-- -lpurple
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll
--
--install: all $(PIDGIN_INSTALL_PLUGINS_DIR)
-- cp $(TARGET).dll $(PIDGIN_INSTALL_PLUGINS_DIR)
--
--$(TARGET).dll: $(PURPLE_DLL).a $(PIDGIN_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -rf $(OBJECTS)
-- rm -rf $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/pidgin/plugins/win32/transparency/win2ktrans.c pidgin-2.10.7-nonprism/pidgin/plugins/win32/transparency/win2ktrans.c
---- pidgin-2.10.7/pidgin/plugins/win32/transparency/win2ktrans.c 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/win32/transparency/win2ktrans.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,723 +0,0 @@
--/*
-- * Pidgin - Transparency plugin
-- *
-- * Copyright (C) 1998-2002, Rob Flynn <rob@marko.net>
-- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
-- * Copyright (C) 2005, Daniel Atallah <daniel_atallah@yahoo.com>
-- *
-- * This program is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU General Public License as
-- * published by the Free Software Foundation; either version 2 of the
-- * License, or (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful, but
-- * WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- * General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-- * 02111-1301, USA.
-- *
-- */
--#ifndef _WIN32_WINNT
--#define _WIN32_WINNT 0x0500
--#endif
--#include <gdk/gdkwin32.h>
--#include "internal.h"
--
--#include "core.h"
--#include "prefs.h"
--#include "debug.h"
--
--#include "gtkconv.h"
--#include "gtkplugin.h"
--#include "gtkprefs.h"
--#include "gtkblist.h"
--#include "gtkutils.h"
--#include "signals.h"
--#include "version.h"
--
--/*
-- * MACROS & DEFINES
-- */
--#define WINTRANS_PLUGIN_ID "gtk-win-trans"
--
--#define blist (purple_get_blist() \
-- ? (PIDGIN_BLIST(purple_get_blist()) \
-- ? ((PIDGIN_BLIST(purple_get_blist()))->window) \
-- : NULL) \
-- : NULL)
--
--/*
-- * DATA STRUCTS
-- */
--typedef struct {
-- GtkWidget *win;
-- GtkWidget *slider;
--} slider_win;
--
--/*
-- * LOCALS
-- */
--static const char *OPT_WINTRANS_IM_ENABLED= "/plugins/gtk/win32/wintrans/im_enabled";
--static const char *OPT_WINTRANS_IM_ALPHA = "/plugins/gtk/win32/wintrans/im_alpha";
--static const char *OPT_WINTRANS_IM_SLIDER = "/plugins/gtk/win32/wintrans/im_slider";
--static const char *OPT_WINTRANS_IM_ONFOCUS= "/plugins/gtk/win32/wintrans/im_solid_onfocus";
--static const char *OPT_WINTRANS_IM_ONTOP = "/plugins/gtk/win32/wintrans/im_always_on_top";
--static const char *OPT_WINTRANS_BL_ENABLED= "/plugins/gtk/win32/wintrans/bl_enabled";
--static const char *OPT_WINTRANS_BL_ALPHA = "/plugins/gtk/win32/wintrans/bl_alpha";
--static const char *OPT_WINTRANS_BL_ONFOCUS= "/plugins/gtk/win32/wintrans/bl_solid_onfocus";
--static const char *OPT_WINTRANS_BL_ONTOP = "/plugins/gtk/win32/wintrans/bl_always_on_top";
--static GSList *window_list = NULL;
--
--/*
-- * CODE
-- */
--
--/* Set window transparency level */
--static void set_wintrans(GtkWidget *window, int alpha, gboolean enabled,
-- gboolean always_on_top) {
--
-- HWND hWnd = GDK_WINDOW_HWND(window->window);
-- LONG style = GetWindowLong(hWnd, GWL_EXSTYLE);
-- if (enabled) {
-- style |= WS_EX_LAYERED;
-- } else {
-- style &= ~WS_EX_LAYERED;
-- }
-- SetWindowLong(hWnd, GWL_EXSTYLE, style);
--
--
-- if (enabled) {
-- SetWindowPos(hWnd,
-- always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST,
-- 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
-- SetLayeredWindowAttributes(hWnd, 0, alpha, LWA_ALPHA);
-- } else {
-- /* Ask the window and its children to repaint */
-- SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
-- SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
--
-- RedrawWindow(hWnd, NULL, NULL,
-- RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
-- }
--
--}
--
--/* When a conv window is focused, if we're only transparent when unfocused,
-- * deal with transparency */
--static gboolean focus_conv_win_cb(GtkWidget *w, GdkEventFocus *e, gpointer d) {
-- if (purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED)
-- && purple_prefs_get_bool(OPT_WINTRANS_IM_ONFOCUS)) {
-- GtkWidget *window = (GtkWidget *) d;
-- if (e->in) { /* Focused */
-- set_wintrans(window, 0, FALSE,
-- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
-- } else {
-- set_wintrans(window,
-- purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA),
-- TRUE,
-- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
-- }
-- }
-- return FALSE;
--}
--
--/* When buddy list window is focused,
-- * if we're only transparent when unfocused, deal with transparency */
--static gboolean focus_blist_win_cb(GtkWidget *w, GdkEventFocus *e, gpointer d) {
-- if (purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED)
-- && purple_prefs_get_bool(OPT_WINTRANS_BL_ONFOCUS)) {
-- GtkWidget *window = (GtkWidget *) d;
-- if (e->in) { /* Focused */
-- set_wintrans(window, 0, FALSE,
-- purple_prefs_get_bool(OPT_WINTRANS_BL_ONTOP));
-- } else {
-- set_wintrans(window,
-- purple_prefs_get_int(OPT_WINTRANS_BL_ALPHA),
-- TRUE,
-- purple_prefs_get_bool(OPT_WINTRANS_BL_ONTOP));
-- }
-- }
-- return FALSE;
--}
--
--static void change_alpha(GtkWidget *w, gpointer data) {
-- int alpha = gtk_range_get_value(GTK_RANGE(w));
-- purple_prefs_set_int(OPT_WINTRANS_IM_ALPHA, alpha);
--
-- /* If we're in no-transparency on focus mode,
-- * don't take effect immediately */
-- if (!purple_prefs_get_bool(OPT_WINTRANS_IM_ONFOCUS))
-- set_wintrans(GTK_WIDGET(data), alpha, TRUE,
-- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
--}
--
--
--static GtkWidget *wintrans_slider(GtkWidget *win) {
-- GtkWidget *hbox;
-- GtkWidget *label, *slider;
-- GtkWidget *frame;
--
-- int imalpha = purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA);
--
-- frame = gtk_frame_new(NULL);
-- gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE);
-- gtk_widget_show(frame);
--
-- hbox = gtk_hbox_new(FALSE, 5);
-- gtk_container_add(GTK_CONTAINER(frame), hbox);
--
-- label = gtk_label_new(_("Opacity:"));
-- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
-- gtk_widget_show(hbox);
--
-- slider = gtk_hscale_new_with_range(50, 255, 1);
-- gtk_range_set_value(GTK_RANGE(slider), imalpha);
-- gtk_widget_set_usize(GTK_WIDGET(slider), 200, -1);
--
-- /* On slider val change, update window's transparency level */
-- g_signal_connect(GTK_OBJECT(slider), "value-changed",
-- G_CALLBACK(change_alpha), win);
--
-- gtk_box_pack_start(GTK_BOX(hbox), slider, FALSE, TRUE, 5);
--
-- /* Set the initial transparency level */
-- set_wintrans(win, imalpha, TRUE,
-- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
--
-- gtk_widget_show_all(hbox);
--
-- return frame;
--}
--
--static slider_win* find_slidwin(GtkWidget *win) {
-- GSList *tmp = window_list;
--
-- while (tmp) {
-- if (((slider_win*) (tmp->data))->win == win)
-- return (slider_win*) tmp->data;
-- tmp = tmp->next;
-- }
-- return NULL;
--}
--
--/* Clean up transparency stuff for the conv window */
--static void cleanup_conv_window(PidginWindow *win) {
-- GtkWidget *window = win->window;
-- slider_win *slidwin = NULL;
--
-- /* Remove window from the window list */
-- purple_debug_info(WINTRANS_PLUGIN_ID,
-- "Conv window destroyed... removing from list\n");
--
-- if ((slidwin = find_slidwin(window))) {
-- window_list = g_slist_remove(window_list, slidwin);
-- g_free(slidwin);
-- }
--
-- /* Remove the focus cbs */
-- g_signal_handlers_disconnect_by_func(G_OBJECT(window),
-- G_CALLBACK(focus_conv_win_cb), window);
--}
--
--static void
--conversation_delete_cb(PurpleConversation *conv) {
-- PidginWindow *win = pidgin_conv_get_window(PIDGIN_CONVERSATION(conv));
-- /* If it is the last conversation in the window, cleanup */
-- if (win != NULL && pidgin_conv_window_get_gtkconv_count(win) == 1)
-- cleanup_conv_window(win);
--}
--
--static void set_blist_trans(GtkWidget *w, const char *pref) {
-- gboolean enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w));
-- purple_prefs_set_bool(pref, enabled);
-- if (blist) {
-- set_wintrans(blist, purple_prefs_get_int(OPT_WINTRANS_BL_ALPHA),
-- purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED),
-- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
-- }
--}
--
--static void add_slider(GtkWidget *win) {
-- GList *wl, *wl1;
-- GtkWidget *vbox = NULL;
--
-- /* Look up this window to see if it already has a slider */
-- if (!find_slidwin(win)) {
-- GtkWidget *slider_box = NULL;
-- slider_win *slidwin = NULL;
-- GtkRequisition slidereq;
-- gint width, height;
--
-- /* Get top vbox */
-- for (wl1 = wl = gtk_container_get_children(
-- GTK_CONTAINER(win));
-- wl != NULL;
-- wl = wl->next) {
-- if (GTK_IS_VBOX(GTK_OBJECT(wl->data)))
-- vbox = GTK_WIDGET(wl->data);
-- else {
-- purple_debug_error(WINTRANS_PLUGIN_ID,
-- "no vbox found\n");
-- return;
-- }
-- }
-- g_list_free(wl1);
--
-- slider_box = wintrans_slider(win);
-- /* Figure out how tall the slider wants to be */
-- gtk_widget_size_request(slider_box, &slidereq);
-- gtk_window_get_size(GTK_WINDOW(win), &width, &height);
-- gtk_box_pack_start(GTK_BOX(vbox),
-- slider_box, FALSE, FALSE, 0);
--#if 0 /*Now that we save window sizes, don't resize it or else it causes windows to grow*/
-- /* Make window taller so we don't slowly collapse its message area */
-- gtk_window_resize(GTK_WINDOW(win), width,
-- (height + slidereq.height));
--#endif
-- /* Add window to list, to track that it has a slider */
-- slidwin = g_new0(slider_win, 1);
-- slidwin->win = win;
-- slidwin->slider = slider_box;
-- window_list = g_slist_append(window_list, slidwin);
-- }
--}
--
--static void remove_sliders() {
-- if (window_list) {
-- GSList *tmp = window_list;
-- while (tmp) {
-- slider_win *slidwin = (slider_win*) tmp->data;
-- if (slidwin != NULL &&
-- GTK_IS_WINDOW(slidwin->win)) {
--#if 0
-- GtkRequisition slidereq;
-- gint width, height;
-- /* Figure out how tall the slider was */
-- gtk_widget_size_request(
-- slidwin->slider, &slidereq);
-- gtk_window_get_size(
-- GTK_WINDOW(slidwin->win),
-- &width, &height);
--#endif
-- gtk_widget_destroy(slidwin->slider);
--#if 0
-- gtk_window_resize(
-- GTK_WINDOW(slidwin->win),
-- width, (height - slidereq.height));
--#endif
-- }
-- g_free(slidwin);
-- tmp = tmp->next;
-- }
-- g_slist_free(window_list);
-- window_list = NULL;
-- }
--}
--
--/* Remove all transparency related aspects from conversation windows */
--static void remove_convs_wintrans(gboolean remove_signal) {
-- GList *wins;
--
-- for (wins = pidgin_conv_windows_get_list(); wins; wins = wins->next) {
-- PidginWindow *win = wins->data;
-- GtkWidget *window = win->window;
--
-- if (purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED))
-- set_wintrans(window, 0, FALSE, FALSE);
--
-- /* Remove the focus cbs */
-- if (remove_signal)
-- g_signal_handlers_disconnect_by_func(G_OBJECT(window),
-- G_CALLBACK(focus_conv_win_cb), window);
-- }
--
-- remove_sliders();
--}
--
--static void set_conv_window_trans(PidginWindow *oldwin, PidginWindow *newwin) {
-- GtkWidget *win = newwin->window;
--
-- /* check prefs to see if we want trans */
-- if (purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED)) {
-- set_wintrans(win, purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA),
-- TRUE, purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
--
-- if (purple_prefs_get_bool(OPT_WINTRANS_IM_SLIDER)) {
-- add_slider(win);
-- }
-- }
--
-- /* If we're moving from one window to another,
-- * add the focus listeners to the new window if not already there */
-- if (oldwin != NULL && oldwin != newwin) {
-- if (pidgin_conv_window_get_gtkconv_count(newwin) == 0) {
-- g_signal_connect(G_OBJECT(win), "focus_in_event",
-- G_CALLBACK(focus_conv_win_cb), win);
-- g_signal_connect(G_OBJECT(win), "focus_out_event",
-- G_CALLBACK(focus_conv_win_cb), win);
-- }
--
-- /* If we've moved the last conversation, cleanup the window */
-- if (pidgin_conv_window_get_gtkconv_count(oldwin) == 1)
-- cleanup_conv_window(oldwin);
-- }
--}
--
--static void update_convs_wintrans(GtkWidget *toggle_btn, const char *pref) {
-- purple_prefs_set_bool(pref, gtk_toggle_button_get_active(
-- GTK_TOGGLE_BUTTON(toggle_btn)));
--
-- if (purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED)) {
-- GList *wins;
--
-- for (wins = pidgin_conv_windows_get_list(); wins; wins = wins->next) {
-- PidginWindow *win = wins->data;
-- set_conv_window_trans(NULL, win);
-- }
--
-- if (!purple_prefs_get_bool(OPT_WINTRANS_IM_SLIDER))
-- remove_sliders();
-- }
-- else
-- remove_convs_wintrans(FALSE);
--}
--
--static void
--conv_updated_cb(PurpleConversation *conv, PurpleConvUpdateType type) {
-- PidginConversation *pconv = PIDGIN_CONVERSATION(conv);
-- PidginWindow *win = pidgin_conv_get_window(pconv);
--
-- if (type == PURPLE_CONV_UPDATE_UNSEEN && !pidgin_conv_is_hidden(pconv)
-- && pconv->unseen_state == PIDGIN_UNSEEN_NONE
-- && pidgin_conv_window_get_gtkconv_count(win) == 1) {
-- GtkWidget *window = win->window;
-- gboolean has_focus;
--
-- g_object_get(G_OBJECT(window), "has-toplevel-focus", &has_focus, NULL);
--
-- if (!has_focus || !purple_prefs_get_bool(OPT_WINTRANS_IM_ONFOCUS))
-- set_conv_window_trans(NULL, win);
--
-- if (g_signal_handler_find(G_OBJECT(window), G_SIGNAL_MATCH_FUNC,
-- 0, 0, NULL, G_CALLBACK(focus_conv_win_cb), NULL) == 0) {
-- g_signal_connect(G_OBJECT(window), "focus_in_event",
-- G_CALLBACK(focus_conv_win_cb), window);
-- g_signal_connect(G_OBJECT(window), "focus_out_event",
-- G_CALLBACK(focus_conv_win_cb), window);
-- }
-- }
--}
--
--static void
--new_conversation_cb(PurpleConversation *conv) {
-- PidginWindow *win = pidgin_conv_get_window(PIDGIN_CONVERSATION(conv));
--
-- /* If it is the first conversation in the window,
-- * add the sliders, and set transparency */
-- if (!pidgin_conv_is_hidden(PIDGIN_CONVERSATION(conv)) && pidgin_conv_window_get_gtkconv_count(win) == 1) {
-- GtkWidget *window = win->window;
--
-- set_conv_window_trans(NULL, win);
--
-- g_signal_connect(G_OBJECT(window), "focus_in_event",
-- G_CALLBACK(focus_conv_win_cb), window);
-- g_signal_connect(G_OBJECT(window), "focus_out_event",
-- G_CALLBACK(focus_conv_win_cb), window);
-- }
--}
--
--static void
--blist_created_cb(PurpleBuddyList *purple_blist, gpointer data) {
-- if (blist) {
-- if (purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED)) {
-- set_wintrans(blist,
-- purple_prefs_get_int(OPT_WINTRANS_BL_ALPHA),
-- TRUE,
-- purple_prefs_get_bool(OPT_WINTRANS_BL_ONTOP));
-- }
--
-- g_signal_connect(G_OBJECT(blist), "focus_in_event",
-- G_CALLBACK(focus_blist_win_cb), blist);
-- g_signal_connect(G_OBJECT(blist), "focus_out_event",
-- G_CALLBACK(focus_blist_win_cb), blist);
-- }
--}
--
--static void alpha_change(GtkWidget *w, gpointer data) {
-- GList *wins;
-- int imalpha = gtk_range_get_value(GTK_RANGE(w));
--
-- for (wins = pidgin_conv_windows_get_list(); wins; wins = wins->next) {
-- PidginWindow *win = wins->data;
-- set_wintrans(win->window, imalpha, TRUE,
-- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
-- }
--}
--
--static void alpha_pref_set_int (GtkWidget *w, GdkEventFocus *e, const char *pref)
--{
-- int alpha = gtk_range_get_value(GTK_RANGE(w));
-- purple_prefs_set_int(pref, alpha);
--}
--
--static void bl_alpha_change(GtkWidget *w, gpointer data) {
-- if (blist)
-- change_alpha(w, blist);
--}
--
--static void update_existing_convs() {
-- GList *wins;
--
-- for (wins = pidgin_conv_windows_get_list(); wins; wins = wins->next) {
-- PidginWindow *win = wins->data;
-- GtkWidget *window = win->window;
--
-- set_conv_window_trans(NULL, win);
--
-- g_signal_connect(G_OBJECT(window), "focus_in_event",
-- G_CALLBACK(focus_conv_win_cb), window);
-- g_signal_connect(G_OBJECT(window), "focus_out_event",
-- G_CALLBACK(focus_conv_win_cb), window);
-- }
--}
--
--/*
-- * EXPORTED FUNCTIONS
-- */
--static gboolean plugin_load(PurplePlugin *plugin) {
--
-- purple_signal_connect(purple_conversations_get_handle(),
-- "conversation-created", plugin,
-- PURPLE_CALLBACK(new_conversation_cb), NULL);
--
-- /* Set callback to remove window from the list, if the window is destroyed */
-- purple_signal_connect(purple_conversations_get_handle(),
-- "deleting-conversation", plugin,
-- PURPLE_CALLBACK(conversation_delete_cb), NULL);
--
-- purple_signal_connect(pidgin_conversations_get_handle(),
-- "conversation-dragging", plugin,
-- PURPLE_CALLBACK(set_conv_window_trans), NULL);
--
-- purple_signal_connect(purple_conversations_get_handle(),
-- "conversation-updated", plugin,
-- PURPLE_CALLBACK(conv_updated_cb), NULL);
--
-- update_existing_convs();
--
-- if (blist)
-- blist_created_cb(NULL, NULL);
-- else
-- purple_signal_connect(pidgin_blist_get_handle(),
-- "gtkblist-created", plugin,
-- PURPLE_CALLBACK(blist_created_cb), NULL);
--
--
-- return TRUE;
--}
--
--static gboolean plugin_unload(PurplePlugin *plugin) {
-- purple_debug_info(WINTRANS_PLUGIN_ID, "Unloading win2ktrans plugin\n");
--
-- remove_convs_wintrans(TRUE);
--
-- if (blist) {
-- if (purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED))
-- set_wintrans(blist, 0, FALSE, FALSE);
--
-- /* Remove the focus cbs */
-- g_signal_handlers_disconnect_by_func(G_OBJECT(blist),
-- G_CALLBACK(focus_blist_win_cb), blist);
-- }
--
-- return TRUE;
--}
--
--static GtkWidget *get_config_frame(PurplePlugin *plugin) {
-- GtkWidget *ret;
-- GtkWidget *imtransbox, *bltransbox;
-- GtkWidget *hbox;
-- GtkWidget *label, *slider;
-- GtkWidget *button;
-- GtkWidget *trans_box;
--
-- ret = gtk_vbox_new(FALSE, 18);
-- gtk_container_set_border_width(GTK_CONTAINER (ret), 12);
--
-- /* IM Convo trans options */
-- imtransbox = pidgin_make_frame(ret, _("IM Conversation Windows"));
-- button = pidgin_prefs_checkbox(_("_IM window transparency"),
-- OPT_WINTRANS_IM_ENABLED, imtransbox);
-- g_signal_connect(GTK_OBJECT(button), "clicked",
-- G_CALLBACK(update_convs_wintrans),
-- (gpointer) OPT_WINTRANS_IM_ENABLED);
--
-- trans_box = gtk_vbox_new(FALSE, 18);
-- if (!purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED))
-- gtk_widget_set_sensitive(GTK_WIDGET(trans_box), FALSE);
-- gtk_widget_show(trans_box);
--
-- g_signal_connect(GTK_OBJECT(button), "clicked",
-- G_CALLBACK(pidgin_toggle_sensitive), trans_box);
--
-- button = pidgin_prefs_checkbox(_("_Show slider bar in IM window"),
-- OPT_WINTRANS_IM_SLIDER, trans_box);
-- g_signal_connect(GTK_OBJECT(button), "clicked",
-- G_CALLBACK(update_convs_wintrans),
-- (gpointer) OPT_WINTRANS_IM_SLIDER);
--
-- button = pidgin_prefs_checkbox(
-- _("Remove IM window transparency on focus"),
-- OPT_WINTRANS_IM_ONFOCUS, trans_box);
--
-- button = pidgin_prefs_checkbox(_("Always on top"), OPT_WINTRANS_IM_ONTOP,
-- trans_box);
-- g_signal_connect(GTK_OBJECT(button), "clicked",
-- G_CALLBACK(update_convs_wintrans),
-- (gpointer) OPT_WINTRANS_IM_ONTOP);
--
-- gtk_box_pack_start(GTK_BOX(imtransbox), trans_box, FALSE, FALSE, 5);
--
-- /* IM transparency slider */
-- hbox = gtk_hbox_new(FALSE, 5);
--
-- label = gtk_label_new(_("Opacity:"));
-- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
--
-- slider = gtk_hscale_new_with_range(50, 255, 1);
-- gtk_range_set_value(GTK_RANGE(slider),
-- purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA));
-- gtk_widget_set_usize(GTK_WIDGET(slider), 200, -1);
--
-- g_signal_connect(GTK_OBJECT(slider), "value-changed",
-- G_CALLBACK(alpha_change), NULL);
-- g_signal_connect(GTK_OBJECT(slider), "focus-out-event",
-- G_CALLBACK(alpha_pref_set_int),
-- (gpointer) OPT_WINTRANS_IM_ALPHA);
--
-- gtk_box_pack_start(GTK_BOX(hbox), slider, FALSE, TRUE, 5);
--
-- gtk_widget_show_all(hbox);
--
-- gtk_box_pack_start(GTK_BOX(trans_box), hbox, FALSE, FALSE, 5);
--
-- /* Buddy List trans options */
-- bltransbox = pidgin_make_frame (ret, _("Buddy List Window"));
-- button = pidgin_prefs_checkbox(_("_Buddy List window transparency"),
-- OPT_WINTRANS_BL_ENABLED, bltransbox);
-- g_signal_connect(GTK_OBJECT(button), "clicked",
-- G_CALLBACK(set_blist_trans),
-- (gpointer) OPT_WINTRANS_BL_ENABLED);
--
-- trans_box = gtk_vbox_new(FALSE, 18);
-- if (!purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED))
-- gtk_widget_set_sensitive(GTK_WIDGET(trans_box), FALSE);
-- gtk_widget_show(trans_box);
-- g_signal_connect(GTK_OBJECT(button), "clicked",
-- G_CALLBACK(pidgin_toggle_sensitive), trans_box);
-- button = pidgin_prefs_checkbox(
-- _("Remove Buddy List window transparency on focus"),
-- OPT_WINTRANS_BL_ONFOCUS, trans_box);
-- button = pidgin_prefs_checkbox(_("Always on top"), OPT_WINTRANS_BL_ONTOP,
-- trans_box);
-- g_signal_connect(GTK_OBJECT(button), "clicked",
-- G_CALLBACK(set_blist_trans),
-- (gpointer) OPT_WINTRANS_BL_ONTOP);
-- gtk_box_pack_start(GTK_BOX(bltransbox), trans_box, FALSE, FALSE, 5);
--
-- /* IM transparency slider */
-- hbox = gtk_hbox_new(FALSE, 5);
--
-- label = gtk_label_new(_("Opacity:"));
-- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
--
-- slider = gtk_hscale_new_with_range(50, 255, 1);
-- gtk_range_set_value(GTK_RANGE(slider),
-- purple_prefs_get_int(OPT_WINTRANS_BL_ALPHA));
--
-- gtk_widget_set_usize(GTK_WIDGET(slider), 200, -1);
--
-- g_signal_connect(GTK_OBJECT(slider), "value-changed",
-- G_CALLBACK(bl_alpha_change), NULL);
-- g_signal_connect(GTK_OBJECT(slider), "focus-out-event",
-- G_CALLBACK(alpha_pref_set_int),
-- (gpointer) OPT_WINTRANS_BL_ALPHA);
--
-- gtk_box_pack_start(GTK_BOX(hbox), slider, FALSE, TRUE, 5);
--
-- gtk_widget_show_all(hbox);
--
-- gtk_box_pack_start(GTK_BOX(trans_box), hbox, FALSE, FALSE, 5);
--
-- gtk_widget_show_all(ret);
-- return ret;
--}
--
--static PidginPluginUiInfo ui_info =
--{
-- get_config_frame,
-- 0, /* page_num (Reserved) */
--
-- /* padding */
-- NULL,
-- NULL,
-- NULL,
-- NULL
--};
--
--static PurplePluginInfo info =
--{
-- PURPLE_PLUGIN_MAGIC,
-- PURPLE_MAJOR_VERSION,
-- PURPLE_MINOR_VERSION,
-- PURPLE_PLUGIN_STANDARD, /**< type */
-- PIDGIN_PLUGIN_TYPE, /**< ui_requirement */
-- 0, /**< flags */
-- NULL, /**< dependencies */
-- PURPLE_PRIORITY_DEFAULT, /**< priority */
-- WINTRANS_PLUGIN_ID, /**< id */
-- N_("Transparency"), /**< name */
-- DISPLAY_VERSION, /**< version */
-- /** summary */
-- N_("Variable Transparency for the buddy list and conversations."),
-- /** description */
-- N_("This plugin enables variable alpha transparency on conversation windows and the buddy list.\n\n"
-- "* Note: This plugin requires Win2000 or greater."),
-- "Herman Bloggs <hermanator12002@yahoo.com>", /**< author */
-- PURPLE_WEBSITE, /**< homepage */
-- plugin_load, /**< load */
-- plugin_unload, /**< unload */
-- NULL, /**< destroy */
-- &ui_info, /**< ui_info */
-- NULL, /**< extra_info */
-- NULL, /**< prefs_info */
-- NULL, /**< actions */
--
-- /* padding */
-- NULL,
-- NULL,
-- NULL,
-- NULL
--};
--
--static void
--init_plugin(PurplePlugin *plugin)
--{
-- purple_prefs_add_none("/plugins/gtk/win32");
-- purple_prefs_add_none("/plugins/gtk/win32/wintrans");
-- purple_prefs_add_bool(OPT_WINTRANS_IM_ENABLED, FALSE);
-- purple_prefs_add_int(OPT_WINTRANS_IM_ALPHA, 255);
-- purple_prefs_add_bool(OPT_WINTRANS_IM_SLIDER, FALSE);
-- purple_prefs_add_bool(OPT_WINTRANS_IM_ONFOCUS, FALSE);
-- purple_prefs_add_bool(OPT_WINTRANS_IM_ONTOP, FALSE);
-- purple_prefs_add_bool(OPT_WINTRANS_BL_ENABLED, FALSE);
-- purple_prefs_add_int(OPT_WINTRANS_BL_ALPHA, 255);
-- purple_prefs_add_bool(OPT_WINTRANS_BL_ONFOCUS, FALSE);
-- purple_prefs_add_bool(OPT_WINTRANS_BL_ONTOP, FALSE);
--}
--
--PURPLE_INIT_PLUGIN(wintrans, init_plugin, info)
-diff -Nur pidgin-2.10.7/pidgin/plugins/win32/winprefs/gtkappbar.c pidgin-2.10.7-nonprism/pidgin/plugins/win32/winprefs/gtkappbar.c
---- pidgin-2.10.7/pidgin/plugins/win32/winprefs/gtkappbar.c 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/win32/winprefs/gtkappbar.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,693 +0,0 @@
--/*
-- * purple - WinPurple Options Plugin
-- *
-- * File: gtkappbar.c
-- * Date: August 2, 2003
-- * Description: Appbar functionality for Windows GTK+ applications
-- *
-- * Copyright (C) 2003, Herman Bloggs <hermanator12002@yahoo.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--/*
-- * TODO:
-- * - Move 'App on top' feature from Trans plugin to here
-- * - Bug: Multiple Show/Hide Desktop calls causes client area to disappear
-- */
--#include <windows.h>
--#include <winver.h>
--#include <stdio.h>
--#include <gtk/gtk.h>
--#include <gdk/gdkwin32.h>
--#include "gtkappbar.h"
--#include "debug.h"
--
--#define APPBAR_CALLBACK WM_USER + 1010
--
--typedef HMONITOR WINAPI purple_MonitorFromPoint(POINT, DWORD);
--typedef HMONITOR WINAPI purple_MonitorFromWindow(HWND, DWORD);
--typedef BOOL WINAPI purple_GetMonitorInfo(HMONITOR, LPMONITORINFO);
--
--static void gtk_appbar_do_dock(GtkAppBar *ab, UINT side);
--
--/* Retrieve the rectangular display area from the specified monitor
-- * Return TRUE if successful, otherwise FALSE
-- */
--static gboolean
--get_rect_from_monitor(HMODULE hmod, HMONITOR monitor, RECT *rect) {
-- purple_GetMonitorInfo *the_GetMonitorInfo;
-- MONITORINFO info;
--
-- if (!(the_GetMonitorInfo = (purple_GetMonitorInfo*)
-- GetProcAddress(hmod, "GetMonitorInfoA"))) {
-- return FALSE;
-- }
--
-- info.cbSize = sizeof(info);
-- if (!the_GetMonitorInfo(monitor, &info)) {
-- return FALSE;
-- }
--
-- CopyRect(rect, &(info.rcMonitor));
--
-- return TRUE;
--}
--
--/**
-- * This will only work on Win98+ and Win2K+
-- * Return TRUE if successful, otherwise FALSE
-- */
--static gboolean
--get_rect_at_point_multimonitor(POINT pt, RECT *rect) {
-- HMODULE hmod;
-- purple_MonitorFromPoint *the_MonitorFromPoint;
-- HMONITOR monitor;
--
-- if (!(hmod = GetModuleHandle("user32"))) {
-- return FALSE;
-- }
--
-- if (!(the_MonitorFromPoint = (purple_MonitorFromPoint*)
-- GetProcAddress(hmod, "MonitorFromPoint"))) {
-- return FALSE;
-- }
--
-- monitor =
-- the_MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
--
-- return get_rect_from_monitor(hmod, monitor, rect);
--}
--
--/**
-- * This will only work on Win98+ and Win2K+
-- * Return TRUE if successful, otherwise FALSE
-- */
--static gboolean
--get_rect_of_window_multimonitor(HWND window, RECT *rect) {
-- HMODULE hmod;
-- purple_MonitorFromWindow *the_MonitorFromWindow;
-- HMONITOR monitor;
--
-- if (!(hmod = GetModuleHandle("user32"))) {
-- return FALSE;
-- }
--
-- if (!(the_MonitorFromWindow = (purple_MonitorFromWindow*)
-- GetProcAddress(hmod, "MonitorFromWindow"))) {
-- return FALSE;
-- }
--
-- monitor =
-- the_MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY);
--
-- return get_rect_from_monitor(hmod, monitor, rect);
--}
--
--/*
-- * Fallback if cannot get the RECT from the monitor directly
-- */
--static void get_default_workarea(RECT *rect) {
-- if (!SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, FALSE)) {
-- /* I don't think this will ever happen */
-- rect->left = 0;
-- rect->top = 0;
-- rect->bottom = GetSystemMetrics(SM_CYSCREEN);
-- rect->right = GetSystemMetrics(SM_CXSCREEN);
-- }
--}
--
--/* Retrieve the rectangle of the active work area at a point */
--static void get_rect_at_point(POINT pt, RECT *rc) {
-- if (!get_rect_at_point_multimonitor(pt, rc)) {
-- get_default_workarea(rc);
-- }
--}
--
--/* Retrieve the rectangle of the active work area of a window*/
--static void get_rect_of_window(HWND window, RECT *rc) {
-- if (!get_rect_of_window_multimonitor(window, rc)) {
-- get_default_workarea(rc);
-- }
--}
--
--static void get_window_normal_rc(HWND hwnd, RECT *rc) {
-- WINDOWPLACEMENT wplc;
-- GetWindowPlacement(hwnd, &wplc);
-- CopyRect(rc, &wplc.rcNormalPosition);
--}
--#if 0
--static void print_rect(RECT *rc) {
-- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "RECT: L:%ld R:%ld T:%ld B:%ld\n",
-- rc->left, rc->right, rc->top, rc->bottom);
--}
--#endif
--/** Set the window style to be the "Tool Window" style - small header, no min/max buttons */
--static void set_toolbar(HWND hwnd, gboolean val) {
-- LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);
--
-- if(val && !(style & WS_EX_TOOLWINDOW))
-- style |= WS_EX_TOOLWINDOW;
-- else if(!val && style & WS_EX_TOOLWINDOW)
-- style &= ~WS_EX_TOOLWINDOW;
-- else
-- return;
-- SetWindowLong(hwnd, GWL_EXSTYLE, style);
-- SetWindowPos(hwnd, 0, 0, 0, 0, 0,
-- SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
--
--/* This really should be the following, but SWP_FRAMECHANGED strangely causes initermittent problems "Show Desktop" done more than once.
-- * Not having SWP_FRAMECHANGED *should* cause the Style not to be applied, but i haven't noticed any problems
-- * SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
-- */
--}
--/** Register the window as an appbar */
--static gboolean gtk_appbar_register(GtkAppBar *ab, HWND hwnd) {
-- APPBARDATA abd;
--
-- abd.cbSize = sizeof(APPBARDATA);
-- abd.hWnd = hwnd;
-- abd.uCallbackMessage = APPBAR_CALLBACK;
--
-- ab->registered = SHAppBarMessage(ABM_NEW, &abd);
--
-- return ab->registered;
--}
--/** Unregister the window as an appbar */
--static gboolean gtk_appbar_unregister(GtkAppBar *ab, HWND hwnd) {
-- APPBARDATA abd;
--
-- if(!ab->registered)
-- return TRUE;
--
-- abd.cbSize = sizeof(APPBARDATA);
-- abd.hWnd = hwnd;
--
-- SHAppBarMessage(ABM_REMOVE, &abd); /** This always returns TRUE */
--
-- ab->registered = FALSE;
--
-- ab->docked = FALSE;
-- ab->undocking = FALSE;
-- ab->docking = FALSE;
--
-- return TRUE;
--}
--
--static void gtk_appbar_querypos(GtkAppBar *ab, HWND hwnd, RECT rcWorkspace) {
-- APPBARDATA abd;
-- guint iWidth = 0;
--
-- if(!ab->registered)
-- gtk_appbar_register(ab, hwnd);
--
-- abd.hWnd = hwnd;
-- abd.cbSize = sizeof(APPBARDATA);
-- abd.uEdge = ab->side;
--
-- iWidth = ab->docked_rect.right - ab->docked_rect.left;
--
-- abd.rc.top = rcWorkspace.top;
-- abd.rc.bottom = rcWorkspace.bottom;
-- switch (abd.uEdge)
-- {
-- case ABE_LEFT:
-- abd.rc.left = rcWorkspace.left;
-- abd.rc.right = rcWorkspace.left + iWidth;
-- break;
--
-- case ABE_RIGHT:
-- abd.rc.right = rcWorkspace.right;
-- abd.rc.left = rcWorkspace.right - iWidth;
-- break;
-- }
--
-- /* Ask the system for the screen space */
-- SHAppBarMessage(ABM_QUERYPOS, &abd);
--
-- switch (abd.uEdge)
-- {
-- case ABE_LEFT:
-- abd.rc.right = abd.rc.left + iWidth;
-- break;
--
-- case ABE_RIGHT:
-- abd.rc.left = abd.rc.right - iWidth;
-- break;
-- }
--
-- CopyRect(&(ab->docked_rect), &abd.rc);
--}
--/* Actually set the size and screen location of the appbar */
--static void gtk_appbar_setpos(GtkAppBar *ab, HWND hwnd) {
-- APPBARDATA abd;
--
-- if(!ab->registered)
-- gtk_appbar_register(ab, hwnd);
--
-- abd.hWnd = hwnd;
-- abd.cbSize = sizeof(APPBARDATA);
-- CopyRect(&abd.rc, &(ab->docked_rect));
-- abd.uEdge = ab->side;
--
-- SHAppBarMessage(ABM_SETPOS, &abd);
--}
--/** Let any callbacks know that we have docked or undocked */
--static void gtk_appbar_dispatch_dock_cbs(GtkAppBar *ab, gboolean val) {
-- GSList *lst = ab->dock_cbs;
--
-- while(lst) {
-- GtkAppBarDockCB dock_cb = lst->data;
-- dock_cb(val);
-- lst = lst->next;
-- }
--}
--
--static GdkFilterReturn wnd_moving(GtkAppBar *ab, GdkXEvent *xevent) {
-- MSG *msg = (MSG*)xevent;
-- POINT cp;
-- RECT *rc = (RECT*)msg->lParam;
-- RECT monRect;
-- int side = -1;
-- long dockAreaWidth = 0;
--
-- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_moving\n");
--
-- GetCursorPos(&cp);
-- get_rect_at_point(cp, &monRect);
--
-- dockAreaWidth = (monRect.right - monRect.left) / 10;
-- /* Which part of the screen are we in ? */
-- if (cp.x > (monRect.right - dockAreaWidth)) {
-- side = ABE_RIGHT;
-- } else if (cp.x < (monRect.left + dockAreaWidth)) {
-- side = ABE_LEFT;
-- }
--
-- if(!ab->docked) {
-- if( (side == ABE_RIGHT || side == ABE_LEFT) ) {
-- if( !ab->docking ) {
-- ab->side = side;
-- GetWindowRect(msg->hwnd, &(ab->docked_rect));
-- gtk_appbar_querypos(ab, msg->hwnd, monRect);
--
-- /* save pre-docking height */
-- ab->undocked_height = rc->bottom - rc->top;
-- ab->docking = TRUE;
-- }
-- }
-- else
-- ab->docking = FALSE;
-- }
-- else if(side < 0) {
-- gtk_appbar_unregister(ab, msg->hwnd);
-- ab->undocking = TRUE;
-- rc->bottom = rc->top + ab->undocked_height;
-- }
--
-- return GDK_FILTER_CONTINUE;
--}
--
--static GdkFilterReturn wnd_sizing(GtkAppBar *ab, GdkXEvent *xevent) {
-- MSG *msg = (MSG*)xevent;
--
-- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_sizing\n");
-- if(ab->docked) {
-- RECT *rc = (RECT*)msg->lParam;
-- if(ab->side == ABE_LEFT && msg->wParam == WMSZ_RIGHT) {
-- ab->docked_rect.right = rc->right;
-- gtk_appbar_setpos(ab, msg->hwnd);
-- }
-- else if(ab->side == ABE_RIGHT && msg->wParam == WMSZ_LEFT) {
-- ab->docked_rect.left = rc->left;
-- gtk_appbar_setpos(ab, msg->hwnd);
-- }
-- return GDK_FILTER_REMOVE;
-- }
-- return GDK_FILTER_CONTINUE;
--}
--/** Notify the system that the appbar has been activated */
--static GdkFilterReturn wnd_activate(GtkAppBar *ab, GdkXEvent *xevent) {
-- if (ab->registered) {
-- APPBARDATA abd;
-- MSG *msg = (MSG*)xevent;
-- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_activate\n");
--
-- abd.hWnd = msg->hwnd;
-- abd.cbSize = sizeof(APPBARDATA);
--
-- SHAppBarMessage(ABM_ACTIVATE, &abd);
-- }
-- return GDK_FILTER_CONTINUE;
--}
--
--static void show_hide(GtkAppBar *ab, gboolean hide) {
-- purple_debug_info("gtkappbar", "show_hide(%d)\n", hide);
--
-- if (hide) {
-- purple_debug_info("gtkappbar", "hidden\n");
-- gtk_appbar_unregister(ab, GDK_WINDOW_HWND(ab->win->window));
-- ab->docked = TRUE;
-- ab->iconized = TRUE;
-- } else {
-- ab->iconized = FALSE;
-- purple_debug_info("gtkappbar", "shown\n");
-- ab->docked = FALSE;
-- gtk_appbar_do_dock(ab, ab->side);
-- }
--
--}
--
--/** Notify the system that the appbar's position has changed */
--static GdkFilterReturn wnd_poschanged(GtkAppBar *ab, GdkXEvent *xevent) {
-- if (ab->registered) {
-- APPBARDATA abd;
-- MSG *msg = (MSG*)xevent;
--
-- purple_debug(PURPLE_DEBUG_MISC, "gtkappbar", "wnd_poschanged\n");
--
-- abd.hWnd = msg->hwnd;
-- abd.cbSize = sizeof(APPBARDATA);
--
-- SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd);
--
-- }
-- return GDK_FILTER_CONTINUE;
--}
--/** The window is about to change */
--static GdkFilterReturn wnd_poschanging(GtkAppBar *ab, GdkXEvent *xevent) {
-- MSG *msg = (MSG*)xevent;
-- WINDOWPOS *wpos = (WINDOWPOS*)msg->lParam;
--
-- purple_debug(PURPLE_DEBUG_MISC, "gtkappbar", "wnd_poschanging\n");
--
-- if(ab->docked || ab->docking) {
-- wpos->x = ab->docked_rect.left;
-- wpos->y = ab->docked_rect.top;
-- wpos->cx = ab->docked_rect.right - ab->docked_rect.left;
-- wpos->cy = ab->docked_rect.bottom - ab->docked_rect.top;
-- if(IsIconic(msg->hwnd))
-- set_toolbar(msg->hwnd, FALSE);
-- /*return GDK_FILTER_REMOVE;*/
-- }
--
-- if (ab->docked) {
-- if (ab->iconized && wpos->flags & SWP_SHOWWINDOW)
-- show_hide(ab, FALSE);
-- else if (!ab->iconized && wpos->flags & SWP_HIDEWINDOW)
-- show_hide(ab, TRUE);
-- }
--
-- return GDK_FILTER_CONTINUE;
--}
--
--static GdkFilterReturn wnd_exitsizemove(GtkAppBar *ab, GdkXEvent *xevent) {
-- MSG *msg = (MSG*)xevent;
--
-- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_exitsizemove\n");
-- if(ab->docking) {
-- gtk_appbar_setpos(ab, msg->hwnd);
-- ab->docking = FALSE;
-- ab->docked = TRUE;
-- ShowWindow(msg->hwnd, SW_HIDE);
-- set_toolbar(msg->hwnd, TRUE);
-- ShowWindow(msg->hwnd, SW_SHOW);
-- gtk_appbar_dispatch_dock_cbs(ab, TRUE);
-- } else if(ab->undocking) {
-- ShowWindow(msg->hwnd, SW_HIDE);
-- set_toolbar(msg->hwnd, FALSE);
-- ShowWindow(msg->hwnd, SW_SHOW);
-- gtk_appbar_dispatch_dock_cbs(ab, FALSE);
-- ab->undocking = FALSE;
-- }
--
-- return GDK_FILTER_CONTINUE;
--}
--
--static GdkFilterReturn wnd_showwindow(GtkAppBar *ab, GdkXEvent *xevent) {
-- MSG *msg = (MSG*)xevent;
--
-- purple_debug_info("gtkappbar", "wnd_showwindow\n");
-- if(msg->wParam && ab->docked) {
-- show_hide(ab, FALSE);
-- } else if(!msg->wParam && ab->docked) {
-- show_hide(ab, TRUE);
-- }
-- return GDK_FILTER_CONTINUE;
--}
--
--/** The window's size has changed */
--static GdkFilterReturn wnd_size(GtkAppBar *ab, GdkXEvent *xevent) {
-- MSG *msg = (MSG*)xevent;
--
-- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_size\n");
--
-- if(msg->wParam == SIZE_MINIMIZED) {
-- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "Minimize\n");
-- if(ab->docked) {
-- gtk_appbar_unregister(ab, GDK_WINDOW_HWND(ab->win->window));
-- ab->docked = TRUE;
-- }
-- }
-- else if(msg->wParam == SIZE_RESTORED) {
-- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "Restore\n");
-- if (!ab->iconized && ab->docked) {
-- gtk_appbar_do_dock(ab, ab->side);
-- }
-- }
-- return GDK_FILTER_CONTINUE;
--}
--
--static GdkFilterReturn wnd_nchittest(GtkAppBar *ab, GdkXEvent *xevent) {
-- MSG *msg = (MSG*)xevent;
--
-- if(ab->docked) {
-- UINT ret = DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
--
-- switch(ret) {
-- case HTBOTTOM:
-- case HTBOTTOMLEFT:
-- case HTBOTTOMRIGHT:
-- case HTTOP:
-- case HTTOPLEFT:
-- case HTTOPRIGHT:
-- return GDK_FILTER_REMOVE;
-- case HTLEFT:
-- if(ab->side == ABE_LEFT)
-- return GDK_FILTER_REMOVE;
-- break;
-- case HTRIGHT:
-- if(ab->side == ABE_RIGHT)
-- return GDK_FILTER_REMOVE;
-- break;
-- }
-- }
-- return GDK_FILTER_CONTINUE;
--}
--
--#if 0
--static GdkFilterReturn wnd_initmenupopup(GtkAppBar *ab, GdkXEvent *xevent) {
-- MSG *msg = (MSG*)xevent;
--
-- if(ab->docked && HIWORD(msg->lParam)) {
-- HMENU sysmenu = GetSystemMenu(msg->hwnd, FALSE);
-- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_initpopupmenu: docked: %d ismenu: %d\n", ab->docked, IsMenu(sysmenu));
-- if(EnableMenuItem(sysmenu, SC_MAXIMIZE, MF_BYCOMMAND|MF_GRAYED)<0)
-- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "SC_MAXIMIZE Menu item does not exist\n");
-- if(EnableMenuItem(sysmenu, SC_MOVE, MF_BYCOMMAND|MF_GRAYED)<0)
-- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "SC_MOVE Menu item does not exist\n");
-- return GDK_FILTER_CONTINUE;
-- }
-- else
-- GetSystemMenu(msg->hwnd, TRUE);
-- return GDK_FILTER_CONTINUE;
--}
--#endif
--
--static GdkFilterReturn gtk_appbar_callback(GtkAppBar *ab, GdkXEvent *xevent) {
-- MSG *msg = (MSG*)xevent;
-- RECT orig, windowRect;
--
-- switch (msg->wParam) {
-- case ABN_STATECHANGE:
-- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_STATECHANGE\n");
-- break;
--
-- case ABN_FULLSCREENAPP:
-- purple_debug(PURPLE_DEBUG_MISC, "gtkappbar", "gtk_appbar_callback: ABN_FULLSCREENAPP: %d\n", (BOOL)msg->lParam);
-- if (!ab->iconized && ab->docked) {
-- if ((BOOL)msg->lParam) {
-- SetWindowPos(msg->hwnd, HWND_BOTTOM, 0, 0, 0, 0,
-- SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
-- } else {
-- SetWindowPos(msg->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
-- SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_FRAMECHANGED);
-- }
-- }
--
-- break;
-- case ABN_POSCHANGED:
-- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_POSCHANGED\n");
-- CopyRect(&orig, &(ab->docked_rect));
-- get_rect_of_window(msg->hwnd, &windowRect);
-- gtk_appbar_querypos(ab, msg->hwnd, windowRect);
-- if (EqualRect(&orig, &(ab->docked_rect)) == 0) {
-- MoveWindow(msg->hwnd, ab->docked_rect.left, ab->docked_rect.top,
-- ab->docked_rect.right - ab->docked_rect.left,
-- ab->docked_rect.bottom - ab->docked_rect.top, TRUE);
-- }
-- gtk_appbar_setpos(ab, msg->hwnd);
-- break;
--#if 0
-- default:
-- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: %d\n", msg->wParam);
--#endif
-- }
-- return GDK_FILTER_CONTINUE;
--}
--
--static GdkFilterReturn gtk_appbar_event_filter(GdkXEvent *xevent, GdkEvent *event, gpointer data) {
-- MSG *msg = (MSG*)xevent;
--
-- /*printf("MSG: %s\n", message_to_string (msg->message));*/
-- switch(msg->message) {
-- case WM_EXITSIZEMOVE:
-- return wnd_exitsizemove(data, xevent);
-- case WM_WINDOWPOSCHANGING:
-- return wnd_poschanging(data, xevent);
-- case WM_WINDOWPOSCHANGED:
-- return wnd_poschanged(data, xevent);
-- case WM_ACTIVATE:
-- return wnd_activate(data, xevent);
-- case WM_SIZING:
-- return wnd_sizing(data, xevent);
-- case WM_MOVING:
-- return wnd_moving(data, xevent);
-- case WM_SHOWWINDOW:
-- return wnd_showwindow(data, xevent);
-- case WM_NCHITTEST:
-- return wnd_nchittest(data, xevent);
--#if 0
-- case WM_INITMENUPOPUP:
-- return wnd_initmenupopup(data, xevent);
--#endif
-- case WM_SIZE:
-- return wnd_size(data, xevent);
-- case APPBAR_CALLBACK:
-- return gtk_appbar_callback(data, xevent);
--#if 0
-- default:
-- purple_debug_info("gtkappbar", "gtk_appbar_event_filter %d\n", msg->message);
--#endif
-- }
-- return GDK_FILTER_CONTINUE;
--}
--
--static void gtk_appbar_do_dock(GtkAppBar *ab, UINT side) {
-- RECT orig, windowRect;
--
-- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_do_dock\n");
--
-- if(!ab || !IsWindow(GDK_WINDOW_HWND(ab->win->window)))
-- return;
--
-- ab->side = side;
-- get_window_normal_rc(GDK_WINDOW_HWND(ab->win->window), &(ab->docked_rect));
-- CopyRect(&orig, &(ab->docked_rect));
-- get_rect_of_window(GDK_WINDOW_HWND(ab->win->window), &windowRect);
-- gtk_appbar_querypos(ab, GDK_WINDOW_HWND(ab->win->window), windowRect);
-- if(EqualRect(&orig, &(ab->docked_rect)) == 0)
-- MoveWindow(GDK_WINDOW_HWND(ab->win->window),
-- ab->docked_rect.left,
-- ab->docked_rect.top,
-- ab->docked_rect.right - ab->docked_rect.left,
-- ab->docked_rect.bottom - ab->docked_rect.top, TRUE);
-- gtk_appbar_setpos(ab, GDK_WINDOW_HWND(ab->win->window));
-- ab->docked = TRUE;
--}
--
--void gtk_appbar_dock(GtkAppBar *ab, UINT side) {
-- HWND hwnd;
--
-- g_return_if_fail(ab != NULL);
--
-- hwnd = GDK_WINDOW_HWND(ab->win->window);
--
-- g_return_if_fail(IsWindow(hwnd));
--
-- ab->iconized = IsIconic(hwnd);
--
-- if (!ab->docked && !ab->iconized)
-- ShowWindow(hwnd, SW_HIDE);
-- gtk_appbar_do_dock(ab, side);
-- set_toolbar(hwnd, TRUE);
-- if (!ab->iconized)
-- ShowWindow(hwnd, SW_SHOW);
--}
--
--void gtk_appbar_add_dock_cb(GtkAppBar *ab, GtkAppBarDockCB dock_cb) {
-- if(!ab)
-- return;
-- ab->dock_cbs = g_slist_prepend(ab->dock_cbs, dock_cb);
--}
--
--GtkAppBar *gtk_appbar_add(GtkWidget *win) {
-- GtkAppBar *ab;
--
-- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_add\n");
--
-- if(!win)
-- return NULL;
-- ab = g_new0(GtkAppBar, 1);
-- ab->win = win;
--
-- /* init docking coords */
-- get_window_normal_rc(GDK_WINDOW_HWND(win->window), &(ab->docked_rect));
--
-- /* Add main window filter */
-- gdk_window_add_filter(win->window,
-- gtk_appbar_event_filter,
-- ab);
-- return ab;
--}
--
--void gtk_appbar_remove(GtkAppBar *ab) {
-- HWND hwnd;
-- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_remove\n");
--
-- if(!ab)
-- return;
--
-- hwnd = GDK_WINDOW_HWND(ab->win->window);
-- gdk_window_remove_filter(ab->win->window,
-- gtk_appbar_event_filter,
-- ab);
-- if(ab->docked) {
-- gtk_window_resize(GTK_WINDOW(ab->win),
-- ab->docked_rect.right - ab->docked_rect.left,
-- ab->undocked_height);
-- if (!ab->iconized)
-- ShowWindow(hwnd, SW_HIDE);
-- set_toolbar(hwnd, FALSE);
-- if (!ab->iconized)
-- ShowWindow(hwnd, SW_SHOW);
-- }
-- gtk_appbar_unregister(ab, hwnd);
--
-- while (ab->dock_cbs)
-- ab->dock_cbs = g_slist_remove(ab->dock_cbs, ab->dock_cbs->data);
--
-- g_free(ab);
--}
-diff -Nur pidgin-2.10.7/pidgin/plugins/win32/winprefs/gtkappbar.h pidgin-2.10.7-nonprism/pidgin/plugins/win32/winprefs/gtkappbar.h
---- pidgin-2.10.7/pidgin/plugins/win32/winprefs/gtkappbar.h 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/win32/winprefs/gtkappbar.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,59 +0,0 @@
--/*
-- * purple - WinPurple Options Plugin
-- *
-- * File: gtkappbar.h
-- * Date: August 2, 2003
-- * Description: Appbar functionality for Windows GTK+ applications
-- *
-- * Copyright (C) 2003, Herman Bloggs <hermanator12002@yahoo.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--#ifndef _GTKAPPBAR_H_
--#define _GTKAPPBAR_H_
--
--#include <glib.h>
--#include <gtk/gtk.h>
--
--typedef struct {
-- GtkWidget *win;
-- /** The rectangle of the screen area used for docking */
-- RECT docked_rect;
-- /** The height of the window prior to docking */
-- UINT undocked_height;
-- /** The side of the screen to which the window is docked*/
-- UINT side;
-- /** Is the window currently docked? */
-- gboolean docked;
-- /** Is the window currently in the process of docking? */
-- gboolean docking;
-- gboolean undocking;
-- /** Is the window currently registered as an appbar */
-- gboolean registered;
-- /** Callback functions to notify of dock state change */
-- GSList *dock_cbs;
-- /** Is the window currently iconized? */
-- gboolean iconized;
--} GtkAppBar;
--
--typedef void (*GtkAppBarDockCB)(gboolean);
--
--GtkAppBar *gtk_appbar_add(GtkWidget *win);
--void gtk_appbar_remove(GtkAppBar *ab);
--void gtk_appbar_dock(GtkAppBar *ab, UINT side);
--void gtk_appbar_add_dock_cb(GtkAppBar *ab, GtkAppBarDockCB dock_cb);
--
--#endif /* _GTKAPPBAR_H_ */
-diff -Nur pidgin-2.10.7/pidgin/plugins/win32/winprefs/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/plugins/win32/winprefs/Makefile.mingw
---- pidgin-2.10.7/pidgin/plugins/win32/winprefs/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/win32/winprefs/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,82 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for winprefs plugin.
--#
--
--PIDGIN_TREE_TOP := ../../../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--TARGET = winprefs
--DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES))
--DEFINES += -DWINVER=0x500
--
--##
--## INCLUDE PATHS
--##
--INCLUDE_PATHS += -I. \
-- -I$(GTK_TOP)/include \
-- -I$(GTK_TOP)/include/gtk-2.0 \
-- -I$(GTK_TOP)/include/glib-2.0 \
-- -I$(GTK_TOP)/include/pango-1.0 \
-- -I$(GTK_TOP)/include/atk-1.0 \
-- -I$(GTK_TOP)/include/cairo \
-- -I$(GTK_TOP)/lib/glib-2.0/include \
-- -I$(GTK_TOP)/lib/gtk-2.0/include \
-- -I$(PURPLE_TOP) \
-- -I$(PURPLE_TOP)/win32 \
-- -I$(PIDGIN_TOP) \
-- -I$(PIDGIN_TOP)/win32 \
-- -I$(PIDGIN_TREE_TOP)
--
--LIB_PATHS += -L$(GTK_TOP)/lib \
-- -L$(PURPLE_TOP) \
-- -L$(PIDGIN_TOP)
--
--##
--## SOURCES, OBJECTS
--##
--C_SRC = winprefs.c \
-- gtkappbar.c
--
--OBJECTS = $(C_SRC:%.c=%.o)
--
--##
--## LIBRARIES
--##
--LIBS = -lgtk-win32-2.0 \
-- -lglib-2.0 \
-- -lgdk-win32-2.0 \
-- -lgmodule-2.0 \
-- -lgobject-2.0 \
-- -lws2_32 \
-- -lintl \
-- -lpurple \
-- -lpidgin
--
--include $(PIDGIN_COMMON_RULES)
--
--##
--## TARGET DEFINITIONS
--##
--.PHONY: all install clean
--
--all: $(TARGET).dll
--
--install: $(TARGET).dll $(PIDGIN_INSTALL_PLUGINS_DIR)
-- cp $(TARGET).dll $(PIDGIN_INSTALL_PLUGINS_DIR)
--
--##
--## BUILD DLL
--##
--$(TARGET).dll: $(PURPLE_DLL).a $(PIDGIN_DLL).a $(OBJECTS)
-- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
--
--##
--## CLEAN RULES
--##
--clean:
-- rm -rf $(OBJECTS)
-- rm -rf $(TARGET).dll
--
--include $(PIDGIN_COMMON_TARGETS)
-diff -Nur pidgin-2.10.7/pidgin/plugins/win32/winprefs/winprefs.c pidgin-2.10.7-nonprism/pidgin/plugins/win32/winprefs/winprefs.c
---- pidgin-2.10.7/pidgin/plugins/win32/winprefs/winprefs.c 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/plugins/win32/winprefs/winprefs.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,391 +0,0 @@
--/*
-- * pidgin - Windows Pidgin Options Plugin
-- *
-- * Pidgin is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--#include <gtk/gtk.h>
--#include <gdk/gdkwin32.h>
--
--#include "internal.h"
--
--#include "gtkwin32dep.h"
--
--#include "core.h"
--#include "debug.h"
--#include "prefs.h"
--#include "signals.h"
--#include "version.h"
--
--#include "gtkappbar.h"
--#include "gtkblist.h"
--#include "gtkconv.h"
--#include "gtkplugin.h"
--#include "gtkprefs.h"
--#include "gtkutils.h"
--
--/*
-- * MACROS & DEFINES
-- */
--#define WINPREFS_PLUGIN_ID "gtk-win-prefs"
--
--#define RUNKEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"
--
--/*
-- * LOCALS
-- */
--static const char *PREF_DBLIST_DOCKABLE = "/plugins/gtk/win32/winprefs/dblist_dockable";
--static const char *PREF_DBLIST_DOCKED = "/plugins/gtk/win32/winprefs/dblist_docked";
--static const char *PREF_DBLIST_HEIGHT = "/plugins/gtk/win32/winprefs/dblist_height";
--static const char *PREF_DBLIST_SIDE = "/plugins/gtk/win32/winprefs/dblist_side";
--static const char *PREF_BLIST_ON_TOP = "/plugins/gtk/win32/winprefs/blist_on_top";
--/* Deprecated */
--static const char *PREF_CHAT_BLINK = "/plugins/gtk/win32/winprefs/chat_blink";
--static const char *PREF_DBLIST_ON_TOP = "/plugins/gtk/win32/winprefs/dblist_on_top";
--
--static PurplePlugin *handle = NULL;
--static GtkAppBar *blist_ab = NULL;
--static GtkWidget *blist = NULL;
--static guint blist_visible_cb_id = 0;
--
--enum {
-- BLIST_TOP_NEVER = 0,
-- BLIST_TOP_ALWAYS,
-- BLIST_TOP_DOCKED,
--};
--
--/*
-- * CODE
-- */
--
--/* BLIST DOCKING */
--
--static void blist_save_state() {
-- if(blist_ab) {
-- if(purple_prefs_get_bool(PREF_DBLIST_DOCKABLE) && blist_ab->docked) {
-- purple_prefs_set_int(PREF_DBLIST_HEIGHT, blist_ab->undocked_height);
-- purple_prefs_set_int(PREF_DBLIST_SIDE, blist_ab->side);
-- purple_prefs_set_bool(PREF_DBLIST_DOCKED, blist_ab->docked);
-- } else
-- purple_prefs_set_bool(PREF_DBLIST_DOCKED, FALSE);
-- }
--}
--
--static void blist_set_ontop(gboolean val) {
-- if(!blist)
-- return;
--
-- gtk_window_set_keep_above(GTK_WINDOW(PIDGIN_BLIST(purple_get_blist())->window), val);
--}
--
--static void blist_dock_cb(gboolean val) {
-- if(val) {
-- purple_debug_info(WINPREFS_PLUGIN_ID, "Blist Docking...\n");
-- if(purple_prefs_get_int(PREF_BLIST_ON_TOP) != BLIST_TOP_NEVER)
-- blist_set_ontop(TRUE);
-- } else {
-- purple_debug_info(WINPREFS_PLUGIN_ID, "Blist Undocking...\n");
-- blist_set_ontop(purple_prefs_get_int(PREF_BLIST_ON_TOP) == BLIST_TOP_ALWAYS);
-- }
--}
--
--static void blist_set_dockable(gboolean val) {
-- if(val) {
-- if(blist_ab == NULL && blist != NULL) {
-- blist_ab = gtk_appbar_add(blist);
-- gtk_appbar_add_dock_cb(blist_ab, blist_dock_cb);
-- }
-- } else {
-- if(blist_ab != NULL) {
-- gtk_appbar_remove(blist_ab);
-- blist_ab = NULL;
-- }
--
-- blist_set_ontop(purple_prefs_get_int(PREF_BLIST_ON_TOP) == BLIST_TOP_ALWAYS);
-- }
--}
--
--/* PLUGIN CALLBACKS */
--
--/* We need this because the blist destroy cb won't be called before the
-- plugin is unloaded, when quitting */
--static void purple_quit_cb() {
-- purple_debug_info(WINPREFS_PLUGIN_ID, "purple_quit_cb: removing appbar\n");
-- blist_save_state();
-- blist_set_dockable(FALSE);
--}
--
--/* Listen for the first time the window stops being withdrawn */
--static void blist_visible_cb(const char *pref, PurplePrefType type,
-- gconstpointer value, gpointer user_data) {
-- if(purple_prefs_get_bool(pref)) {
-- gtk_appbar_dock(blist_ab,
-- purple_prefs_get_int(PREF_DBLIST_SIDE));
--
-- if(purple_prefs_get_int(PREF_BLIST_ON_TOP)
-- == BLIST_TOP_DOCKED)
-- blist_set_ontop(TRUE);
--
-- /* We only need to be notified about this once */
-- purple_prefs_disconnect_callback(blist_visible_cb_id);
-- }
--}
--
--/* This needs to be delayed otherwise, when the blist is originally created and
-- * hidden, it'll trigger the blist_visible_cb */
--static gboolean listen_for_blist_visible_cb(gpointer data) {
-- if (handle != NULL)
-- blist_visible_cb_id =
-- purple_prefs_connect_callback(handle,
-- PIDGIN_PREFS_ROOT "/blist/list_visible",
-- blist_visible_cb, NULL);
--
-- return FALSE;
--}
--
--static void blist_create_cb(PurpleBuddyList *purple_blist, void *data) {
-- purple_debug_info(WINPREFS_PLUGIN_ID, "buddy list created\n");
--
-- blist = PIDGIN_BLIST(purple_blist)->window;
--
-- if(purple_prefs_get_bool(PREF_DBLIST_DOCKABLE)) {
-- blist_set_dockable(TRUE);
-- if(purple_prefs_get_bool(PREF_DBLIST_DOCKED)) {
-- blist_ab->undocked_height = purple_prefs_get_int(PREF_DBLIST_HEIGHT);
-- if(!(gdk_window_get_state(blist->window)
-- & GDK_WINDOW_STATE_WITHDRAWN)) {
-- gtk_appbar_dock(blist_ab,
-- purple_prefs_get_int(PREF_DBLIST_SIDE));
-- if(purple_prefs_get_int(PREF_BLIST_ON_TOP)
-- == BLIST_TOP_DOCKED)
-- blist_set_ontop(TRUE);
-- } else {
-- g_idle_add(listen_for_blist_visible_cb, NULL);
-- }
-- }
-- }
--
-- if(purple_prefs_get_int(PREF_BLIST_ON_TOP) == BLIST_TOP_ALWAYS)
-- blist_set_ontop(TRUE);
--
--}
--
--/* WIN PREFS GENERAL */
--
--static void
--winprefs_set_autostart(GtkWidget *w) {
-- char *runval = NULL;
--
-- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
-- runval = g_strdup_printf("\"%s" G_DIR_SEPARATOR_S "pidgin.exe\"", wpurple_install_dir());
--
-- if(!wpurple_write_reg_string(HKEY_CURRENT_USER, RUNKEY, "Pidgin", runval)
-- /* For Win98 */
-- && !wpurple_write_reg_string(HKEY_LOCAL_MACHINE, RUNKEY, "Pidgin", runval))
-- purple_debug_error(WINPREFS_PLUGIN_ID, "Could not set registry key value\n");
--
-- g_free(runval);
--}
--
--static void
--winprefs_set_multiple_instances(GtkWidget *w) {
-- wpurple_write_reg_string(HKEY_CURRENT_USER, "Environment", "PIDGIN_MULTI_INST",
-- gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)) ? "1" : NULL);
--}
--
--static void
--winprefs_set_blist_dockable(const char *pref, PurplePrefType type,
-- gconstpointer value, gpointer user_data)
--{
-- blist_set_dockable(GPOINTER_TO_INT(value));
--}
--
--static void
--winprefs_set_blist_ontop(const char *pref, PurplePrefType type,
-- gconstpointer value, gpointer user_data)
--{
-- gint setting = purple_prefs_get_int(PREF_BLIST_ON_TOP);
-- if((setting == BLIST_TOP_DOCKED && blist_ab && blist_ab->docked)
-- || setting == BLIST_TOP_ALWAYS)
-- blist_set_ontop(TRUE);
-- else
-- blist_set_ontop(FALSE);
--}
--
--/*
-- * EXPORTED FUNCTIONS
-- */
--
--static gboolean plugin_load(PurplePlugin *plugin) {
-- handle = plugin;
--
-- /* blist docking init */
-- if(purple_get_blist() && PIDGIN_BLIST(purple_get_blist())
-- && PIDGIN_BLIST(purple_get_blist())->window) {
-- blist_create_cb(purple_get_blist(), NULL);
-- }
--
-- /* This really shouldn't happen anymore generally, but if for some strange
-- reason, the blist is recreated, we need to set it up again. */
-- purple_signal_connect(pidgin_blist_get_handle(), "gtkblist-created",
-- plugin, PURPLE_CALLBACK(blist_create_cb), NULL);
--
-- purple_signal_connect((void*)purple_get_core(), "quitting", plugin,
-- PURPLE_CALLBACK(purple_quit_cb), NULL);
--
-- purple_prefs_connect_callback(handle, PREF_BLIST_ON_TOP,
-- winprefs_set_blist_ontop, NULL);
-- purple_prefs_connect_callback(handle, PREF_DBLIST_DOCKABLE,
-- winprefs_set_blist_dockable, NULL);
--
-- return TRUE;
--}
--
--static gboolean plugin_unload(PurplePlugin *plugin) {
-- blist_set_dockable(FALSE);
-- blist_set_ontop(FALSE);
--
-- handle = NULL;
--
-- return TRUE;
--}
--
--static GtkWidget* get_config_frame(PurplePlugin *plugin) {
-- GtkWidget *ret;
-- GtkWidget *vbox;
-- GtkWidget *button;
-- char *run_key_val;
-- char *tmp;
--
-- ret = gtk_vbox_new(FALSE, 18);
-- gtk_container_set_border_width(GTK_CONTAINER(ret), 12);
--
-- /* Autostart */
-- vbox = pidgin_make_frame(ret, _("Startup"));
-- tmp = g_strdup_printf(_("_Start %s on Windows startup"), PIDGIN_NAME);
-- button = gtk_check_button_new_with_mnemonic(tmp);
-- g_free(tmp);
-- gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
-- if ((run_key_val = wpurple_read_reg_string(HKEY_CURRENT_USER, RUNKEY, "Pidgin"))
-- || (run_key_val = wpurple_read_reg_string(HKEY_LOCAL_MACHINE, RUNKEY, "Pidgin"))) {
-- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
-- g_free(run_key_val);
-- }
-- g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(winprefs_set_autostart), NULL);
-- gtk_widget_show(button);
--
-- button = gtk_check_button_new_with_mnemonic(_("Allow multiple instances"));
-- gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
-- if ((run_key_val = wpurple_read_reg_string(HKEY_CURRENT_USER, "Environment", "PIDGIN_MULTI_INST"))) {
-- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
-- g_free(run_key_val);
-- }
-- g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(winprefs_set_multiple_instances), NULL);
-- gtk_widget_show(button);
--
-- /* Buddy List */
-- vbox = pidgin_make_frame(ret, _("Buddy List"));
-- pidgin_prefs_checkbox(_("_Dockable Buddy List"),
-- PREF_DBLIST_DOCKABLE, vbox);
--
-- /* Blist On Top */
-- pidgin_prefs_dropdown(vbox, _("_Keep Buddy List window on top:"),
-- PURPLE_PREF_INT, PREF_BLIST_ON_TOP,
-- _("Never"), BLIST_TOP_NEVER,
-- _("Always"), BLIST_TOP_ALWAYS,
-- /* XXX: Did this ever work? */
-- _("Only when docked"), BLIST_TOP_DOCKED,
-- NULL);
--
-- gtk_widget_show_all(ret);
-- return ret;
--}
--
--static PidginPluginUiInfo ui_info =
--{
-- get_config_frame,
-- 0,
--
-- /* padding */
-- NULL,
-- NULL,
-- NULL,
-- NULL
--};
--
--static PurplePluginInfo info =
--{
-- PURPLE_PLUGIN_MAGIC,
-- PURPLE_MAJOR_VERSION,
-- PURPLE_MINOR_VERSION,
-- PURPLE_PLUGIN_STANDARD,
-- PIDGIN_PLUGIN_TYPE,
-- 0,
-- NULL,
-- PURPLE_PRIORITY_DEFAULT,
-- WINPREFS_PLUGIN_ID,
-- N_("Windows Pidgin Options"),
-- DISPLAY_VERSION,
-- N_("Options specific to Pidgin for Windows."),
-- N_("Provides options specific to Pidgin for Windows, such as buddy list docking."),
-- "Herman Bloggs <hermanator12002@yahoo.com>",
-- PURPLE_WEBSITE,
-- plugin_load,
-- plugin_unload,
-- NULL,
-- &ui_info,
-- NULL,
-- NULL,
-- NULL,
--
-- /* padding */
-- NULL,
-- NULL,
-- NULL,
-- NULL
--};
--
--static void
--init_plugin(PurplePlugin *plugin)
--{
-- purple_prefs_add_none("/plugins/gtk");
-- purple_prefs_add_none("/plugins/gtk/win32");
-- purple_prefs_add_none("/plugins/gtk/win32/winprefs");
-- purple_prefs_add_bool(PREF_DBLIST_DOCKABLE, FALSE);
-- purple_prefs_add_bool(PREF_DBLIST_DOCKED, FALSE);
-- purple_prefs_add_int(PREF_DBLIST_HEIGHT, 0);
-- purple_prefs_add_int(PREF_DBLIST_SIDE, 0);
--
-- /* Convert old preferences */
-- if(purple_prefs_exists(PREF_DBLIST_ON_TOP)) {
-- gint blist_top = BLIST_TOP_NEVER;
-- if(purple_prefs_get_bool(PREF_BLIST_ON_TOP))
-- blist_top = BLIST_TOP_ALWAYS;
-- else if(purple_prefs_get_bool(PREF_DBLIST_ON_TOP))
-- blist_top = BLIST_TOP_DOCKED;
-- purple_prefs_remove(PREF_BLIST_ON_TOP);
-- purple_prefs_remove(PREF_DBLIST_ON_TOP);
-- purple_prefs_add_int(PREF_BLIST_ON_TOP, blist_top);
-- } else
-- purple_prefs_add_int(PREF_BLIST_ON_TOP, BLIST_TOP_NEVER);
-- purple_prefs_remove(PREF_CHAT_BLINK);
--}
--
--PURPLE_INIT_PLUGIN(winprefs, init_plugin, info)
--
-diff -Nur pidgin-2.10.7/pidgin/win32/gtkdocklet-win32.c pidgin-2.10.7-nonprism/pidgin/win32/gtkdocklet-win32.c
---- pidgin-2.10.7/pidgin/win32/gtkdocklet-win32.c 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/gtkdocklet-win32.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,671 +0,0 @@
--/*
-- * System tray icon (aka docklet) plugin for Winpidgin
-- *
-- * Copyright (C) 2002-3 Robert McQueen <robot101@debian.org>
-- * Copyright (C) 2003 Herman Bloggs <hermanator12002@yahoo.com>
-- * Inspired by a similar plugin by:
-- * John (J5) Palmieri <johnp@martianrock.com>
-- *
-- * This program is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU General Public License as
-- * published by the Free Software Foundation; either version 2 of the
-- * License, or (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful, but
-- * WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- * General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-- * 02111-1301, USA.
-- */
--#define _WIN32_IE 0x0500
--#include <windows.h>
--#include <gdk/gdkwin32.h>
--#include <gdk/gdk.h>
--
--#include "internal.h"
--#include "gtkblist.h"
--#include "debug.h"
--
--#include "resource.h"
--#include "MinimizeToTray.h"
--#include "gtkwin32dep.h"
--#include "gtkdocklet.h"
--#include "pidginstock.h"
--
--/*
-- * DEFINES, MACROS & DATA TYPES
-- */
--#define WM_TRAYMESSAGE WM_USER /* User defined WM Message */
--
--/*
-- * LOCALS
-- */
--static HWND systray_hwnd = NULL;
--/* additional two cached_icons entries for pending and connecting icons */
--static HICON cached_icons[PURPLE_STATUS_NUM_PRIMITIVES + 2];
--static GtkWidget *image = NULL;
--/* This is used to trigger click events on so they appear to GTK+ as if they are triggered by input */
--static GtkWidget *dummy_button = NULL;
--static GtkWidget *dummy_window = NULL;
--static NOTIFYICONDATAW _nicon_data;
--
--static gboolean dummy_button_cb(GtkWidget *widget, GdkEventButton *event, gpointer user_data) {
-- pidgin_docklet_clicked(event->button);
-- return TRUE;
--}
--
--static LRESULT CALLBACK systray_mainmsg_handler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
-- static UINT taskbarRestartMsg; /* static here means value is kept across multiple calls to this func */
--
-- switch(msg) {
-- case WM_CREATE:
-- purple_debug_info("docklet", "WM_CREATE\n");
-- taskbarRestartMsg = RegisterWindowMessageW(L"TaskbarCreated");
-- break;
--
-- case WM_TIMER:
-- purple_debug_info("docklet", "WM_TIMER\n");
-- break;
--
-- case WM_DESTROY:
-- purple_debug_info("docklet", "WM_DESTROY\n");
-- break;
--
-- case WM_TRAYMESSAGE:
-- {
-- int type = 0;
-- GdkEvent *event;
-- GdkEventButton *event_btn;
--
-- /* We'll use Double Click - Single click over on linux */
-- if(lparam == WM_LBUTTONDBLCLK)
-- type = 1;
-- else if(lparam == WM_MBUTTONUP)
-- type = 2;
-- else if(lparam == WM_RBUTTONUP)
-- type = 3;
-- else
-- break;
--
-- gtk_widget_show_all(dummy_window);
-- event = gdk_event_new(GDK_BUTTON_PRESS);
-- event_btn = (GdkEventButton *) event;
-- event_btn->window = g_object_ref (gdk_get_default_root_window());
-- event_btn->send_event = TRUE;
-- event_btn->time = GetTickCount();
-- event_btn->axes = NULL;
-- event_btn->state = 0;
-- event_btn->button = type;
-- event_btn->device = gdk_display_get_default ()->core_pointer;
-- event->any.window = g_object_ref(dummy_window->window);
-- gdk_window_set_user_data(event->any.window, dummy_button);
--
-- gtk_main_do_event((GdkEvent *)event);
-- gtk_widget_hide(dummy_window);
-- gdk_event_free((GdkEvent *)event);
--
-- break;
-- }
-- default:
-- if (msg == taskbarRestartMsg) {
-- /* explorer crashed and left us hanging...
-- This will put the systray icon back in it's place, when it restarts */
-- Shell_NotifyIconW(NIM_ADD, &_nicon_data);
-- }
-- break;
-- }/* end switch */
--
-- return DefWindowProc(hwnd, msg, wparam, lparam);
--}
--
--/* Create hidden window to process systray messages */
--static HWND systray_create_hiddenwin() {
-- WNDCLASSEXW wcex;
-- wchar_t *wname;
--
-- wname = L"WinpidginSystrayWinCls";
--
-- wcex.cbSize = sizeof(wcex);
-- wcex.style = 0;
-- wcex.lpfnWndProc = systray_mainmsg_handler;
-- wcex.cbClsExtra = 0;
-- wcex.cbWndExtra = 0;
-- wcex.hInstance = winpidgin_exe_hinstance();
-- wcex.hIcon = NULL;
-- wcex.hCursor = NULL,
-- wcex.hbrBackground = NULL;
-- wcex.lpszMenuName = NULL;
-- wcex.lpszClassName = wname;
-- wcex.hIconSm = NULL;
--
-- RegisterClassExW(&wcex);
--
-- /* Create the window */
-- return (CreateWindowW(wname, L"", 0, 0, 0, 0, 0, GetDesktopWindow(), NULL, winpidgin_exe_hinstance(), 0));
--}
--
--static void systray_init_icon(HWND hWnd) {
-- wchar_t *w;
-- ZeroMemory(&_nicon_data, sizeof(_nicon_data));
-- _nicon_data.cbSize = sizeof(NOTIFYICONDATAW);
-- _nicon_data.hWnd = hWnd;
-- _nicon_data.uID = 0;
-- _nicon_data.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
-- _nicon_data.uCallbackMessage = WM_TRAYMESSAGE;
-- _nicon_data.hIcon = NULL;
-- w = g_utf8_to_utf16(PIDGIN_NAME, -1, NULL, NULL, NULL);
-- wcsncpy(_nicon_data.szTip, w, sizeof(_nicon_data.szTip) / sizeof(wchar_t));
-- g_free(w);
-- Shell_NotifyIconW(NIM_ADD, &_nicon_data);
-- pidgin_docklet_embedded();
--}
--
--/* This is ganked from GTK+.
-- * When we can use GTK+ 2.10 and the GtkStatusIcon stuff, this will no longer be necesary */
--#define WIN32_GDI_FAILED(api) printf("GDI FAILED %s\n", api)
--
--static gboolean
--_gdk_win32_pixbuf_to_hicon_supports_alpha (void)
--{
-- static gboolean is_win_xp=FALSE, is_win_xp_checked=FALSE;
--
-- if (!is_win_xp_checked)
-- {
-- is_win_xp_checked = TRUE;
--
-- if (!G_WIN32_IS_NT_BASED ())
-- is_win_xp = FALSE;
-- else
-- {
-- OSVERSIONINFO version;
--
-- memset (&version, 0, sizeof (version));
-- version.dwOSVersionInfoSize = sizeof (version);
-- is_win_xp = GetVersionEx (&version)
-- && version.dwPlatformId == VER_PLATFORM_WIN32_NT
-- && (version.dwMajorVersion > 5
-- || (version.dwMajorVersion == 5 && version.dwMinorVersion >= 1));
-- }
-- }
-- return is_win_xp;
--}
--
--static HBITMAP
--create_alpha_bitmap (gint size,
-- guchar **outdata)
--{
-- BITMAPV5HEADER bi;
-- HDC hdc;
-- HBITMAP hBitmap;
--
-- ZeroMemory (&bi, sizeof (BITMAPV5HEADER));
-- bi.bV5Size = sizeof (BITMAPV5HEADER);
-- bi.bV5Height = bi.bV5Width = size;
-- bi.bV5Planes = 1;
-- bi.bV5BitCount = 32;
-- bi.bV5Compression = BI_BITFIELDS;
-- /* The following mask specification specifies a supported 32 BPP
-- * alpha format for Windows XP (BGRA format).
-- */
-- bi.bV5RedMask = 0x00FF0000;
-- bi.bV5GreenMask = 0x0000FF00;
-- bi.bV5BlueMask = 0x000000FF;
-- bi.bV5AlphaMask = 0xFF000000;
--
-- /* Create the DIB section with an alpha channel. */
-- hdc = GetDC (NULL);
-- if (!hdc)
-- {
-- WIN32_GDI_FAILED ("GetDC");
-- return NULL;
-- }
-- hBitmap = CreateDIBSection (hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS,
-- (PVOID *) outdata, NULL, (DWORD)0);
-- if (hBitmap == NULL)
-- WIN32_GDI_FAILED ("CreateDIBSection");
-- ReleaseDC (NULL, hdc);
--
-- return hBitmap;
--}
--
--static HBITMAP
--create_color_bitmap (gint size,
-- guchar **outdata,
-- gint bits)
--{
-- struct {
-- BITMAPV4HEADER bmiHeader;
-- RGBQUAD bmiColors[2];
-- } bmi;
-- HDC hdc;
-- HBITMAP hBitmap;
--
-- ZeroMemory (&bmi, sizeof (bmi));
-- bmi.bmiHeader.bV4Size = sizeof (BITMAPV4HEADER);
-- bmi.bmiHeader.bV4Height = bmi.bmiHeader.bV4Width = size;
-- bmi.bmiHeader.bV4Planes = 1;
-- bmi.bmiHeader.bV4BitCount = bits;
-- bmi.bmiHeader.bV4V4Compression = BI_RGB;
--
-- /* when bits is 1, these will be used.
-- * bmiColors[0] already zeroed from ZeroMemory()
-- */
-- bmi.bmiColors[1].rgbBlue = 0xFF;
-- bmi.bmiColors[1].rgbGreen = 0xFF;
-- bmi.bmiColors[1].rgbRed = 0xFF;
--
-- hdc = GetDC (NULL);
-- if (!hdc)
-- {
-- WIN32_GDI_FAILED ("GetDC");
-- return NULL;
-- }
-- hBitmap = CreateDIBSection (hdc, (BITMAPINFO *)&bmi, DIB_RGB_COLORS,
-- (PVOID *) outdata, NULL, (DWORD)0);
-- if (hBitmap == NULL)
-- WIN32_GDI_FAILED ("CreateDIBSection");
-- ReleaseDC (NULL, hdc);
--
-- return hBitmap;
--}
--
--static gboolean
--pixbuf_to_hbitmaps_alpha_winxp (GdkPixbuf *pixbuf,
-- HBITMAP *color,
-- HBITMAP *mask)
--{
-- /* Based on code from
-- * http://www.dotnet247.com/247reference/msgs/13/66301.aspx
-- */
-- HBITMAP hColorBitmap, hMaskBitmap;
-- guchar *indata, *inrow;
-- guchar *colordata, *colorrow, *maskdata, *maskbyte;
-- gint width, height, size, i, i_offset, j, j_offset, rowstride;
-- guint maskstride, mask_bit;
--
-- width = gdk_pixbuf_get_width (pixbuf); /* width of icon */
-- height = gdk_pixbuf_get_height (pixbuf); /* height of icon */
--
-- /* The bitmaps are created square */
-- size = MAX (width, height);
--
-- hColorBitmap = create_alpha_bitmap (size, &colordata);
-- if (!hColorBitmap)
-- return FALSE;
-- hMaskBitmap = create_color_bitmap (size, &maskdata, 1);
-- if (!hMaskBitmap)
-- {
-- DeleteObject (hColorBitmap);
-- return FALSE;
-- }
--
-- /* MSDN says mask rows are aligned to "LONG" boundaries */
-- maskstride = (((size + 31) & ~31) >> 3);
--
-- indata = gdk_pixbuf_get_pixels (pixbuf);
-- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
--
-- if (width > height)
-- {
-- i_offset = 0;
-- j_offset = (width - height) / 2;
-- }
-- else
-- {
-- i_offset = (height - width) / 2;
-- j_offset = 0;
-- }
--
-- for (j = 0; j < height; j++)
-- {
-- colorrow = colordata + 4*(j+j_offset)*size + 4*i_offset;
-- maskbyte = maskdata + (j+j_offset)*maskstride + i_offset/8;
-- mask_bit = (0x80 >> (i_offset % 8));
-- inrow = indata + (height-j-1)*rowstride;
-- for (i = 0; i < width; i++)
-- {
-- colorrow[4*i+0] = inrow[4*i+2];
-- colorrow[4*i+1] = inrow[4*i+1];
-- colorrow[4*i+2] = inrow[4*i+0];
-- colorrow[4*i+3] = inrow[4*i+3];
-- if (inrow[4*i+3] == 0)
-- maskbyte[0] |= mask_bit; /* turn ON bit */
-- else
-- maskbyte[0] &= ~mask_bit; /* turn OFF bit */
-- mask_bit >>= 1;
-- if (mask_bit == 0)
-- {
-- mask_bit = 0x80;
-- maskbyte++;
-- }
-- }
-- }
--
-- *color = hColorBitmap;
-- *mask = hMaskBitmap;
--
-- return TRUE;
--}
--
--static gboolean
--pixbuf_to_hbitmaps_normal (GdkPixbuf *pixbuf,
-- HBITMAP *color,
-- HBITMAP *mask)
--{
-- /* Based on code from
-- * http://www.dotnet247.com/247reference/msgs/13/66301.aspx
-- */
-- HBITMAP hColorBitmap, hMaskBitmap;
-- guchar *indata, *inrow;
-- guchar *colordata, *colorrow, *maskdata, *maskbyte;
-- gint width, height, size, i, i_offset, j, j_offset, rowstride, nc, bmstride;
-- gboolean has_alpha;
-- guint maskstride, mask_bit;
--
-- width = gdk_pixbuf_get_width (pixbuf); /* width of icon */
-- height = gdk_pixbuf_get_height (pixbuf); /* height of icon */
--
-- /* The bitmaps are created square */
-- size = MAX (width, height);
--
-- hColorBitmap = create_color_bitmap (size, &colordata, 24);
-- if (!hColorBitmap)
-- return FALSE;
-- hMaskBitmap = create_color_bitmap (size, &maskdata, 1);
-- if (!hMaskBitmap)
-- {
-- DeleteObject (hColorBitmap);
-- return FALSE;
-- }
--
-- /* rows are always aligned on 4-byte boundarys */
-- bmstride = size * 3;
-- if (bmstride % 4 != 0)
-- bmstride += 4 - (bmstride % 4);
--
-- /* MSDN says mask rows are aligned to "LONG" boundaries */
-- maskstride = (((size + 31) & ~31) >> 3);
--
-- indata = gdk_pixbuf_get_pixels (pixbuf);
-- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
-- nc = gdk_pixbuf_get_n_channels (pixbuf);
-- has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
--
-- if (width > height)
-- {
-- i_offset = 0;
-- j_offset = (width - height) / 2;
-- }
-- else
-- {
-- i_offset = (height - width) / 2;
-- j_offset = 0;
-- }
--
-- for (j = 0; j < height; j++)
-- {
-- colorrow = colordata + (j+j_offset)*bmstride + 3*i_offset;
-- maskbyte = maskdata + (j+j_offset)*maskstride + i_offset/8;
-- mask_bit = (0x80 >> (i_offset % 8));
-- inrow = indata + (height-j-1)*rowstride;
-- for (i = 0; i < width; i++)
-- {
-- if (has_alpha && inrow[nc*i+3] < 128)
-- {
-- colorrow[3*i+0] = colorrow[3*i+1] = colorrow[3*i+2] = 0;
-- maskbyte[0] |= mask_bit; /* turn ON bit */
-- }
-- else
-- {
-- colorrow[3*i+0] = inrow[nc*i+2];
-- colorrow[3*i+1] = inrow[nc*i+1];
-- colorrow[3*i+2] = inrow[nc*i+0];
-- maskbyte[0] &= ~mask_bit; /* turn OFF bit */
-- }
-- mask_bit >>= 1;
-- if (mask_bit == 0)
-- {
-- mask_bit = 0x80;
-- maskbyte++;
-- }
-- }
-- }
--
-- *color = hColorBitmap;
-- *mask = hMaskBitmap;
--
-- return TRUE;
--}
--
--static HICON
--pixbuf_to_hicon (GdkPixbuf *pixbuf)
--{
-- gint x = 0, y = 0;
-- gboolean is_icon = TRUE;
-- ICONINFO ii;
-- HICON icon;
-- gboolean success;
--
-- if (pixbuf == NULL)
-- return NULL;
--
-- if (_gdk_win32_pixbuf_to_hicon_supports_alpha() && gdk_pixbuf_get_has_alpha (pixbuf))
-- success = pixbuf_to_hbitmaps_alpha_winxp (pixbuf, &ii.hbmColor, &ii.hbmMask);
-- else
-- success = pixbuf_to_hbitmaps_normal (pixbuf, &ii.hbmColor, &ii.hbmMask);
--
-- if (!success)
-- return NULL;
--
-- ii.fIcon = is_icon;
-- ii.xHotspot = x;
-- ii.yHotspot = y;
-- icon = CreateIconIndirect (&ii);
-- DeleteObject (ii.hbmColor);
-- DeleteObject (ii.hbmMask);
-- return icon;
--}
--
--static HICON load_hicon_from_stock(const char *stock) {
-- HICON hicon = NULL;
-- GdkPixbuf *pixbuf = gtk_widget_render_icon(image, stock,
-- gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL), NULL);
--
-- if (pixbuf) {
-- hicon = pixbuf_to_hicon(pixbuf);
-- g_object_unref(pixbuf);
-- } else
-- purple_debug_error("docklet", "Unable to load pixbuf for %s.\n", stock);
--
-- return hicon;
--}
--
--
--static void systray_change_icon(HICON hicon) {
-- g_return_if_fail(hicon != NULL);
--
-- _nicon_data.hIcon = hicon;
-- Shell_NotifyIconW(NIM_MODIFY, &_nicon_data);
--}
--
--static void systray_remove_nid(void) {
-- Shell_NotifyIconW(NIM_DELETE, &_nicon_data);
--}
--
--static void winpidgin_tray_update_icon(PurpleStatusPrimitive status,
-- gboolean connecting, gboolean pending) {
--
-- int icon_index;
-- g_return_if_fail(image != NULL);
--
-- if(connecting)
-- icon_index = PURPLE_STATUS_NUM_PRIMITIVES;
-- else if(pending)
-- icon_index = PURPLE_STATUS_NUM_PRIMITIVES+1;
-- else
-- icon_index = status;
--
-- g_return_if_fail(icon_index < (sizeof(cached_icons) / sizeof(HICON)));
--
-- /* Look up and cache the HICON if we don't already have it */
-- if (cached_icons[icon_index] == NULL) {
-- const gchar *icon_name = NULL;
-- switch (status) {
-- case PURPLE_STATUS_OFFLINE:
-- icon_name = PIDGIN_STOCK_TRAY_OFFLINE;
-- break;
-- case PURPLE_STATUS_AWAY:
-- icon_name = PIDGIN_STOCK_TRAY_AWAY;
-- break;
-- case PURPLE_STATUS_UNAVAILABLE:
-- icon_name = PIDGIN_STOCK_TRAY_BUSY;
-- break;
-- case PURPLE_STATUS_EXTENDED_AWAY:
-- icon_name = PIDGIN_STOCK_TRAY_XA;
-- break;
-- case PURPLE_STATUS_INVISIBLE:
-- icon_name = PIDGIN_STOCK_TRAY_INVISIBLE;
-- break;
-- default:
-- icon_name = PIDGIN_STOCK_TRAY_AVAILABLE;
-- break;
-- }
--
-- if (pending)
-- icon_name = PIDGIN_STOCK_TRAY_PENDING;
-- if (connecting)
-- icon_name = PIDGIN_STOCK_TRAY_CONNECT;
--
-- g_return_if_fail(icon_name != NULL);
--
-- cached_icons[icon_index] = load_hicon_from_stock(icon_name);
-- }
--
-- systray_change_icon(cached_icons[icon_index]);
--}
--
--static void winpidgin_tray_blank_icon() {
-- _nicon_data.hIcon = NULL;
-- Shell_NotifyIconW(NIM_MODIFY, &_nicon_data);
--}
--
--static void winpidgin_tray_set_tooltip(gchar *tooltip) {
-- const char *value = tooltip;
-- wchar_t *w;
-- if (value == NULL) {
-- value = PIDGIN_NAME;
-- }
-- w = g_utf8_to_utf16(value, -1, NULL, NULL, NULL);
-- wcsncpy(_nicon_data.szTip, w, sizeof(_nicon_data.szTip) / sizeof(wchar_t));
-- g_free(w);
-- Shell_NotifyIconW(NIM_MODIFY, &_nicon_data);
--}
--
--static void winpidgin_tray_minimize(PidginBuddyList *gtkblist) {
-- MinimizeWndToTray(GDK_WINDOW_HWND(gtkblist->window->window));
--}
--
--static void winpidgin_tray_maximize(PidginBuddyList *gtkblist) {
-- RestoreWndFromTray(GDK_WINDOW_HWND(gtkblist->window->window));
--}
--
--
--static void winpidgin_tray_create() {
-- OSVERSIONINFO osinfo;
-- /* dummy window to process systray messages */
-- systray_hwnd = systray_create_hiddenwin();
--
-- dummy_window = gtk_window_new(GTK_WINDOW_POPUP);
-- dummy_button = gtk_button_new();
-- gtk_container_add(GTK_CONTAINER(dummy_window), dummy_button);
--
-- /* We trigger the click event indirectly so that gtk_get_current_event_state() is TRUE when the event is handled */
-- g_signal_connect(G_OBJECT(dummy_button), "button-press-event",
-- G_CALLBACK(dummy_button_cb), NULL);
--
-- image = gtk_image_new();
-- g_object_ref_sink(image);
--
-- osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-- GetVersionEx(&osinfo);
--
-- /* Load icons, and init systray notify icon
-- * NOTE: Windows < XP only supports displaying 4-bit images in the Systray,
-- * 2K and ME will use the highest color depth that the desktop will support,
-- * but will scale it back to 4-bits for display.
-- * That is why we use custom 4-bit icons for pre XP Windowses */
-- if (osinfo.dwMajorVersion < 5 || (osinfo.dwMajorVersion == 5 && osinfo.dwMinorVersion == 0))
-- {
-- cached_icons[PURPLE_STATUS_OFFLINE] = (HICON) LoadImage(winpidgin_dll_hinstance(),
-- MAKEINTRESOURCE(PIDGIN_TRAY_OFFLINE_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
-- cached_icons[PURPLE_STATUS_AVAILABLE] = (HICON) LoadImage(winpidgin_dll_hinstance(),
-- MAKEINTRESOURCE(PIDGIN_TRAY_AVAILABLE_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
-- cached_icons[PURPLE_STATUS_AWAY] = (HICON) LoadImage(winpidgin_dll_hinstance(),
-- MAKEINTRESOURCE(PIDGIN_TRAY_AWAY_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
-- cached_icons[PURPLE_STATUS_EXTENDED_AWAY] = (HICON) LoadImage(winpidgin_dll_hinstance(),
-- MAKEINTRESOURCE(PIDGIN_TRAY_XA_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
-- cached_icons[PURPLE_STATUS_UNAVAILABLE] = (HICON) LoadImage(winpidgin_dll_hinstance(),
-- MAKEINTRESOURCE(PIDGIN_TRAY_BUSY_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
-- cached_icons[PURPLE_STATUS_NUM_PRIMITIVES] = (HICON) LoadImage(winpidgin_dll_hinstance(),
-- MAKEINTRESOURCE(PIDGIN_TRAY_CONNECTING_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
-- cached_icons[PURPLE_STATUS_NUM_PRIMITIVES+1] = (HICON) LoadImage(winpidgin_dll_hinstance(),
-- MAKEINTRESOURCE(PIDGIN_TRAY_PENDING_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
-- cached_icons[PURPLE_STATUS_INVISIBLE] = (HICON) LoadImage(winpidgin_dll_hinstance(),
-- MAKEINTRESOURCE(PIDGIN_TRAY_INVISIBLE_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
-- }
--
-- /* Create icon in systray */
-- systray_init_icon(systray_hwnd);
--
-- purple_signal_connect(pidgin_blist_get_handle(), "gtkblist-hiding",
-- pidgin_docklet_get_handle(), PURPLE_CALLBACK(winpidgin_tray_minimize), NULL);
-- purple_signal_connect(pidgin_blist_get_handle(), "gtkblist-unhiding",
-- pidgin_docklet_get_handle(), PURPLE_CALLBACK(winpidgin_tray_maximize), NULL);
--
-- purple_debug_info("docklet", "created\n");
--}
--
--static void winpidgin_tray_destroy() {
-- int cached_cnt = sizeof(cached_icons) / sizeof(HICON);
-- systray_remove_nid();
--
-- purple_signals_disconnect_by_handle(pidgin_docklet_get_handle());
--
-- DestroyWindow(systray_hwnd);
-- pidgin_docklet_remove();
--
-- while (--cached_cnt >= 0) {
-- if (cached_icons[cached_cnt] != NULL)
-- DestroyIcon(cached_icons[cached_cnt]);
-- cached_icons[cached_cnt] = NULL;
-- }
--
-- g_object_unref(image);
-- image = NULL;
--
-- gtk_widget_destroy(dummy_window);
-- dummy_button = NULL;
-- dummy_window = NULL;
--}
--
--static struct docklet_ui_ops winpidgin_tray_ops =
--{
-- winpidgin_tray_create,
-- winpidgin_tray_destroy,
-- winpidgin_tray_update_icon,
-- winpidgin_tray_blank_icon,
-- winpidgin_tray_set_tooltip,
-- NULL
--};
--
--/* Used by docklet's plugin load func */
--void docklet_ui_init() {
-- /* Initialize the cached icons to NULL */
-- ZeroMemory(cached_icons, sizeof(cached_icons));
--
-- pidgin_docklet_set_ui_ops(&winpidgin_tray_ops);
--}
-diff -Nur pidgin-2.10.7/pidgin/win32/gtkwin32dep.c pidgin-2.10.7-nonprism/pidgin/win32/gtkwin32dep.c
---- pidgin-2.10.7/pidgin/win32/gtkwin32dep.c 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/gtkwin32dep.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,562 +0,0 @@
--/**
-- * @file gtkwin32dep.c UI Win32 Specific Functionality
-- * @ingroup win32
-- *
-- * Pidgin is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--#define _WIN32_IE 0x500
--#ifndef WINVER
--#define WINVER 0x0500 /* W2K */
--#endif
--#include <windows.h>
--#include <io.h>
--#include <stdlib.h>
--#include <stdio.h>
--#include <winuser.h>
--
--#include <glib.h>
--#include <glib/gstdio.h>
--#include <gtk/gtk.h>
--#include <gdk/gdkwin32.h>
--
--#include "internal.h"
--
--#include "debug.h"
--#include "notify.h"
--#include "network.h"
--
--#include "resource.h"
--#include "zlib.h"
--#include "untar.h"
--
--#include "gtkwin32dep.h"
--#include "win32dep.h"
--#include "gtkconv.h"
--#include "gtkconn.h"
--#include "util.h"
--#ifdef USE_GTKSPELL
--#include "wspell.h"
--#endif
--
--/*
-- * GLOBALS
-- */
--HINSTANCE exe_hInstance = 0;
--HINSTANCE dll_hInstance = 0;
--HWND messagewin_hwnd;
--static int gtkwin32_handle;
--
--static gboolean pwm_handles_connections = TRUE;
--
--
--/*
-- * PUBLIC CODE
-- */
--
--HINSTANCE winpidgin_exe_hinstance(void) {
-- return exe_hInstance;
--}
--
--HINSTANCE winpidgin_dll_hinstance(void) {
-- return dll_hInstance;
--}
--
--int winpidgin_gz_decompress(const char* in, const char* out) {
-- gzFile fin;
-- FILE *fout;
-- char buf[1024];
-- int ret;
--
-- if((fin = gzopen(in, "rb"))) {
-- if(!(fout = g_fopen(out, "wb"))) {
-- purple_debug_error("winpidgin_gz_decompress", "Error opening file: %s\n", out);
-- gzclose(fin);
-- return 0;
-- }
-- }
-- else {
-- purple_debug_error("winpidgin_gz_decompress", "gzopen failed to open: %s\n", in);
-- return 0;
-- }
--
-- while((ret = gzread(fin, buf, 1024))) {
-- if(fwrite(buf, 1, ret, fout) < ret) {
-- purple_debug_error("wpurple_gz_decompress", "Error writing %d bytes to file\n", ret);
-- gzclose(fin);
-- fclose(fout);
-- return 0;
-- }
-- }
-- fclose(fout);
-- gzclose(fin);
--
-- if(ret < 0) {
-- purple_debug_error("winpidgin_gz_decompress", "gzread failed while reading: %s\n", in);
-- return 0;
-- }
--
-- return 1;
--}
--
--int winpidgin_gz_untar(const char* filename, const char* destdir) {
-- char tmpfile[_MAX_PATH];
-- char template[]="wpidginXXXXXX";
--
-- sprintf(tmpfile, "%s%s%s", g_get_tmp_dir(), G_DIR_SEPARATOR_S, _mktemp(template));
-- if(winpidgin_gz_decompress(filename, tmpfile)) {
-- int ret;
-- if(untar(tmpfile, destdir, UNTAR_FORCE | UNTAR_QUIET))
-- ret = 1;
-- else {
-- purple_debug_error("winpidgin_gz_untar", "Failure untarring %s\n", tmpfile);
-- ret = 0;
-- }
-- g_unlink(tmpfile);
-- return ret;
-- }
-- else {
-- purple_debug_error("winpidgin_gz_untar", "Failed to gz decompress %s\n", filename);
-- return 0;
-- }
--}
--
--void winpidgin_shell_execute(const char *target, const char *verb, const char *clazz) {
--
-- SHELLEXECUTEINFOW wsinfo;
-- wchar_t *w_uri, *w_verb, *w_clazz = NULL;
--
-- g_return_if_fail(target != NULL);
-- g_return_if_fail(verb != NULL);
--
-- w_uri = g_utf8_to_utf16(target, -1, NULL, NULL, NULL);
-- w_verb = g_utf8_to_utf16(verb, -1, NULL, NULL, NULL);
--
-- memset(&wsinfo, 0, sizeof(wsinfo));
-- wsinfo.cbSize = sizeof(wsinfo);
-- wsinfo.lpVerb = w_verb;
-- wsinfo.lpFile = w_uri;
-- wsinfo.nShow = SW_SHOWNORMAL;
-- wsinfo.fMask |= SEE_MASK_FLAG_NO_UI;
-- if (clazz != NULL) {
-- w_clazz = g_utf8_to_utf16(clazz, -1, NULL, NULL, NULL);
-- wsinfo.fMask |= SEE_MASK_CLASSNAME;
-- wsinfo.lpClass = w_clazz;
-- }
--
-- if(!ShellExecuteExW(&wsinfo))
-- purple_debug_error("winpidgin", "Error opening URI: %s error: %d\n",
-- target, (int) wsinfo.hInstApp);
--
-- g_free(w_uri);
-- g_free(w_verb);
-- g_free(w_clazz);
--
--}
--
--void winpidgin_notify_uri(const char *uri) {
-- /* Allow a few commonly used and "safe" schemes to go to the specific
-- * class handlers and send everything else to the default http browser.
-- * This isn't optimal, but should cover the most common cases. I didn't
-- * see any better secure solutions when I did some research.
-- */
-- gchar *scheme = g_uri_parse_scheme(uri);
-- if (scheme && (g_ascii_strcasecmp(scheme, "https") == 0
-- || g_ascii_strcasecmp(scheme, "ftp") == 0
-- || g_ascii_strcasecmp(scheme, "mailto") == 0))
-- winpidgin_shell_execute(uri, "open", scheme);
-- else
-- winpidgin_shell_execute(uri, "open", "http");
-- g_free(scheme);
--}
--
--#define PIDGIN_WM_FOCUS_REQUEST (WM_APP + 13)
--#define PIDGIN_WM_PROTOCOL_HANDLE (WM_APP + 14)
--
--static void*
--winpidgin_netconfig_changed_cb(void *data)
--{
-- pwm_handles_connections = FALSE;
--
-- return NULL;
--}
--
--static void*
--winpidgin_get_handle(void)
--{
-- static int handle;
--
-- return &handle;
--}
--
--static gboolean
--winpidgin_pwm_reconnect()
--{
-- purple_signal_disconnect(purple_network_get_handle(), "network-configuration-changed",
-- winpidgin_get_handle(), PURPLE_CALLBACK(winpidgin_netconfig_changed_cb));
--
-- if (pwm_handles_connections == TRUE) {
-- PurpleConnectionUiOps *ui_ops = pidgin_connections_get_ui_ops();
--
-- purple_debug_info("winpidgin", "Resumed from standby, reconnecting accounts.\n");
--
-- if (ui_ops != NULL && ui_ops->network_connected != NULL)
-- ui_ops->network_connected();
-- } else {
-- purple_debug_info("winpidgin", "Resumed from standby, gtkconn will handle reconnecting.\n");
-- pwm_handles_connections = TRUE;
-- }
--
-- return FALSE;
--}
--
--static LRESULT CALLBACK message_window_handler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
--
-- if (msg == PIDGIN_WM_FOCUS_REQUEST) {
-- purple_debug_info("winpidgin", "Got external Buddy List focus request.");
-- purple_blist_set_visible(TRUE);
-- return TRUE;
-- } else if (msg == PIDGIN_WM_PROTOCOL_HANDLE) {
-- char *proto_msg = (char *) lparam;
-- purple_debug_info("winpidgin", "Got protocol handler request: %s\n", proto_msg ? proto_msg : "");
-- purple_got_protocol_handler_uri(proto_msg);
-- return TRUE;
-- } else if (msg == WM_POWERBROADCAST) {
-- if (wparam == PBT_APMQUERYSUSPEND) {
-- purple_debug_info("winpidgin", "Windows requesting permission to suspend.\n");
-- return TRUE;
-- } else if (wparam == PBT_APMSUSPEND) {
-- PurpleConnectionUiOps *ui_ops = pidgin_connections_get_ui_ops();
--
-- purple_debug_info("winpidgin", "Entering system standby, disconnecting accounts.\n");
--
-- if (ui_ops != NULL && ui_ops->network_disconnected != NULL)
-- ui_ops->network_disconnected();
--
-- purple_signal_connect(purple_network_get_handle(), "network-configuration-changed", winpidgin_get_handle(),
-- PURPLE_CALLBACK(winpidgin_netconfig_changed_cb), NULL);
--
-- return TRUE;
-- } else if (wparam == PBT_APMRESUMESUSPEND) {
-- purple_debug_info("winpidgin", "Resuming from system standby.\n");
-- /* TODO: It seems like it'd be wise to use the NLA message, if possible, instead of this. */
-- purple_timeout_add_seconds(1, winpidgin_pwm_reconnect, NULL);
-- return TRUE;
-- }
-- }
--
-- return DefWindowProc(hwnd, msg, wparam, lparam);
--}
--
--static HWND winpidgin_message_window_init(void) {
-- HWND win_hwnd;
-- WNDCLASSEX wcx;
-- LPCTSTR wname;
--
-- wname = TEXT("WinpidginMsgWinCls");
--
-- wcx.cbSize = sizeof(wcx);
-- wcx.style = 0;
-- wcx.lpfnWndProc = message_window_handler;
-- wcx.cbClsExtra = 0;
-- wcx.cbWndExtra = 0;
-- wcx.hInstance = winpidgin_exe_hinstance();
-- wcx.hIcon = NULL;
-- wcx.hCursor = NULL;
-- wcx.hbrBackground = NULL;
-- wcx.lpszMenuName = NULL;
-- wcx.lpszClassName = wname;
-- wcx.hIconSm = NULL;
--
-- RegisterClassEx(&wcx);
--
-- /* Create the window */
-- if(!(win_hwnd = CreateWindow(wname, TEXT("WinpidginMsgWin"), 0, 0, 0, 0, 0,
-- NULL, NULL, winpidgin_exe_hinstance(), 0))) {
-- purple_debug_error("winpidgin",
-- "Unable to create message window.\n");
-- return NULL;
-- }
--
-- return win_hwnd;
--}
--
--static gboolean stop_flashing(GtkWidget *widget, GdkEventFocus *event, gpointer data) {
-- GtkWindow *window = data;
-- gpointer handler_id;
--
-- winpidgin_window_flash(window, FALSE);
--
-- if ((handler_id = g_object_get_data(G_OBJECT(window), "flash_stop_handler_id"))) {
-- g_signal_handler_disconnect(G_OBJECT(window), (gulong) GPOINTER_TO_UINT(handler_id));
-- g_object_steal_data(G_OBJECT(window), "flash_stop_handler_id");
-- }
--
-- return FALSE;
--}
--
--void
--winpidgin_window_flash(GtkWindow *window, gboolean flash) {
-- GdkWindow * gdkwin;
-- FLASHWINFO info;
--
-- g_return_if_fail(window != NULL);
--
-- gdkwin = GTK_WIDGET(window)->window;
--
-- g_return_if_fail(GDK_IS_WINDOW(gdkwin));
-- g_return_if_fail(GDK_WINDOW_TYPE(gdkwin) != GDK_WINDOW_CHILD);
--
-- if(GDK_WINDOW_DESTROYED(gdkwin))
-- return;
--
-- memset(&info, 0, sizeof(FLASHWINFO));
-- info.cbSize = sizeof(FLASHWINFO);
-- info.hwnd = GDK_WINDOW_HWND(gdkwin);
-- if (flash) {
-- DWORD flashCount;
-- info.uCount = 3;
-- if (SystemParametersInfo(SPI_GETFOREGROUNDFLASHCOUNT, 0, &flashCount, 0))
-- info.uCount = flashCount;
-- info.dwFlags = FLASHW_ALL | FLASHW_TIMER;
-- } else
-- info.dwFlags = FLASHW_STOP;
-- FlashWindowEx(&info);
-- info.dwTimeout = 0;
--
--}
--
--void
--winpidgin_conv_blink(PurpleConversation *conv, PurpleMessageFlags flags) {
-- PidginWindow *win;
-- GtkWindow *window;
--
-- /* Don't flash for our own messages or system messages */
-- if(flags & PURPLE_MESSAGE_SEND || flags & PURPLE_MESSAGE_SYSTEM)
-- return;
--
-- if(conv == NULL) {
-- purple_debug_info("winpidgin", "No conversation found to blink.\n");
-- return;
-- }
--
-- win = pidgin_conv_get_window(PIDGIN_CONVERSATION(conv));
-- if(win == NULL) {
-- purple_debug_info("winpidgin", "No conversation windows found to blink.\n");
-- return;
-- }
-- window = GTK_WINDOW(win->window);
--
-- /* Don't flash if the window is in the foreground */
-- if (GetForegroundWindow() == GDK_WINDOW_HWND(GTK_WIDGET(window)->window))
-- return;
--
-- winpidgin_window_flash(window, TRUE);
-- /* Stop flashing when window receives focus */
-- if (g_object_get_data(G_OBJECT(window), "flash_stop_handler_id") == NULL) {
-- gulong handler_id = g_signal_connect(G_OBJECT(window), "focus-in-event",
-- G_CALLBACK(stop_flashing), window);
-- g_object_set_data(G_OBJECT(window), "flash_stop_handler_id", GUINT_TO_POINTER(handler_id));
-- }
--}
--
--static gboolean
--winpidgin_conv_im_blink(PurpleAccount *account, const char *who, char **message,
-- PurpleConversation *conv, PurpleMessageFlags flags, void *data)
--{
-- if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/win32/blink_im"))
-- winpidgin_conv_blink(conv, flags);
-- return FALSE;
--}
--
--void winpidgin_init(HINSTANCE hint) {
-- typedef void (__cdecl* LPFNSETLOGFILE)(const LPCSTR);
-- LPFNSETLOGFILE MySetLogFile;
-- gchar *exchndl_dll_path;
--
-- purple_debug_info("winpidgin", "winpidgin_init start\n");
--
-- exe_hInstance = hint;
--
-- exchndl_dll_path = g_build_filename(wpurple_install_dir(), "exchndl.dll", NULL);
-- MySetLogFile = (LPFNSETLOGFILE) wpurple_find_and_loadproc(exchndl_dll_path, "SetLogFile");
-- g_free(exchndl_dll_path);
-- exchndl_dll_path = NULL;
-- if (MySetLogFile) {
-- gchar *debug_dir, *locale_debug_dir;
--
-- debug_dir = g_build_filename(purple_user_dir(), "pidgin.RPT", NULL);
-- locale_debug_dir = g_locale_from_utf8(debug_dir, -1, NULL, NULL, NULL);
--
-- purple_debug_info("winpidgin", "Setting exchndl.dll LogFile to %s\n", debug_dir);
--
-- MySetLogFile(locale_debug_dir);
--
-- g_free(debug_dir);
-- g_free(locale_debug_dir);
-- }
--
--#ifdef USE_GTKSPELL
-- winpidgin_spell_init();
--#endif
-- purple_debug_info("winpidgin", "GTK+ :%u.%u.%u\n",
-- gtk_major_version, gtk_minor_version, gtk_micro_version);
--
-- messagewin_hwnd = winpidgin_message_window_init();
--
-- purple_debug_info("winpidgin", "winpidgin_init end\n");
--}
--
--void winpidgin_post_init(void) {
--
-- purple_prefs_add_none(PIDGIN_PREFS_ROOT "/win32");
-- purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/win32/blink_im", TRUE);
--
-- purple_signal_connect(pidgin_conversations_get_handle(),
-- "displaying-im-msg", &gtkwin32_handle, PURPLE_CALLBACK(winpidgin_conv_im_blink),
-- NULL);
--
--}
--
--/* Windows Cleanup */
--
--void winpidgin_cleanup(void) {
-- purple_debug_info("winpidgin", "winpidgin_cleanup\n");
--
-- if(messagewin_hwnd)
-- DestroyWindow(messagewin_hwnd);
--
--}
--
--/* DLL initializer */
--/* suppress gcc "no previous prototype" warning */
--BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
--BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
-- dll_hInstance = hinstDLL;
-- return TRUE;
--}
--
--static gboolean
--get_WorkingAreaRectForWindow(HWND hwnd, RECT *workingAreaRc) {
--
-- HMONITOR monitor;
-- MONITORINFO info;
--
-- monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
--
-- info.cbSize = sizeof(info);
-- if(!GetMonitorInfo(monitor, &info))
-- return FALSE;
--
-- CopyRect(workingAreaRc, &(info.rcWork));
-- return TRUE;
--}
--
--void winpidgin_ensure_onscreen(GtkWidget *win) {
-- RECT winR, wAR, intR;
-- HWND hwnd = GDK_WINDOW_HWND(win->window);
--
-- g_return_if_fail(hwnd != NULL);
-- GetWindowRect(hwnd, &winR);
--
-- purple_debug_info("win32placement",
-- "Window RECT: L:%ld R:%ld T:%ld B:%ld\n",
-- winR.left, winR.right,
-- winR.top, winR.bottom);
--
-- if(!get_WorkingAreaRectForWindow(hwnd, &wAR)) {
-- purple_debug_info("win32placement",
-- "Couldn't get multimonitor working area\n");
-- if(!SystemParametersInfo(SPI_GETWORKAREA, 0, &wAR, FALSE)) {
-- /* I don't think this will ever happen */
-- wAR.left = 0;
-- wAR.top = 0;
-- wAR.bottom = GetSystemMetrics(SM_CYSCREEN);
-- wAR.right = GetSystemMetrics(SM_CXSCREEN);
-- }
-- }
--
-- purple_debug_info("win32placement",
-- "Working Area RECT: L:%ld R:%ld T:%ld B:%ld\n",
-- wAR.left, wAR.right,
-- wAR.top, wAR.bottom);
--
-- /** If the conversation window doesn't intersect perfectly, move it to do so */
-- if(!(IntersectRect(&intR, &winR, &wAR)
-- && EqualRect(&intR, &winR))) {
-- purple_debug_info("win32placement",
-- "conversation window out of working area, relocating\n");
--
-- /* Make sure the working area is big enough. */
-- if ((winR.right - winR.left) <= (wAR.right - wAR.left)
-- && (winR.bottom - winR.top) <= (wAR.bottom - wAR.top)) {
-- /* Is it off the bottom? */
-- if (winR.bottom > wAR.bottom) {
-- winR.top = wAR.bottom - (winR.bottom - winR.top);
-- winR.bottom = wAR.bottom;
-- }
-- /* Is it off the top? */
-- else if (winR.top < wAR.top) {
-- winR.bottom = wAR.top + (winR.bottom - winR.top);
-- winR.top = wAR.top;
-- }
--
-- /* Is it off the left? */
-- if (winR.left < wAR.left) {
-- winR.right = wAR.left + (winR.right - winR.left);
-- winR.left = wAR.left;
-- }
-- /* Is it off the right? */
-- else if (winR.right > wAR.right) {
-- winR.left = wAR.right - (winR.right - winR.left);
-- winR.right = wAR.right;
-- }
--
-- } else {
-- /* We couldn't salvage it; move it to the top left corner of the working area */
-- winR.right = wAR.left + (winR.right - winR.left);
-- winR.bottom = wAR.top + (winR.bottom - winR.top);
-- winR.left = wAR.left;
-- winR.top = wAR.top;
-- }
--
-- purple_debug_info("win32placement",
-- "Relocation RECT: L:%ld R:%ld T:%ld B:%ld\n",
-- winR.left, winR.right,
-- winR.top, winR.bottom);
--
-- MoveWindow(hwnd, winR.left, winR.top,
-- (winR.right - winR.left),
-- (winR.bottom - winR.top), TRUE);
-- }
--
--}
--
--DWORD winpidgin_get_lastactive() {
-- DWORD result = 0;
--
-- LASTINPUTINFO lii;
-- memset(&lii, 0, sizeof(lii));
-- lii.cbSize = sizeof(lii);
-- if (GetLastInputInfo(&lii))
-- result = lii.dwTime;
--
-- return result;
--}
--
-diff -Nur pidgin-2.10.7/pidgin/win32/gtkwin32dep.h pidgin-2.10.7-nonprism/pidgin/win32/gtkwin32dep.h
---- pidgin-2.10.7/pidgin/win32/gtkwin32dep.h 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/gtkwin32dep.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,50 +0,0 @@
--/**
-- * @file gtkwin32dep.h UI Win32 Specific Functionality
-- * @ingroup win32
-- *
-- * Pidgin is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- */
--#ifndef _GTKWIN32DEP_H_
--#define _GTKWIN32DEP_H_
--#include <windows.h>
--#include <gtk/gtk.h>
--#include "conversation.h"
--
--HINSTANCE winpidgin_dll_hinstance(void);
--HINSTANCE winpidgin_exe_hinstance(void);
--
--/* Utility */
--int winpidgin_gz_decompress(const char* in, const char* out);
--int winpidgin_gz_untar(const char* filename, const char* destdir);
--
--/* Misc */
--void winpidgin_notify_uri(const char *uri);
--void winpidgin_shell_execute(const char *target, const char *verb, const char *clazz);
--void winpidgin_ensure_onscreen(GtkWidget *win);
--void winpidgin_conv_blink(PurpleConversation *conv, PurpleMessageFlags flags);
--void winpidgin_window_flash(GtkWindow *window, gboolean flash);
--DWORD winpidgin_get_lastactive(void);
--
--/* init / cleanup */
--void winpidgin_init(HINSTANCE);
--void winpidgin_post_init(void);
--void winpidgin_cleanup(void);
--
--#endif /* _GTKWIN32DEP_H_ */
--
-diff -Nur pidgin-2.10.7/pidgin/win32/MinimizeToTray.c pidgin-2.10.7-nonprism/pidgin/win32/MinimizeToTray.c
---- pidgin-2.10.7/pidgin/win32/MinimizeToTray.c 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/MinimizeToTray.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,119 +0,0 @@
--/* MinimizeToTray
-- *
-- * A couple of routines to show how to make it produce a custom caption
-- * animation to make it look like we are minimizing to and maximizing
-- * from the system tray
-- *
-- * These routines are public domain, but it would be nice if you dropped
-- * me a line if you use them!
-- *
-- * 1.0 29.06.2000 Initial version
-- * 1.1 01.07.2000 The window retains it's place in the Z-order of windows
-- * when minimized/hidden. This means that when restored/shown, it doesn't
-- * always appear as the foreground window unless we call SetForegroundWindow
-- *
-- * Copyright 2000 Matthew Ellis <m.t.ellis@bigfoot.com>
-- */
--#define _WIN32_WINNT 0x0500
--#include <windows.h>
--#include "MinimizeToTray.h"
--
--#define DEFAULT_RECT_WIDTH 150
--#define DEFAULT_RECT_HEIGHT 30
--
--static void GetTrayWndRect(LPRECT lpTrayRect) {
-- APPBARDATA appBarData;
-- HWND hShellTrayWnd = FindWindowEx(NULL, NULL, TEXT("Shell_TrayWnd"),
-- NULL);
--
-- if(hShellTrayWnd) {
-- HWND hTrayNotifyWnd = FindWindowEx(hShellTrayWnd, NULL,
-- TEXT("TrayNotifyWnd"), NULL);
--
-- if(hTrayNotifyWnd) {
-- GetWindowRect(hTrayNotifyWnd,lpTrayRect);
-- return;
-- }
-- }
--
-- appBarData.cbSize = sizeof(appBarData);
-- if(SHAppBarMessage(ABM_GETTASKBARPOS, &appBarData)) {
-- switch(appBarData.uEdge) {
-- case ABE_LEFT:
-- case ABE_RIGHT:
-- lpTrayRect->top = appBarData.rc.bottom - 100;
-- lpTrayRect->bottom = appBarData.rc.bottom - 16;
-- lpTrayRect->left = appBarData.rc.left;
-- lpTrayRect->right = appBarData.rc.right;
-- break;
-- case ABE_TOP:
-- case ABE_BOTTOM:
-- lpTrayRect->top = appBarData.rc.top;
-- lpTrayRect->bottom = appBarData.rc.bottom;
-- lpTrayRect->left = appBarData.rc.right - 100;
-- lpTrayRect->right = appBarData.rc.right - 16;
-- break;
-- }
-- return;
-- }
--
-- hShellTrayWnd = FindWindowEx(NULL, NULL, TEXT("Shell_TrayWnd"), NULL);
-- if(hShellTrayWnd) {
-- GetWindowRect(hShellTrayWnd, lpTrayRect);
-- if(lpTrayRect->right-lpTrayRect->left > DEFAULT_RECT_WIDTH)
-- lpTrayRect->left = lpTrayRect->right - DEFAULT_RECT_WIDTH;
-- if(lpTrayRect->bottom-lpTrayRect->top > DEFAULT_RECT_HEIGHT)
-- lpTrayRect->top=lpTrayRect->bottom - DEFAULT_RECT_HEIGHT;
--
-- return;
-- }
--
-- SystemParametersInfo(SPI_GETWORKAREA, 0, lpTrayRect, 0);
-- lpTrayRect->left = lpTrayRect->right - DEFAULT_RECT_WIDTH;
-- lpTrayRect->top = lpTrayRect->bottom - DEFAULT_RECT_HEIGHT;
--}
--
--static BOOL GetDoAnimateMinimize(void) {
-- ANIMATIONINFO ai;
--
-- ai.cbSize = sizeof(ai);
-- SystemParametersInfo(SPI_GETANIMATION, sizeof(ai), &ai, 0);
--
-- return ai.iMinAnimate ? TRUE : FALSE;
--}
--
--void MinimizeWndToTray(HWND hWnd) {
--
-- if(!IsWindowVisible(hWnd))
-- return;
--
-- if(GetDoAnimateMinimize()) {
-- RECT rcFrom, rcTo;
--
-- GetWindowRect(hWnd, &rcFrom);
-- GetTrayWndRect(&rcTo);
--
-- DrawAnimatedRects(hWnd, IDANI_CAPTION, &rcFrom, &rcTo);
-- }
--
-- ShowWindow(hWnd, SW_HIDE);
--}
--
--void RestoreWndFromTray(HWND hWnd) {
--
-- if(IsWindowVisible(hWnd))
-- return;
--
-- if(GetDoAnimateMinimize()) {
-- RECT rcFrom, rcTo;
-- GetTrayWndRect(&rcFrom);
-- GetWindowRect(hWnd, &rcTo);
--
-- DrawAnimatedRects(hWnd, IDANI_CAPTION, &rcFrom, &rcTo);
-- }
--
-- ShowWindow(hWnd, SW_SHOW);
-- SetActiveWindow(hWnd);
-- SetForegroundWindow(hWnd);
--}
--
-diff -Nur pidgin-2.10.7/pidgin/win32/MinimizeToTray.h pidgin-2.10.7-nonprism/pidgin/win32/MinimizeToTray.h
---- pidgin-2.10.7/pidgin/win32/MinimizeToTray.h 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/MinimizeToTray.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,7 +0,0 @@
--#ifndef _MINIMIZE_TO_TRAY_H_
--#define _MINIMIZE_TO_TRAY_H_
--
--void MinimizeWndToTray(HWND hWnd);
--void RestoreWndFromTray(HWND hWnd);
--
--#endif /* _MINIMIZE_TO_TRAY_H_ */
-diff -Nur pidgin-2.10.7/pidgin/win32/nsis/available.lst pidgin-2.10.7-nonprism/pidgin/win32/nsis/available.lst
---- pidgin-2.10.7/pidgin/win32/nsis/available.lst 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/nsis/available.lst 1969-12-31 21:00:00.000000000 -0300
-@@ -1,100 +0,0 @@
--#This file is from ftp://ftp.services.openoffice.org/pub/OpenOffice.org/contrib/dictionaries/available.lst
--af,ZA,af_ZA,Afrikaans (South Africa),af_ZA.zip
--ak,GH,ak_GH,Akan (Ghana),ak_GH.zip
--sq,AL,sq_AL,Albanian (Albania),sq_AL.zip
--bg,BG,bg_BG,Bulgarian (Bulgaria),bg_BG.zip
--ca,ES,ca_ES,Catalan (Spain),ca_ES.zip
--cop,EG,cop_EG,Coptic (Egypt),cop_EG.zip
--hr,HR,hr_HR,Croatian (Croatia),hr_HR.zip
--cs,CZ,cs_CZ,Czech (Czech Republic),cs_CZ.zip
--da,DK,da_DK,Danish (Denmark),da_DK.zip
--nl,NL,nl_NL,Dutch (Netherlands),nl_NL.zip
--nl,NL,nl_med,Dutch Medical (Netherlands),nl_med.zip
--en,AU,en_AU,English (Australia),en_AU.zip
--en,CA,en_CA,English (Canada),en_CA.zip
--en,NZ,en_NZ,English (New Zealand),en_NZ.zip
--en,ZA,en_ZA,English (South Africa),en_ZA.zip
--en,GB,en_GB,English (United Kingdom),en_GB.zip
--en,US,en_US,English (United States),en_US.zip
--eo,ANY,eo_l3,Esperanto,eo.zip
--et,EE,et_EE,Estonian (Estonia),et_EE.zip
--fo,FO,fo_FO,Faroese (Faroe Islands),fo_FO.zip
--fr,FR,fr_FR-classique,Français Classique,fr_FR-classique_1-3-2.zip
--fr,FR,fr_FR-1990,Français Réforme 1990,fr_FR-1990_1-3-2.zip
--fr,FR,fr_FR,Français Réforme 1990 & Classique,fr_FR_1-3-2.zip
--fy,NL,fy_NL,Frisian (Netherlands),fy_NL.zip
--gl,ES,gl_ES,Galician (Spain),gl_ES.zip
--gsc,FR,gsc_FR,Gascon (France),gsc_FR.zip
--de,AT,de_AT,German (Austria Extension),de_AT.zip
--de,AT,de_AT_frami,German (Austria) neu 08/2006 (frami),de_AT_frami.zip
--de,DE,de_DE,German (Germany),de_DE.zip
--de,DE,de_DE_frami,German (Germany) neu 08/2006 (frami),de_DE_frami.zip
--de,CH,de_CH,German (Switzerland),de_CH.zip
--de,CT,de_CH_frami,German (Switzerland) neu 08/2006 (frami),de_CH_frami.zip
--el,GR,el_GR,Greek (Greece),el_GR.zip
--gu,IN,gu_IN,Gujarati (India),gu_IN.zip
--he,IL,he_IL,Hebrew (Israel),he_IL.zip
--hil,PH,hil_PH,Hiligaynon (Philippines),hil_PH.zip
--hu,HU,hu_HU,Hungarian (Hungary),hu_HU.zip
--hu,HU,hu_HU_comb,Hungarian (Hungary) collected compounds,hu_HU_comb.zip
--id,ID,id_ID,Indonesian (Indonesia),id_ID.zip
--ga,IE,ga_IE,Irish (Ireland),ga_IE.zip
--it,IT,it_IT,Italian (Italy),it_IT.zip
--sw,KE,sw_KE,Kiswahili (Africa),sw_KE.zip
--ku,TR,ku_TR,Kurdish (Turkey),ku_TR.zip
--it,IT,la,Latin,la.zip
--lv,LV,lv_LV,Latvian (Latvia),lv_LV.zip
--lt,LT,lt_LT,Lithuanian (Lithuania),lt_LT.zip
--mk,MK,mk_MK,Macedonian (Macedonia),mk_MK.zip
--ms,MY,ms_MY,Malay (Malaysia),ms_MY.zip
--mi,NZ,mi_NZ,Maori (New Zealand),mi_NZ.zip
--mr,IN,mr_IN,Marathi (India),mr_IN.zip
--mos,BF,mos_BF,Moore,ms_BF.zip
--nr,ZA,nr_ZA,Ndebele (South Africa),nr_ZA.zip
--ne,NP,ne_NP,Nepali (Nepal),ne_NP.zip
--ns,ZA,ns_ZA,Northern Sotho (South Africa),ns_ZA.zip
--nb,NO,nb_NO,Norwegian Bokmaal (Norway),nb_NO.zip
--nn,NO,nn_NO,Norwegian Nynorsk (Norway),nn_NO.zip
--oc,FR,oc_FR,Occitan (Languedoc),oc_FR.zip
--pl,PL,pl_PL,Polish (Poland),pl_PL.zip
--pt,BR,pt_BR,Portuguese (Brazil),pt_BR.zip
--pt,PT,pt_PT,Portuguese (Portugal),pt_PT.zip
--ro,RO,ro_RO,Romanian (Romania),ro_RO.zip
--ru,RU,ru_RU,Russian (Russia),ru_RU.zip
--ru,RU,ru_RU_ye,Russian_ye (Russia),ru_RU_ye.zip
--ru,RU,ru_RU_yo,Russian_yo (Russia),ru_RU_yo.zip
--gd,GB,gd_GB,Scots Gaelic (Scotland),gd_GB.zip
--tn,ZA,tn_ZA,Setswana (Africa),tn_ZA.zip
--sk,SK,sk_SK,Slovak (Slovakia),sk_SK.zip
--sl,SI,sl_SI,Slovenian (Slovenia),sl_SI.zip
--st,ZA,st_ZA,Southern Sotho (South Africa),st_ZA.zip
--es,AR,es_AR,Spanish (Argentina),es_AR.zip
--es,BZ,es_HN,Spanish (Belize),es_HN.zip
--es,BO,es_BO,Spanish (Bolivia),es_BO.zip
--es,CL,es_CL,Spanish (Chile),es_CL.zip
--es,CO,es_CO,Spanish (Colombia),es_CO.zip
--es,CR,es_CR,Spanish (Costa Rica),es_CR.zip
--es,CU,es_CU,Spanish (Cuba),es_CU.zip
--es,DO,es_DO,Spanish (Dominican Republic),es_DO.zip
--es,EC,es_EC,Spanish (Ecuador),es_EC.zip
--es,SV,es_SV,Spanish (El Salvador),es_SV.zip
--es,GT,es_GT,Spanish (Guatemala),es_GT.zip
--es,MX,es_MX,Spanish (Mexico),es_MX.zip
--es,NI,es_NI,Spanish (Nicaragua),es_NI.zip
--es,PA,es_PA,Spanish (Panama),es_PA.zip
--es,PY,es_PY,Spanish (Paraguay),es_PY.zip
--es,PE,es_PE,Spanish (Peru),es_PE.zip
--es,PR,es_PR,Spanish (Puerto Rico),es_PR.zip
--es,ES,es_ES,Spanish (Spain),es_ES.zip
--es,UY,es_UY,Spanish (Uruguay),es_UY.zip
--es,VE,es_VE,Spanish (Venezuela),es_VE.zip
--ss,ZA,ss_ZA,Swati (South Africa),ss_ZA.zip
--sv,SE,sv_SE,Swedish (Sweden),sv_SE.zip
--ts,ZA,ts_ZA,Tsonga (South Africa),ts_ZA.zip
--uk,UA,uk_UA,Ukrainian (Ukraine),uk_UA.zip
--ur,PK,ur_PK,Urdu,ur_PK.zip
--ve,ZA,ve_ZA,Venda (South Africa),ve_ZA.zip
--vi,VN,vi_VN,Vietnamese (Viet-Nam),vi_VN.zip
--cy,GB,cy_GB,Welsh (Wales),cy_GB.zip
--xh,ZA,xh_ZA,Xhosa (South Africa),xh_ZA.zip
--zu,ZA,zu_ZA,Zulu (South Africa),zu_ZA.zip
-diff -Nur pidgin-2.10.7/pidgin/win32/nsis/create_nsis_translations.pl pidgin-2.10.7-nonprism/pidgin/win32/nsis/create_nsis_translations.pl
---- pidgin-2.10.7/pidgin/win32/nsis/create_nsis_translations.pl 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/nsis/create_nsis_translations.pl 1969-12-31 21:00:00.000000000 -0300
-@@ -1,390 +0,0 @@
--#!/usr/bin/perl
--#
--# create_nsis_translations.pl
--#
--# Copyright (C) 2000-2009 Bruno Coudoin
--#
--# This program is free software; you can redistribute it and/or modify
--# it under the terms of the GNU General Public License as published by
--# the Free Software Foundation; either version 3 of the License, or
--# (at your option) any later version.
--#
--# This program is distributed in the hope that it will be useful,
--# but WITHOUT ANY WARRANTY; without even the implied warranty of
--# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--# GNU General Public License for more details.
--#
--# You should have received a copy of the GNU General Public License
--# along with this program; if not, see <http://www.gnu.org/licenses/>.
--#
--
--use strict;
--
--sub usage {
-- print 'create_nsis_translations.pl translations installer tmp_dir
-- translations
-- This is an input file that contains all the
-- translated strings. If must be formated as a GNU/Linux
-- desktop file and contains multiple strings entry.
-- For example you must have:
-- toBe=To be or not to be
-- toBe[fr]=Etre ou ne pas etre
--
-- installer
-- This is your nsis installer source file. You must include
-- in it the marker @INSERT_TRANSLATIONS@ before you use any
-- translation string.
-- After that you can use the variable $(toBe) in your file.
--
-- tmp_dir
-- This is a directory in which temporary files needed for
-- the translation system.
-- It will be created if non existant.
-- You can remove it once you have created your installer.
--';
--}
--
--my $translations;
--if (! $ARGV[0] || ! -f $ARGV[0])
--{
-- usage();
--}
--else
--{
-- $translations = $ARGV[0];
--}
--
--shift;
--my $installer;
--if (! $ARGV[0] || ! -f $ARGV[0])
--{
-- usage();
--}
--else
--{
-- $installer = $ARGV[0];
--}
--
--shift;
--my $tmp_dir;
--if (! $ARGV[0] )
--{
-- usage();
--}
--else
--{
-- $tmp_dir = $ARGV[0];
--
-- if ( ! -d $tmp_dir )
-- {
-- mkdir $tmp_dir or die "ERROR: '$tmp_dir' $!\n";
-- }
--}
--
--print "Processing translation file '$translations'\n";
--print " NSIS source file '$installer'\n";
--print " Working dir '$tmp_dir'\n";
--
--# Commented out locales that are not available in nsis
--# Map value is ["NSISFilename", "Encoding", "LCID"]
--my %localeNames = (
-- "af" => ["Afrikaans", "WINDOWS-1252", "1078"],
--# "am" => ["Amharic", "UTF-8"],
-- "ar" => ["Arabic", "WINDOWS-1256", "1025"],
-- "be" => ["Belarusian", "WINDOWS-1251", "1059"],
-- "bg" => ["Bulgarian", "WINDOWS-1251", "1026"],
-- "bs" => ["Bosnian", "WINDOWS-1250", "5146"],
-- "br" => ["Breton", "WINDOWS-1252", "1150"],
-- "ca" => ["Catalan", "WINDOWS-1252", "1027"],
-- "cs" => ["Czech", "WINDOWS-1250", "1029"],
-- "cy" => ["Welsh", "WINDOWS-1252", "1160"],
-- "da" => ["Danish", "WINDOWS-1252", "1030"],
-- "de" => ["German", "WINDOWS-1252", "1031"],
--# "dz" => ["Dzongkha", "UTF-8"],
-- "el" => ["Greek", "WINDOWS-1253", "1032"],
-- "en" => ["English", "WINDOWS-1252", "1033"],
-- "eo" => ["Esperanto", "WINDOWS-1252", "9998"],
-- "es" => ["Spanish", "WINDOWS-1252", "1034"],
-- "et" => ["Estonian", "WINDOWS-1257", "1061"],
-- "eu" => ["Basque", "WINDOWS-1252", "1069"],
-- "fa" => ["Farsi", "WINDOWS-1256", "1065"],
-- "fi" => ["Finnish", "WINDOWS-1252", "1035"],
-- "fr" => ["French", "WINDOWS-1252", "1036"],
-- "ga" => ["Irish", "WINDOWS-1252", "2108"],
-- "gl" => ["Galician", "WINDOWS-1252", "1110"],
--# "gu" => ["Gujarati", "UTF-8"],
-- "he" => ["Hebrew", "WINDOWS-1255", "1037"],
--# "hi" => ["Hindi", "UTF-8"],
-- "hr" => ["Croatian", "WINDOWS-1250", "1050"],
-- "hu" => ["Hungarian", "WINDOWS-1250", "1038"],
-- "id" => ["Indonesian", "WINDOWS-1252", "1057"],
-- "is" => ["Icelandic", "WINDOWS-1252", "15"], #This should be 1039!
-- "it" => ["Italian", "WINDOWS-1252", "1040"],
-- "ja" => ["Japanese", "CP932", "1041"],
--# "ka" => ["Georgian", "UTF-8"],
-- "ko" => ["Korean", "CP949", "1042"],
-- "ku" => ["Kurdish", "WINDOWS-1254", "9999"],
-- "lb" => ["Luxembourgish", "WINDOWS-1252", "4103"],
-- "lt" => ["Lithuanian", "WINDOWS-1257", "1063"],
-- "lv" => ["Latvian", "WINDOWS-1257", "1062"],
-- "mk" => ["Macedonian", "WINDOWS-1251", "1071"],
--# "ml" => ["Malayalam", "UTF-8"],
--# "mr" => ["Marathi", "UTF-8"],
-- "mn" => ["Mongolian", "WINDOWS-1251", "1104"],
-- "ms" => ["Malay", "WINDOWS-1252", "1086"],
-- "nb" => ["Norwegian", "WINDOWS-1252", "1044"],
--# "ne" => ["Nepal", "UTF-8"],
-- "nl" => ["Dutch", "WINDOWS-1252", "1043"],
-- "nn" => ["NorwegianNynorsk", "WINDOWS-1252", "2068"],
--# "oc" => ["Occitan", "WINDOWS-1252"],
--# "pa" => ["Punjabi", "UTF-8"],
-- "pl" => ["Polish", "WINDOWS-1250", "1045"],
-- "pt" => ["Portuguese", "WINDOWS-1252", "2070"],
-- "pt_BR" => ["PortugueseBR", "WINDOWS-1252", "1046"],
-- "ro" => ["Romanian", "WINDOWS-1250", "1048"],
-- "ru" => ["Russian", "WINDOWS-1251", "1049"],
--# "rw" => ["Kinyarwanda", "UTF-8"],
-- "sk" => ["Slovak", "WINDOWS-1250", "1051"],
-- "sl" => ["Slovenian", "WINDOWS-1250", "1060"],
--# "so" => ["Somali", "UTF-8"],
-- "sq" => ["Albanian", "WINDOWS-1252", "1052"],
-- "sr" => ["Serbian", "WINDOWS-1251", "3098"],
-- "sr\@latin" => ["SerbianLatin", "WINDOWS-1250", "2074"],
-- "sv" => ["Swedish", "WINDOWS-1252", "1053"],
--# "ta" => ["Tamil", "UTF-8"],
-- "th" => ["Thai", "WINDOWS-874", "1054"],
-- "tr" => ["Turkish", "WINDOWS-1254", "1055"],
-- "uk" => ["Ukrainian", "WINDOWS-1251", "1058"],
-- "uz" => ["Uzbek", "WINDOWS-1252", "1091"],
--# "ur" => ["Urdu", "UTF-8"],
--# "vi" => ["Vietnamese", "WINDOWS-1258"],
--# "wa" => ["Walloon", "WINDOWS-1252"],
-- "zh_CN" => ["SimpChinese", "WINDOWS-936", "2052"],
-- "zh_TW" => ["TradChinese", "CP950", "1028"],
--);
--
--my @localeKeys = keys(%localeNames);
--
--# Create the holder for the results
--# %result{"locale"}{"stringname"} = result line
--print "Parsing nsis_translations.desktop\n";
--my %result;
--
--# Create a hash of the keys to translate
--open (MYFILE, $translations);
--while (<MYFILE>) {
-- chomp $_;
-- if ($_ =~ /Encoding=UTF-8/)
-- {
-- next;
-- }
-- elsif ($_ =~ /^(\w+)=(.*)/)
-- {
-- my $line = "!define $1 \"$2\"\n";
-- $result{"en"}{"$1"} = $line;
-- }
-- elsif ($_ =~ /^(\w+)\[(\w+)\]=(.*)/)
-- {
-- my $line = "!define $1 \"$3\"\n";
-- $result{"$2"}{"$1"} = $line;
-- }
--}
--close (MYFILE);
--
--# Lets insert the default languages
--# in the installer file which means replacing:
--# @INSERTMACRO_MUI_LANGUAGE@
--# By the list of locales:
--# !insertmacro MUI_LANGUAGE "French"
--
--my $muiLanguages;
--$muiLanguages = '
-- ;; English goes first because its the default. The rest are
-- ;; in alphabetical order (at least the strings actually displayed
-- ;; will be).
-- !insertmacro MUI_LANGUAGE "English"
--';
--
--# The specific GCompris translation for the installer
--# replacing:
--# @GCOMPRIS_MACRO_INCLUDE_LANGFILE@
--# By the list of locales:
--# !insertmacro GCOMPRIS_MACRO_INCLUDE_LANGFILE "ALBANIAN" "${GCOMPRIS_NSIS_INCLUDE_PATH}\translations\albanian.nsh"
--
--my $gcomprisLanguages;
--
--$gcomprisLanguages .= '
--;--------------------------------
--;Translations
-- !define GCOMPRIS_DEFAULT_LANGFILE "${GCOMPRIS_NSIS_INCLUDE_PATH}\\translations\\en.nsh"
--;;
--;; Windows GCompris NSIS installer language macros
--;;
--
--!macro GCOMPRIS_MACRO_DEFAULT_STRING LABEL VALUE
-- !ifndef "${LABEL}"
-- !define "${LABEL}" "${VALUE}"
-- !ifdef INSERT_DEFAULT
-- !warning "${LANG} lang file missing ${LABEL}, using default..."
-- !endif
-- !endif
--!macroend
--
--!macro GCOMPRIS_MACRO_LANGSTRING_INSERT LABEL LANG
-- LangString "${LABEL}" "${LANG_${LANG}}" "${${LABEL}}"
-- !undef "${LABEL}"
--!macroend
--
--!macro GCOMPRIS_MACRO_LANGUAGEFILE_BEGIN LANG
-- !define CUR_LANG "${LANG}"
--!macroend
--';
--
--
--# GCOMPRIS_MACRO_LANGUAGEFILE_END
--$gcomprisLanguages .= '
--!macro GCOMPRIS_MACRO_LANGUAGEFILE_END
-- !define INSERT_DEFAULT
-- !include "${GCOMPRIS_DEFAULT_LANGFILE}"
-- !undef INSERT_DEFAULT
--
-- ; String labels should match those from the default language file.
--';
--
--my $text_en = $result{"en"};
--foreach my $keyEn (keys(%$text_en)) {
-- $gcomprisLanguages .= " !insertmacro GCOMPRIS_MACRO_LANGSTRING_INSERT $keyEn \${CUR_LANG}";
-- $gcomprisLanguages .= "\n";
--}
--
--$gcomprisLanguages .= '
-- !undef CUR_LANG
--!macroend
--';
--
--$gcomprisLanguages .= '
--!macro GCOMPRIS_MACRO_INCLUDE_LANGFILE LANG FILE
-- !insertmacro GCOMPRIS_MACRO_LANGUAGEFILE_BEGIN "${LANG}"
-- !include "${FILE}"
-- !insertmacro GCOMPRIS_MACRO_LANGUAGEFILE_END
--!macroend
--';
--
--#
--# Create each nsh translation file
--#
--
--print "Creating the nsh default file\n";
--open (DESC, ">$tmp_dir/en.nsh");
--print DESC ";; Auto generated file by create_nsis_translations.pl\n";
--foreach my $keyEn (keys(%$text_en)) {
-- my $line = $result{'en'}{$keyEn};
-- $line =~ s/!define /!insertmacro GCOMPRIS_MACRO_DEFAULT_STRING /;
-- print DESC $line;
--}
--close DESC;
--
--$gcomprisLanguages .= " !insertmacro GCOMPRIS_MACRO_INCLUDE_LANGFILE".
-- " \"ENGLISH\"".
-- " \"\${GCOMPRIS_NSIS_INCLUDE_PATH}\\translations\\en.nsh\"\n";
--
--my $selectTranslationFunction = '
--!macro SELECT_TRANSLATION_SECTION LANG_NAME LANG_CODE
-- StrCmp "$LANGUAGE" "${LANG_${LANG_NAME}}" 0 end_${LANG_CODE}
-- !insertmacro SelectSection ${SecLang_${LANG_CODE}}
-- Goto done
-- end_${LANG_CODE}:
--!macroend
--; Convert the current $LANGUAGE to a language code that we can use for translation mo selection
--; If there\'s a better way to do this, I\'d love to know it
--!macro SELECT_TRANSLATION_FUNCTION
--';
--
--#
--# Two pass are needed:
--# - create the utf8 file
--# - transform it to the proper windows locale
--#
--print "Creating the nsh locale files\n";
--foreach my $lang (@localeKeys) {
-- if ( $lang eq "en" ) { next; }
-- open (DESC, ">$tmp_dir/$lang.nsh.utf8");
-- print DESC ";; Auto generated file by create_nsis_translations.pl\n";
-- print DESC ";; Code Page: $localeNames{$lang}[1]\n";
--
-- my $text_locale = $result{"$lang"};
-- my $total_key_count = 0;
-- my $found_key_count = 0;
-- foreach my $keyEn (keys(%$text_en)) {
-- my $found = 0;
-- $total_key_count++;
-- foreach my $keyLocale (keys(%$text_locale)) {
-- # Fine, we found a translation
-- if ( $keyLocale eq $keyEn )
-- {
-- print DESC "$result{$lang}{$keyLocale}";
-- $found = 1;
-- $found_key_count++;
-- last;
-- }
-- }
-- # English keys are the reference.
-- # If not found they are inserted
-- #if ( ! $found )
-- #{
-- # print DESC "$result{'en'}{$keyEn}";
-- #}
-- }
-- close DESC;
--
-- # If we have at least 50% of the keys found, include the language
-- if (($found_key_count * 1.0 / $total_key_count) >= 0.5) {
-- $muiLanguages .= " !insertmacro MUI_LANGUAGE \"$localeNames{$lang}[0]\"\n";
-- $gcomprisLanguages .= " !insertmacro GCOMPRIS_MACRO_INCLUDE_LANGFILE".
-- " \"". uc($localeNames{$lang}[0]) . "\"".
-- " \"\${GCOMPRIS_NSIS_INCLUDE_PATH}\\translations\\$lang.nsh\"\n";
-- $selectTranslationFunction .= " !insertmacro SELECT_TRANSLATION_SECTION".
-- " \"" . uc($localeNames{$lang}[0]) . "\" \"$lang\"\n";
-- } else {
-- print "Ignoring language $lang because it is less than 50% translated ($found_key_count of $total_key_count).\n";
-- next;
-- }
--
--
-- # iconv conversion
-- system("iconv -f UTF-8 -t $localeNames{$lang}[1] $tmp_dir/$lang.nsh.utf8 > $tmp_dir/$lang.nsh");
-- if ($? ne 0)
-- {
-- die("ERROR: Failed to run: iconv -f UTF-8 -t $localeNames{$lang}[1] $lang.nsh.utf8 > $lang.nsh\n");
-- }
-- #`rm $tmp_dir/$lang.nsh.utf8`;
--
--}
--
--$selectTranslationFunction .= '
--done:
--!macroend
--';
--
--# We have all the data, let's replace it
--my $gcomprisInstaller;
--open (MYFILE, $installer);
--while (<MYFILE>) {
-- if ($_ =~ /\@INSERT_TRANSLATIONS\@/)
-- {
-- print "Processing \@INSERT_TRANSLATIONS\@\n";
-- $gcomprisInstaller .= $muiLanguages;
-- $gcomprisInstaller .= $gcomprisLanguages;
-- $gcomprisInstaller .= $selectTranslationFunction;
-- }
-- else
-- {
-- $gcomprisInstaller .= "$_";
-- }
--}
--close (MYFILE);
--
--# Rewrite the file with the replaced data
--open (MYFILE, ">$installer");
--print MYFILE "$gcomprisInstaller";
--close (MYFILE);
-diff -Nur pidgin-2.10.7/pidgin/win32/nsis/generate_gtk_zip.sh pidgin-2.10.7-nonprism/pidgin/win32/nsis/generate_gtk_zip.sh
---- pidgin-2.10.7/pidgin/win32/nsis/generate_gtk_zip.sh 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/nsis/generate_gtk_zip.sh 1969-12-31 21:00:00.000000000 -0300
-@@ -1,140 +0,0 @@
--#!/bin/bash
--# Script to generate zip file for GTK+ runtime to be included in Pidgin installer
--
--PIDGIN_BASE=$1
--GPG_SIGN=$2
--
--if [ ! -e $PIDGIN_BASE/ChangeLog ]; then
-- echo $(basename $0) must must have the pidgin base dir specified as a parameter.
-- exit 1
--fi
--
--STAGE_DIR=`readlink -f $PIDGIN_BASE/pidgin/win32/nsis/gtk_runtime_stage`
--#Subdirectory of $STAGE_DIR
--INSTALL_DIR=Gtk
--CONTENTS_FILE=$INSTALL_DIR/CONTENTS
--PIDGIN_VERSION=$( < $PIDGIN_BASE/VERSION )
--
--#This needs to be changed every time there is any sort of change.
--BUNDLE_VERSION=2.16.6.1
--BUNDLE_SHA1SUM=5e16b7efb11943e8c80bc390f6c38df904fd36ed
--ZIP_FILE="$PIDGIN_BASE/pidgin/win32/nsis/gtk-runtime-$BUNDLE_VERSION.zip"
--
--#Download the existing file (so that we distribute the exact same file for all releases with the same bundle version)
--FILE="$ZIP_FILE"
--if [ ! -e "$FILE" ]; then
-- wget "https://pidgin.im/win32/download_redir.php?version=$PIDGIN_VERSION&gtk_version=$BUNDLE_VERSION&dl_pkg=gtk" -O "$FILE"
--fi
--CHECK_SHA1SUM=`sha1sum $FILE`
--CHECK_SHA1SUM=${CHECK_SHA1SUM%%\ *}
--if [ "$CHECK_SHA1SUM" != "$BUNDLE_SHA1SUM" ]; then
-- echo "sha1sum ($CHECK_SHA1SUM) for $FILE doesn't match expected value of $BUNDLE_SHA1SUM"
-- # Allow "devel" versions to build their own bundles if the download doesn't succeed
-- if [[ "$PIDGIN_VERSION" == *"devel" ]]; then
-- echo "Continuing GTK+ Bundle creation for development version of Pidgin"
-- else
-- exit 1
-- fi
--else
-- exit 0
--fi
--
--
--ATK="http://ftp.gnome.org/pub/gnome/binaries/win32/atk/1.32/atk_1.32.0-2_win32.zip ATK 1.32.0-2 sha1sum:3c31c9d6b19af840e2bd8ccbfef4072a6548dc4e"
--#Cairo 1.10.2 has a bug that can be seen when selecting text
--#CAIRO="http://ftp.gnome.org/pub/GNOME/binaries/win32/dependencies/cairo_1.10.2-2_win32.zip Cairo 1.10.2-2 sha1sum:d44cd66a9f4d7d29a8f2c28d1c1c5f9b0525ba44"
--CAIRO="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/cairo_1.8.10-1_win32.zip Cairo 1.8.10-1 sha1sum:a08476cccd807943958610977a138c4d6097c7b8"
--EXPAT="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/expat_2.1.0-1_win32.zip Expat 2.1.0-1 gpg:0x71D4DDE53F188CBE"
--FONTCONFIG="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/fontconfig_2.8.0-2_win32.zip Fontconfig 2.8.0-2 sha1sum:37a3117ea6cc50c8a88fba9b6018f35a04fa71ce"
--FREETYPE="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/freetype_2.4.10-1_win32.zip Freetype 2.4.10-1 gpg:0x71D4DDE53F188CBE"
--GETTEXT="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/gettext-runtime_0.18.1.1-2_win32.zip Gettext 0.18.1.1-2 sha1sum:a7cc1ce2b99b408d1bbea9a3b4520fcaf26783b3"
--GLIB="http://ftp.gnome.org/pub/gnome/binaries/win32/glib/2.28/glib_2.28.8-1_win32.zip Glib 2.28.8-1 sha1sum:5d158f4c77ca0b5508e1042955be573dd940b574"
--GTK="http://ftp.acc.umu.se/pub/gnome/binaries/win32/gtk+/2.16/gtk+_2.16.6-2_win32.zip GTK+ 2.16.6-2 sha1sum:012853e6de814ebda0cc4459f9eed8ae680e6d17"
--LIBPNG="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/libpng_1.4.12-1_win32.zip libpng 1.4.12-1 gpg:0x71D4DDE53F188CBE"
--PANGO="http://ftp.gnome.org/pub/gnome/binaries/win32/pango/1.29/pango_1.29.4-1_win32.zip Pango 1.29.4-1 sha1sum:3959319bd04fbce513458857f334ada279b8cdd4"
--ZLIB="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/zlib_1.2.5-2_win32.zip zlib 1.2.5-2 sha1sum:568907188761df2d9309196e447d91bbc5555d2b"
--
--ALL="ATK CAIRO EXPAT FONTCONFIG FREETYPE GETTEXT GLIB GTK LIBPNG PANGO ZLIB"
--
--mkdir -p $STAGE_DIR
--cd $STAGE_DIR
--
--rm -rf $INSTALL_DIR
--mkdir $INSTALL_DIR
--
--#new CONTENTS file
--echo Bundle Version $BUNDLE_VERSION > $CONTENTS_FILE
--
--function download_and_extract {
-- URL=${1%%\ *}
-- VALIDATION=${1##*\ }
-- NAME=${1%\ *}
-- NAME=${NAME#*\ }
-- FILE=$(basename $URL)
-- if [ ! -e $FILE ]; then
-- echo Downloading $NAME
-- wget $URL || exit 1
-- fi
-- VALIDATION_TYPE=${VALIDATION%%:*}
-- VALIDATION_VALUE=${VALIDATION##*:}
-- if [ $VALIDATION_TYPE == 'sha1sum' ]; then
-- CHECK_SHA1SUM=`sha1sum $FILE`
-- CHECK_SHA1SUM=${CHECK_SHA1SUM%%\ *}
-- if [ "$CHECK_SHA1SUM" != "$VALIDATION_VALUE" ]; then
-- echo "sha1sum ($CHECK_SHA1SUM) for $FILE doesn't match expected value of $VALIDATION_VALUE"
-- exit 1
-- fi
-- elif [ $VALIDATION_TYPE == 'gpg' ]; then
-- if [ ! -e "$FILE.asc" ]; then
-- echo Downloading GPG key for $NAME
-- wget "$URL.asc" || exit 1
-- fi
-- #Use our own keyring to avoid adding stuff to the main keyring
-- #This doesn't use $GPG_SIGN because we don't this validation to be bypassed when people are skipping signing output
-- GPG_BASE="gpg -q --keyring $STAGE_DIR/$VALIDATION_VALUE-keyring.gpg"
-- if [[ ! -e $STAGE_DIR/$VALIDATION_VALUE-keyring.gpg \
-- || `$GPG_BASE --list-keys "$VALIDATION_VALUE" > /dev/null && echo -n "0"` -ne 0 ]]; then
-- touch $STAGE_DIR/$VALIDATION_VALUE-keyring.gpg
-- $GPG_BASE --no-default-keyring --keyserver pgp.mit.edu --recv-key "$VALIDATION_VALUE" || exit 1
-- fi
-- $GPG_BASE --verify "$FILE.asc" || (echo "$FILE failed signature verification"; exit 1) || exit 1
-- else
-- echo "Unrecognized validation type of $VALIDATION_TYPE"
-- exit 1
-- fi
-- EXTENSION=${FILE##*.}
-- #This is an OpenSuSE build service RPM
-- if [ $EXTENSION == 'rpm' ]; then
-- echo "Generating zip from $FILE"
-- FILE=$(../rpm2zip.sh $FILE)
-- fi
-- unzip -q $FILE -d $INSTALL_DIR || exit 1
-- echo "$NAME" >> $CONTENTS_FILE
--}
--
--for VAL in $ALL
--do
-- VAR=${!VAL}
-- download_and_extract "$VAR"
--done
--
--#Default GTK+ Theme to MS-Windows
--echo gtk-theme-name = \"MS-Windows\" > $INSTALL_DIR/etc/gtk-2.0/gtkrc
--
--#Blow away translations that we don't have in Pidgin
--for LOCALE_DIR in $INSTALL_DIR/share/locale/*
--do
-- LOCALE=$(basename $LOCALE_DIR)
-- if [ ! -e $PIDGIN_BASE/po/$LOCALE.po ]; then
-- echo Removing $LOCALE translation as it is missing from Pidgin
-- rm -r $LOCALE_DIR
-- fi
--done
--
--#Generate zip file to be included in installer
--rm -f $ZIP_FILE
--zip -9 -r $ZIP_FILE Gtk
--($GPG_SIGN -ab $ZIP_FILE && $GPG_SIGN --verify $ZIP_FILE.asc) || exit 1
--
--exit 0
--
-diff -Nur pidgin-2.10.7/pidgin/win32/nsis/nsis_translations.desktop.in pidgin-2.10.7-nonprism/pidgin/win32/nsis/nsis_translations.desktop.in
---- pidgin-2.10.7/pidgin/win32/nsis/nsis_translations.desktop.in 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/nsis/nsis_translations.desktop.in 1969-12-31 21:00:00.000000000 -0300
-@@ -1,62 +0,0 @@
--[Desktop Entry]
--Encoding=UTF-8
--
--_INSTALLERISRUNNING=The installer is already running.
--_PIDGINISRUNNING=An instance of Pidgin is currently running. Please exit Pidgin and try again.
--
--# "Next >" appears on a button on the License Page of the Installer
--_PIDGINLICENSEBUTTON=Next >
--# $(^Name) is the current Version name (e.g. Pidgin 2.7.0). $_CLICK will become a translated version of "Click Next to continue." DO NOT translate the CLICK in $_CLICK. It will break the installer.
--_PIDGINLICENSEBOTTOMTEXT=$(^Name) is released under the GNU General Public License (GPL). The license is provided here for information purposes only. $_CLICK
--
--#Installer Subsection Text
--_PIDGINSECTIONTITLE=Pidgin Instant Messaging Client (required)
--#Installer Subsection Text
--_GTKSECTIONTITLE=GTK+ Runtime (required if not present)
--#Installer Subsection Text
--_PIDGINSHORTCUTSSECTIONTITLE=Shortcuts
--#Installer Subsection Text
--_PIDGINDESKTOPSHORTCUTSECTIONTITLE=Desktop
--#Installer Subsection Text
--_PIDGINSTARTMENUSHORTCUTSECTIONTITLE=Start Menu
--#Installer Subsection Text
--_TRANSLATIONSSECTIONTITLE=Localizations
--#Installer Subsection Detailed Description
--_PIDGINSECTIONDESCRIPTION=Core Pidgin files and dlls
--#Installer Subsection Detailed Description
--_PIDGINSHORTCUTSSECTIONDESCRIPTION=Shortcuts for starting Pidgin
--#Installer Subsection Detailed Description
--_PIDGINDESKTOPSHORTCUTDESC=Create a shortcut to Pidgin on the Desktop
--#Installer Subsection Detailed Description
--_PIDGINSTARTMENUSHORTCUTDESC=Create a Start Menu entry for Pidgin
--#Installer Subsection Detailed Description
--_GTKSECTIONDESCRIPTION=A multi-platform GUI toolkit, used by Pidgin
--#Installer Subsection Text
--_DEBUGSYMBOLSSECTIONTITLE=Debug Symbols (for reporting crashes)
--
--# Text displayed on Installer Finish Page
--_PIDGINFINISHVISITWEBSITE=Visit the Pidgin Web Page
--
--_PIDGINPROMPTCONTINUEWITHOUTUNINSTALL=Unable to uninstall the currently installed version of Pidgin. The new version will be installed without removing the currently installed version.
--
--_PIDGINPROMPTFORCENOGTK=Pidgin requires a compatible GTK+ Runtime (which doesn't appear to be already present).$\rAre you sure you want to skip installing the GTK+ Runtime?
--
--#Installer Subsection Text
--_URIHANDLERSSECTIONTITLE=URI Handlers
--
--#Installer Subsection Text
--_PIDGINSPELLCHECKSECTIONTITLE=Spellchecking Support
--# $R3 will display the URL that the Dictionary failed to download from
--_PIDGINSPELLCHECKERROR=Error Installing Spellchecking ($R3).$\rIf retrying fails, manual installation instructions are at: http://developer.pidgin.im/wiki/Installing%20Pidgin#manual_win32_spellcheck_installation
--#Installer Subsection Detailed Description
--_PIDGINSPELLCHECKSECTIONDESCRIPTION=Support for Spellchecking. (Internet connection required for installation)
--
--# $R2 will display the URL that the Debug Symbols failed to download from
--_PIDGINDEBUGSYMBOLSERROR=Error Installing Debug Symbols ($R2).$\rIf retrying fails, you may need to use the 'Offline Installer' from http://pidgin.im/download/windows/ .
--
--# $R2 will display the URL that the GTK+ Runtime failed to download from
--_PIDGINGTKDOWNLOADERROR=Error Downloading the GTK+ Runtime ($R2).$\rThis is required for Pidgin to function; if retrying fails, you may need to use the 'Offline Installer' from http://pidgin.im/download/windows/ .
--
--_PIDGINUNINSTALLERROR1=The uninstaller could not find registry entries for Pidgin.$\rIt is likely that another user installed this application.
--_PIDGINUNINSTALLERROR2=You do not have permission to uninstall this application.
--
-diff -Nur pidgin-2.10.7/pidgin/win32/nsis/pidgin-installer.nsi pidgin-2.10.7-nonprism/pidgin/win32/nsis/pidgin-installer.nsi
---- pidgin-2.10.7/pidgin/win32/nsis/pidgin-installer.nsi 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/nsis/pidgin-installer.nsi 1969-12-31 21:00:00.000000000 -0300
-@@ -1,1339 +0,0 @@
--; Installer script for win32 Pidgin
--; Original Author: Herman Bloggs <hermanator12002@yahoo.com>
--; Updated By: Daniel Atallah <daniel_atallah@yahoo.com>
--
--; NOTE: this .NSI script is intended for NSIS 2.27+
--;
--
--;--------------------------------
--;Global Variables
--Var name
--Var STARTUP_RUN_KEY
--Var CURRENT_GTK_STATE
--Var WARNED_GTK_STATE
--
--;--------------------------------
--;Configuration
--
--;The name var is set in .onInit
--Name $name
--
--!ifdef OFFLINE_INSTALLER
--OutFile "pidgin-${PIDGIN_VERSION}-offline.exe"
--!else
--OutFile "pidgin-${PIDGIN_VERSION}.exe"
--!endif
--
--SetCompressor /SOLID lzma
--ShowInstDetails show
--ShowUninstDetails show
--SetDateSave on
--RequestExecutionLevel highest
--
--; $name and $INSTDIR are set in .onInit function..
--
--!include "MUI.nsh"
--!include "Sections.nsh"
--!include "LogicLib.nsh"
--!include "Memento.nsh"
--
--!include "FileFunc.nsh"
--!insertmacro GetParameters
--!insertmacro GetOptions
--!insertmacro GetParent
--
--!include "WordFunc.nsh"
--!insertmacro VersionCompare
--!insertmacro WordFind
--!insertmacro un.WordFind
--
--!include "TextFunc.nsh"
--
--;--------------------------------
--;Defines
--
--!define PIDGIN_NSIS_INCLUDE_PATH "."
--
--; Remove these and the stuff that uses them at some point
--!define OLD_GAIM_REG_KEY "SOFTWARE\gaim"
--!define OLD_GAIM_UNINSTALL_KEY "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Gaim"
--!define OLD_GAIM_UNINST_EXE "gaim-uninst.exe"
--
--!define PIDGIN_REG_KEY "SOFTWARE\pidgin"
--!define PIDGIN_UNINSTALL_KEY "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Pidgin"
--
--!define HKLM_APP_PATHS_KEY "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\pidgin.exe"
--!define STARTUP_RUN_KEY "SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
--!define PIDGIN_UNINST_EXE "pidgin-uninst.exe"
--
--!define GTK_MIN_VERSION "2.14.0"
--!define PERL_REG_KEY "SOFTWARE\Perl"
--!define PERL_DLL "perl510.dll"
--
--!define DOWNLOADER_URL "https://pidgin.im/win32/download_redir.php?version=${PIDGIN_VERSION}"
--
--!define MEMENTO_REGISTRY_ROOT HKLM
--!define MEMENTO_REGISTRY_KEY "${PIDGIN_UNINSTALL_KEY}"
--
--;--------------------------------
--;Version resource
--VIProductVersion "${PIDGIN_PRODUCT_VERSION}"
--VIAddVersionKey "ProductName" "Pidgin"
--VIAddVersionKey "FileVersion" "${PIDGIN_VERSION}"
--VIAddVersionKey "ProductVersion" "${PIDGIN_VERSION}"
--VIAddVersionKey "LegalCopyright" ""
--!ifdef OFFLINE_INSTALLER
--VIAddVersionKey "FileDescription" "Pidgin Installer (Offline)"
--!else
--VIAddVersionKey "FileDescription" "Pidgin Installer"
--!endif
--
--;--------------------------------
--;Reserve files used in .onInit
--;for faster start-up
--ReserveFile "${NSISDIR}\Plugins\System.dll"
--ReserveFile "${NSISDIR}\Plugins\UserInfo.dll"
--!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
--!insertmacro MUI_RESERVEFILE_LANGDLL
--
--;--------------------------------
--;Modern UI Configuration
--
-- !define MUI_ICON ".\pixmaps\pidgin-install.ico"
-- !define MUI_UNICON ".\pixmaps\pidgin-install.ico"
-- !define MUI_WELCOMEFINISHPAGE_BITMAP ".\pixmaps\pidgin-intro.bmp"
-- !define MUI_HEADERIMAGE
-- !define MUI_HEADERIMAGE_BITMAP ".\pixmaps\pidgin-header.bmp"
--
-- ; Alter License section
-- !define MUI_LICENSEPAGE_BUTTON $(PIDGINLICENSEBUTTON)
-- !define MUI_LICENSEPAGE_TEXT_BOTTOM $(PIDGINLICENSEBOTTOMTEXT)
--
-- !define MUI_LANGDLL_REGISTRY_ROOT "HKCU"
-- !define MUI_LANGDLL_REGISTRY_KEY ${PIDGIN_REG_KEY}
-- !define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language"
--
-- !define MUI_COMPONENTSPAGE_SMALLDESC
-- !define MUI_ABORTWARNING
--
-- ;Finish Page config
-- !define MUI_FINISHPAGE_NOAUTOCLOSE
-- ;!define MUI_FINISHPAGE_RUN "$INSTDIR\pidgin.exe"
-- ;!define MUI_FINISHPAGE_RUN_NOTCHECKED
-- !define MUI_FINISHPAGE_LINK $(PIDGINFINISHVISITWEBSITE)
-- !define MUI_FINISHPAGE_LINK_LOCATION "http://pidgin.im"
--
--;--------------------------------
--;Pages
--
-- !define MUI_PAGE_CUSTOMFUNCTION_PRE preWelcomePage
-- !insertmacro MUI_PAGE_WELCOME
-- !insertmacro MUI_PAGE_LICENSE "../../../COPYING"
-- !insertmacro MUI_PAGE_COMPONENTS
--
-- ; Pidgin install dir page
-- !insertmacro MUI_PAGE_DIRECTORY
--
-- !insertmacro MUI_PAGE_INSTFILES
-- !insertmacro MUI_PAGE_FINISH
--
-- !insertmacro MUI_UNPAGE_WELCOME
-- !insertmacro MUI_UNPAGE_CONFIRM
-- !insertmacro MUI_UNPAGE_INSTFILES
-- !insertmacro MUI_UNPAGE_FINISH
--
--;--------------------------------
--;Languages
--
-- !include "${PIDGIN_NSIS_INCLUDE_PATH}\langmacros.nsh"
--
--;--------------------------------
--
--;;;;;;;;;;;;;;;;;;;;;;;;;;;;
--;; Start Install Sections ;;
--;;;;;;;;;;;;;;;;;;;;;;;;;;;;
--
--;--------------------------------
--;Uninstall any old version of Pidgin (or Gaim)
--
--Section -SecUninstallOldPidgin
-- ; Check install rights..
-- Call CheckUserInstallRights
-- Pop $R0
--
-- ;First try to uninstall Pidgin
-- StrCpy $R4 ${PIDGIN_REG_KEY}
-- StrCpy $R5 ${PIDGIN_UNINSTALL_KEY}
-- StrCpy $R6 ${PIDGIN_UNINST_EXE}
-- StrCpy $R7 "Pidgin"
--
-- start_comparison:
-- ;If pidgin is currently set to run on startup,
-- ; save the section of the Registry where the setting is before uninstalling,
-- ; so we can put it back after installing the new version
-- ClearErrors
-- ReadRegStr $STARTUP_RUN_KEY HKCU "${STARTUP_RUN_KEY}" $R7
-- IfErrors +3
-- StrCpy $STARTUP_RUN_KEY "HKCU"
-- Goto +5
-- ClearErrors
-- ReadRegStr $STARTUP_RUN_KEY HKLM "${STARTUP_RUN_KEY}" $R7
-- IfErrors +2
-- StrCpy $STARTUP_RUN_KEY "HKLM"
--
-- StrCmp $R0 "HKLM" compare_hklm
-- StrCmp $R0 "HKCU" compare_hkcu done
--
-- compare_hkcu:
-- ReadRegStr $R1 HKCU $R4 ""
-- ReadRegStr $R2 HKCU $R4 "Version"
-- ReadRegStr $R3 HKCU "$R5" "UninstallString"
-- Goto try_uninstall
--
-- compare_hklm:
-- ReadRegStr $R1 HKLM $R4 ""
-- ReadRegStr $R2 HKLM $R4 "Version"
-- ReadRegStr $R3 HKLM "$R5" "UninstallString"
--
-- ; If a previous version exists, remove it
-- try_uninstall:
-- StrCmp $R1 "" no_version_found
-- ; Version key started with 0.60a3. Prior versions can't be
-- ; automatically uninstalled.
-- StrCmp $R2 "" uninstall_problem
-- ; Check if we have uninstall string..
-- IfFileExists $R3 0 uninstall_problem
-- ; Have uninstall string, go ahead and uninstall.
-- SetOverwrite on
-- ; Need to copy uninstaller outside of the install dir
-- ClearErrors
-- CopyFiles /SILENT $R3 "$TEMP\$R6"
-- SetOverwrite off
-- IfErrors uninstall_problem
-- ; Ready to uninstall..
-- ClearErrors
-- ExecWait '"$TEMP\$R6" /S /UPGRADE=1 _?=$R1'
-- IfErrors exec_error
-- Delete "$TEMP\$R6"
-- Goto done
--
-- exec_error:
-- Delete "$TEMP\$R6"
-- Goto uninstall_problem
--
-- no_version_found:
-- ;We've already tried to fallback to an old gaim instance
-- StrCmp $R7 "Gaim" done
-- ; If we couldn't uninstall Pidgin, try to uninstall Gaim
-- StrCpy $STARTUP_RUN_KEY "NONE"
-- StrCpy $R4 ${OLD_GAIM_REG_KEY}
-- StrCpy $R5 ${OLD_GAIM_UNINSTALL_KEY}
-- StrCpy $R6 ${OLD_GAIM_UNINST_EXE}
-- StrCpy $R7 "Gaim"
-- Goto start_comparison
--
-- uninstall_problem:
-- ; We can't uninstall. Either the user must manually uninstall or we ignore and reinstall over it.
-- MessageBox MB_OKCANCEL $(PIDGINPROMPTCONTINUEWITHOUTUNINSTALL) /SD IDOK IDOK done
-- Quit
-- done:
--SectionEnd
--
--
--;--------------------------------
--;GTK+ Runtime Install Section
--
--Section $(GTKSECTIONTITLE) SecGtk
--
-- InitPluginsDir
-- StrCpy $R1 "$PLUGINSDIR\gtk.zip"
--!ifdef OFFLINE_INSTALLER
--
-- SetOutPath $PLUGINSDIR
-- File /oname=gtk.zip ".\gtk-runtime-${GTK_INSTALL_VERSION}.zip"
--
--!else
--
-- ; We need to download the GTK+ runtime
-- retry:
-- StrCpy $R2 "${DOWNLOADER_URL}&gtk_version=${GTK_INSTALL_VERSION}&dl_pkg=gtk"
-- DetailPrint "Downloading GTK+ Runtime ... ($R2)"
-- NSISdl::download /TIMEOUT=10000 $R2 $R1
-- Pop $R0
-- ;StrCmp $R0 "cancel" done
-- StrCmp $R0 "success" 0 prompt_retry
--
-- Push "${GTK_SHA1SUM}"
-- Push "$R1" ; Filename
-- Call CheckSHA1Sum
-- Pop $R0
--
-- StrCmp "$R0" "0" extract
-- prompt_retry:
-- MessageBox MB_RETRYCANCEL "$(PIDGINGTKDOWNLOADERROR)" /SD IDCANCEL IDRETRY retry IDCANCEL done
--
-- extract:
--!endif
--
-- ;Delete the old Gtk directory
-- RMDir /r "$INSTDIR\Gtk"
--
-- SetOutPath "$INSTDIR"
-- nsisunz::UnzipToLog $R1 "$INSTDIR"
-- Pop $R0
-- StrCmp $R0 "success" +2
-- DetailPrint "$R0" ;print error message to log
--
--!ifndef OFFLINE_INSTALLER
-- done:
--!endif
--SectionEnd ; end of GTK+ section
--
--;--------------------------------
--;Pidgin Install Section
--
--Section $(PIDGINSECTIONTITLE) SecPidgin
-- SectionIn 1 RO
--
-- ; Check install rights..
-- Call CheckUserInstallRights
-- Pop $R0
--
-- StrCmp $R0 "NONE" pidgin_install_files
-- StrCmp $R0 "HKLM" pidgin_hklm pidgin_hkcu
--
-- pidgin_hklm:
-- WriteRegStr HKLM "${HKLM_APP_PATHS_KEY}" "" "$INSTDIR\pidgin.exe"
-- WriteRegStr HKLM "${HKLM_APP_PATHS_KEY}" "Path" "$INSTDIR\Gtk\bin"
-- WriteRegStr HKLM ${PIDGIN_REG_KEY} "" "$INSTDIR"
-- WriteRegStr HKLM ${PIDGIN_REG_KEY} "Version" "${PIDGIN_VERSION}"
-- WriteRegStr HKLM "${PIDGIN_UNINSTALL_KEY}" "DisplayIcon" "$INSTDIR\pidgin.exe"
-- WriteRegStr HKLM "${PIDGIN_UNINSTALL_KEY}" "DisplayName" "Pidgin"
-- WriteRegStr HKLM "${PIDGIN_UNINSTALL_KEY}" "DisplayVersion" "${PIDGIN_VERSION}"
-- WriteRegStr HKLM "${PIDGIN_UNINSTALL_KEY}" "HelpLink" "http://developer.pidgin.im/wiki/Using Pidgin"
-- WriteRegDWORD HKLM "${PIDGIN_UNINSTALL_KEY}" "NoModify" 1
-- WriteRegDWORD HKLM "${PIDGIN_UNINSTALL_KEY}" "NoRepair" 1
-- WriteRegStr HKLM "${PIDGIN_UNINSTALL_KEY}" "UninstallString" "$INSTDIR\${PIDGIN_UNINST_EXE}"
-- ; Sets scope of the desktop and Start Menu entries for all users.
-- SetShellVarContext "all"
-- Goto pidgin_install_files
--
-- pidgin_hkcu:
-- WriteRegStr HKCU ${PIDGIN_REG_KEY} "" "$INSTDIR"
-- WriteRegStr HKCU ${PIDGIN_REG_KEY} "Version" "${PIDGIN_VERSION}"
-- WriteRegStr HKCU "${PIDGIN_UNINSTALL_KEY}" "DisplayIcon" "$INSTDIR\pidgin.exe"
-- WriteRegStr HKCU "${PIDGIN_UNINSTALL_KEY}" "DisplayName" "Pidgin"
-- WriteRegStr HKCU "${PIDGIN_UNINSTALL_KEY}" "DisplayVersion" "${PIDGIN_VERSION}"
-- WriteRegStr HKCU "${PIDGIN_UNINSTALL_KEY}" "HelpLink" "http://developer.pidgin.im/wiki/Using Pidgin"
-- WriteRegDWORD HKCU "${PIDGIN_UNINSTALL_KEY}" "NoModify" 1
-- WriteRegDWORD HKCU "${PIDGIN_UNINSTALL_KEY}" "NoRepair" 1
-- WriteRegStr HKCU "${PIDGIN_UNINSTALL_KEY}" "UninstallString" "$INSTDIR\${PIDGIN_UNINST_EXE}"
-- Goto pidgin_install_files
--
-- pidgin_install_files:
-- SetOutPath "$INSTDIR"
-- ; Pidgin files
-- SetOverwrite on
--
-- ;Delete old liboscar and libjabber since they tend to be problematic
-- Delete "$INSTDIR\plugins\liboscar.dll"
-- Delete "$INSTDIR\plugins\libjabber.dll"
--
-- File /r /x locale /x Gtk ..\..\..\${PIDGIN_INSTALL_DIR}\*.*
--
-- ; Check if Perl is installed, if so add it to the AppPaths
-- ReadRegStr $R2 HKLM ${PERL_REG_KEY} ""
-- StrCmp $R2 "" 0 perl_exists
-- ReadRegStr $R2 HKCU ${PERL_REG_KEY} ""
-- StrCmp $R2 "" perl_done perl_exists
--
-- perl_exists:
-- IfFileExists "$R2\bin\${PERL_DLL}" 0 perl_done
-- StrCmp $R0 "HKLM" 0 perl_done
-- ReadRegStr $R3 HKLM "${HKLM_APP_PATHS_KEY}" "Path"
-- WriteRegStr HKLM "${HKLM_APP_PATHS_KEY}" "Path" "$R3;$R2\bin"
--
-- perl_done:
--
-- SetOutPath "$INSTDIR"
--
-- ; If we don't have install rights we're done
-- StrCmp $R0 "NONE" done
-- SetOverwrite off
--
-- ; write out uninstaller
-- SetOverwrite on
-- WriteUninstaller "$INSTDIR\${PIDGIN_UNINST_EXE}"
-- SetOverwrite off
--
-- ; If we previously had pidgin set up to run on startup, make it do so again
-- StrCmp $STARTUP_RUN_KEY "HKCU" +1 +2
-- WriteRegStr HKCU "${STARTUP_RUN_KEY}" "Pidgin" "$INSTDIR\pidgin.exe"
-- StrCmp $STARTUP_RUN_KEY "HKLM" +1 +2
-- WriteRegStr HKLM "${STARTUP_RUN_KEY}" "Pidgin" "$INSTDIR\pidgin.exe"
--
-- done:
--SectionEnd ; end of default Pidgin section
--
--;--------------------------------
--;Shortcuts
--
--SectionGroup /e $(PIDGINSHORTCUTSSECTIONTITLE) SecShortcuts
-- Section /o $(PIDGINDESKTOPSHORTCUTSECTIONTITLE) SecDesktopShortcut
-- SetOverwrite on
-- CreateShortCut "$DESKTOP\Pidgin.lnk" "$INSTDIR\pidgin.exe"
-- SetOverwrite off
-- SectionEnd
-- Section $(PIDGINSTARTMENUSHORTCUTSECTIONTITLE) SecStartMenuShortcut
-- SetOverwrite on
-- CreateShortCut "$SMPROGRAMS\Pidgin.lnk" "$INSTDIR\pidgin.exe"
-- SetOverwrite off
-- SectionEnd
--SectionGroupEnd
--
--;--------------------------------
--;URI Handling
--
--!macro URI_SECTION proto
-- Section /o "${proto}:" SecURI_${proto}
-- Push "${proto}"
-- Call RegisterURIHandler
-- SectionEnd
--!macroend
--SectionGroup /e $(URIHANDLERSSECTIONTITLE) SecURIHandlers
-- !insertmacro URI_SECTION "aim"
-- !insertmacro URI_SECTION "msnim"
-- !insertmacro URI_SECTION "myim"
-- !insertmacro URI_SECTION "ymsgr"
-- !insertmacro URI_SECTION "xmpp"
--SectionGroupEnd
--
--;--------------------------------
--;Translations
--
--!macro LANG_SECTION lang
-- ${MementoUnselectedSection} "${lang}" SecLang_${lang}
-- SetOutPath "$INSTDIR\locale\${lang}\LC_MESSAGES"
-- File "..\..\..\${PIDGIN_INSTALL_DIR}\locale\${lang}\LC_MESSAGES\*.mo"
-- SetOutPath "$INSTDIR"
-- ${MementoSectionEnd}
--!macroend
--SectionGroup $(TRANSLATIONSSECTIONTITLE) SecTranslations
-- # pidgin-translations is generated based on the contents of the locale directory
-- !include "pidgin-translations.nsh"
--SectionGroupEnd
--${MementoSectionDone}
--
--;--------------------------------
--;Spell Checking
--
--!macro SPELLCHECK_SECTION lang lang_name lang_file
-- Section /o "${lang_name}" SecSpell_${lang}
-- Push ${lang_file}
-- Push ${lang}
-- Call InstallDict
-- SectionEnd
--!macroend
--SectionGroup $(PIDGINSPELLCHECKSECTIONTITLE) SecSpellCheck
-- !include "pidgin-spellcheck.nsh"
--SectionGroupEnd
--
--Section /o $(DEBUGSYMBOLSSECTIONTITLE) SecDebugSymbols
--
-- InitPluginsDir
-- StrCpy $R1 "$PLUGINSDIR\dbgsym.zip"
--!ifdef OFFLINE_INSTALLER
--
-- SetOutPath $PLUGINSDIR
-- File /oname=dbgsym.zip "..\..\..\pidgin-${PIDGIN_VERSION}-dbgsym.zip"
--
--!else
--
-- ; We need to download the debug symbols
-- retry:
-- StrCpy $R2 "${DOWNLOADER_URL}&dl_pkg=dbgsym"
-- DetailPrint "Downloading Debug Symbols... ($R2)"
-- NSISdl::download /TIMEOUT=10000 $R2 $R1
-- Pop $R0
-- StrCmp $R0 "cancel" done
-- StrCmp $R0 "success" 0 prompt_retry
--
-- Push "${DEBUG_SYMBOLS_SHA1SUM}"
-- Push "$R1" ; Filename
-- Call CheckSHA1Sum
-- Pop $R0
--
-- StrCmp "$R0" "0" extract
-- prompt_retry:
-- MessageBox MB_RETRYCANCEL "$(PIDGINDEBUGSYMBOLSERROR)" /SD IDCANCEL IDRETRY retry IDCANCEL done
--
-- extract:
--!endif
--
-- SetOutPath "$INSTDIR"
-- nsisunz::UnzipToLog $R1 "$INSTDIR"
-- Pop $R0
-- StrCmp $R0 "success" +2
-- DetailPrint "$R0" ;print error message to log
--
--!ifndef OFFLINE_INSTALLER
-- done:
--!endif
--SectionEnd
--
--;--------------------------------
--;Uninstaller Section
--
--
--Section Uninstall
-- Call un.CheckUserInstallRights
-- Pop $R0
-- StrCmp $R0 "NONE" no_rights
-- StrCmp $R0 "HKCU" try_hkcu try_hklm
--
-- try_hkcu:
-- ReadRegStr $R0 HKCU ${PIDGIN_REG_KEY} ""
-- StrCmp $R0 $INSTDIR 0 cant_uninstall
-- ; HKCU install path matches our INSTDIR so uninstall
-- DeleteRegKey HKCU ${PIDGIN_REG_KEY}
-- DeleteRegKey HKCU "${PIDGIN_UNINSTALL_KEY}"
-- Goto cont_uninstall
--
-- try_hklm:
-- ReadRegStr $R0 HKLM ${PIDGIN_REG_KEY} ""
-- StrCmp $R0 $INSTDIR 0 try_hkcu
-- ; HKLM install path matches our INSTDIR so uninstall
-- DeleteRegKey HKLM ${PIDGIN_REG_KEY}
-- DeleteRegKey HKLM "${PIDGIN_UNINSTALL_KEY}"
-- DeleteRegKey HKLM "${HKLM_APP_PATHS_KEY}"
-- ; Sets start menu and desktop scope to all users..
-- SetShellVarContext "all"
--
-- cont_uninstall:
-- ; The WinPrefs plugin may have left this behind..
-- DeleteRegValue HKCU "${STARTUP_RUN_KEY}" "Pidgin"
-- DeleteRegValue HKLM "${STARTUP_RUN_KEY}" "Pidgin"
-- ; Remove Language preference info
-- DeleteRegValue HKCU "${PIDGIN_REG_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}"
--
-- ; Remove any URI handlers
-- ; I can't think of an easy way to maintain a list in a single place
-- Push "aim"
-- Call un.UnregisterURIHandler
-- Push "msnim"
-- Call un.UnregisterURIHandler
-- Push "myim"
-- Call un.UnregisterURIHandler
-- Push "ymsgr"
-- Call un.UnregisterURIHandler
-- Push "xmpp"
-- Call un.UnregisterURIHandler
--
-- Delete "$INSTDIR\ca-certs\AddTrust_External_Root.pem"
-- Delete "$INSTDIR\ca-certs\America_Online_Root_Certification_Authority_1.pem"
-- Delete "$INSTDIR\ca-certs\AOL_Member_CA.pem"
-- Delete "$INSTDIR\ca-certs\CAcert_Class3.pem"
-- Delete "$INSTDIR\ca-certs\CAcert_Root.pem"
-- Delete "$INSTDIR\ca-certs\Deutsche_Telekom_Root_CA_2.pem"
-- Delete "$INSTDIR\ca-certs\DigiCertHighAssuranceCA-3.pem"
-- Delete "$INSTDIR\ca-certs\Entrust.net_Secure_Server_CA.pem"
-- Delete "$INSTDIR\ca-certs\Equifax_Secure_CA.pem"
-- Delete "$INSTDIR\ca-certs\Equifax_Secure_Global_eBusiness_CA-1.pem"
-- Delete "$INSTDIR\ca-certs\Go_Daddy_Class_2_CA.pem"
-- Delete "$INSTDIR\ca-certs\GTE_CyberTrust_Global_Root.pem"
-- Delete "$INSTDIR\ca-certs\Microsoft_Internet_Authority.pem"
-- Delete "$INSTDIR\ca-certs\Microsoft_Internet_Authority_2010.pem"
-- Delete "$INSTDIR\ca-certs\Microsoft_Secure_Server_Authority.pem"
-- Delete "$INSTDIR\ca-certs\Microsoft_Secure_Server_Authority_2010.pem"
-- Delete "$INSTDIR\ca-certs\StartCom_Certification_Authority.pem"
-- Delete "$INSTDIR\ca-certs\StartCom_Free_SSL_CA.pem"
-- Delete "$INSTDIR\ca-certs\Thawte_Premium_Server_CA.pem"
-- Delete "$INSTDIR\ca-certs\Thawte_Primary_Root_CA.pem"
-- Delete "$INSTDIR\ca-certs\ValiCert_Class_2_VA.crt"
-- Delete "$INSTDIR\ca-certs\VeriSign_Class3_Extended_Validation_CA.pem"
-- Delete "$INSTDIR\ca-certs\Verisign_Class3_Primary_CA.pem"
-- Delete "$INSTDIR\ca-certs\VeriSign_Class_3_Public_Primary_Certification_Authority_-_G2.pem"
-- Delete "$INSTDIR\ca-certs\VeriSign_Class_3_Public_Primary_Certification_Authority_-_G5.pem"
-- Delete "$INSTDIR\ca-certs\VeriSign_Class_3_Public_Primary_Certification_Authority_-_G5_2.pem"
-- Delete "$INSTDIR\ca-certs\VeriSign_International_Server_Class_3_CA.pem"
-- Delete "$INSTDIR\ca-certs\Verisign_RSA_Secure_Server_CA.pem"
-- RMDir "$INSTDIR\ca-certs"
-- RMDir /r "$INSTDIR\locale"
-- RMDir /r "$INSTDIR\pixmaps"
-- Delete "$INSTDIR\plugins\autoaccept.dll"
-- Delete "$INSTDIR\plugins\buddynote.dll"
-- Delete "$INSTDIR\plugins\convcolors.dll"
-- Delete "$INSTDIR\plugins\extplacement.dll"
-- Delete "$INSTDIR\plugins\gtkbuddynote.dll"
-- Delete "$INSTDIR\plugins\history.dll"
-- Delete "$INSTDIR\plugins\iconaway.dll"
-- Delete "$INSTDIR\plugins\idle.dll"
-- Delete "$INSTDIR\plugins\joinpart.dll"
-- Delete "$INSTDIR\plugins\libaim.dll"
-- Delete "$INSTDIR\plugins\libbonjour.dll"
-- Delete "$INSTDIR\plugins\libgg.dll"
-- Delete "$INSTDIR\plugins\libicq.dll"
-- Delete "$INSTDIR\plugins\libirc.dll"
-- Delete "$INSTDIR\plugins\libmsn.dll"
-- Delete "$INSTDIR\plugins\libmxit.dll"
-- Delete "$INSTDIR\plugins\libmyspace.dll"
-- Delete "$INSTDIR\plugins\libnapster.dll"
-- Delete "$INSTDIR\plugins\libnovell.dll"
-- Delete "$INSTDIR\plugins\libsametime.dll"
-- Delete "$INSTDIR\plugins\libsilc.dll"
-- Delete "$INSTDIR\plugins\libsimple.dll"
-- Delete "$INSTDIR\plugins\libtoc.dll"
-- Delete "$INSTDIR\plugins\libyahoo.dll"
-- Delete "$INSTDIR\plugins\libyahoojp.dll"
-- Delete "$INSTDIR\plugins\libxmpp.dll"
-- Delete "$INSTDIR\plugins\log_reader.dll"
-- Delete "$INSTDIR\plugins\markerline.dll"
-- Delete "$INSTDIR\plugins\newline.dll"
-- Delete "$INSTDIR\plugins\notify.dll"
-- Delete "$INSTDIR\plugins\offlinemsg.dll"
-- Delete "$INSTDIR\plugins\perl.dll"
-- Delete "$INSTDIR\plugins\pidginrc.dll"
-- Delete "$INSTDIR\plugins\psychic.dll"
-- Delete "$INSTDIR\plugins\relnot.dll"
-- Delete "$INSTDIR\plugins\sendbutton.dll"
-- Delete "$INSTDIR\plugins\spellchk.dll"
-- Delete "$INSTDIR\plugins\ssl-nss.dll"
-- Delete "$INSTDIR\plugins\ssl.dll"
-- Delete "$INSTDIR\plugins\statenotify.dll"
-- Delete "$INSTDIR\plugins\tcl.dll"
-- Delete "$INSTDIR\plugins\themeedit.dll"
-- Delete "$INSTDIR\plugins\ticker.dll"
-- Delete "$INSTDIR\plugins\timestamp.dll"
-- Delete "$INSTDIR\plugins\timestamp_format.dll"
-- Delete "$INSTDIR\plugins\win2ktrans.dll"
-- Delete "$INSTDIR\plugins\winprefs.dll"
-- Delete "$INSTDIR\plugins\xmppconsole.dll"
-- Delete "$INSTDIR\plugins\xmppdisco.dll"
-- RMDir /r "$INSTDIR\plugins\perl"
-- RMDir "$INSTDIR\plugins"
-- RMDir /r "$INSTDIR\sasl2"
-- Delete "$INSTDIR\sounds\purple\alert.wav"
-- Delete "$INSTDIR\sounds\purple\login.wav"
-- Delete "$INSTDIR\sounds\purple\logout.wav"
-- Delete "$INSTDIR\sounds\purple\receive.wav"
-- Delete "$INSTDIR\sounds\purple\send.wav"
-- RMDir "$INSTDIR\sounds\purple"
-- RMDir "$INSTDIR\sounds"
-- Delete "$INSTDIR\spellcheck\libenchant.dll"
-- Delete "$INSTDIR\spellcheck\libgtkspell-0.dll"
-- Delete "$INSTDIR\spellcheck\lib\enchant\libenchant_aspell.dll"
-- Delete "$INSTDIR\spellcheck\lib\enchant\libenchant_ispell.dll"
-- Delete "$INSTDIR\spellcheck\lib\enchant\libenchant_myspell.dll"
-- RMDir "$INSTDIR\spellcheck\lib\enchant"
-- RMDir "$INSTDIR\spellcheck\lib"
-- RMDir "$INSTDIR\spellcheck"
-- Delete "$INSTDIR\freebl3.dll"
-- Delete "$INSTDIR\libjabber.dll"
-- Delete "$INSTDIR\libnspr4.dll"
-- Delete "$INSTDIR\libmeanwhile-1.dll"
-- Delete "$INSTDIR\liboscar.dll"
-- Delete "$INSTDIR\libplc4.dll"
-- Delete "$INSTDIR\libplds4.dll"
-- Delete "$INSTDIR\libpurple.dll"
-- Delete "$INSTDIR\libsasl.dll"
-- Delete "$INSTDIR\libsilc-1-1-2.dll"
-- Delete "$INSTDIR\libsilcclient-1-1-3.dll"
-- Delete "$INSTDIR\libssp-0.dll"
-- Delete "$INSTDIR\libxml2-2.dll"
-- Delete "$INSTDIR\libymsg.dll"
-- Delete "$INSTDIR\nss3.dll"
-- Delete "$INSTDIR\nssutil3.dll"
-- Delete "$INSTDIR\pidgin.dll"
-- Delete "$INSTDIR\pidgin.exe"
-- Delete "$INSTDIR\smime3.dll"
-- Delete "$INSTDIR\softokn3.dll"
-- Delete "$INSTDIR\sqlite3.dll"
-- Delete "$INSTDIR\ssl3.dll"
-- Delete "$INSTDIR\${PIDGIN_UNINST_EXE}"
-- Delete "$INSTDIR\exchndl.dll"
-- Delete "$INSTDIR\install.log"
--
-- ; Remove the debug symbols
-- RMDir /r "$INSTDIR\pidgin-${PIDGIN_VERSION}-dbgsym"
--
-- ; Remove the local GTK+ copy (if we're not just upgrading)
-- ${GetParameters} $R0
-- ClearErrors
-- ${GetOptions} "$R0" "/UPGRADE=" $R1
-- IfErrors +2
-- StrCmp $R1 "1" upgrade_done
-- RMDir /r "$INSTDIR\Gtk"
-- ; Remove the downloaded spellcheck dictionaries (if we're not just upgrading)
-- RMDir /r "$INSTDIR\spellcheck"
-- upgrade_done:
--
-- ;Try to remove Pidgin install dir (only if empty)
-- RMDir "$INSTDIR"
--
-- ; Shortcuts..
-- Delete "$DESKTOP\Pidgin.lnk"
-- Delete "$SMPROGRAMS\Pidgin.lnk"
--
-- Goto done
--
-- cant_uninstall:
-- MessageBox MB_OK $(PIDGINUNINSTALLERROR1) /SD IDOK
-- Quit
--
-- no_rights:
-- MessageBox MB_OK $(PIDGINUNINSTALLERROR2) /SD IDOK
-- Quit
--
-- done:
--SectionEnd ; end of uninstall section
--
--;--------------------------------
--;Descriptions
--!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
-- !insertmacro MUI_DESCRIPTION_TEXT ${SecPidgin} \
-- $(PIDGINSECTIONDESCRIPTION)
-- !insertmacro MUI_DESCRIPTION_TEXT ${SecGtk} \
-- $(GTKSECTIONDESCRIPTION)
--
-- !insertmacro MUI_DESCRIPTION_TEXT ${SecShortcuts} \
-- $(PIDGINSHORTCUTSSECTIONDESCRIPTION)
-- !insertmacro MUI_DESCRIPTION_TEXT ${SecDesktopShortcut} \
-- $(PIDGINDESKTOPSHORTCUTDESC)
-- !insertmacro MUI_DESCRIPTION_TEXT ${SecStartMenuShortcut} \
-- $(PIDGINSTARTMENUSHORTCUTDESC)
--
-- !insertmacro MUI_DESCRIPTION_TEXT ${SecSpellCheck} \
-- $(PIDGINSPELLCHECKSECTIONDESCRIPTION)
--
--!insertmacro MUI_FUNCTION_DESCRIPTION_END
--
--;--------------------------------
--;Functions
--
--; Default the URI handler checkboxes if Pidgin is the current handler or if there is no handler
--Function SelectURIHandlerSelections
-- Push $R0
-- Push $R1
-- Push $R2
-- Push $R3
--
-- ; Start with the first URI handler
-- IntOp $R0 ${SecURIHandlers} + 1
--
-- start:
-- ; If it is the end of the section group, stop
-- SectionGetFlags $R0 $R1
-- IntOp $R2 $R1 & ${SF_SECGRPEND}
-- IntCmp $R2 ${SF_SECGRPEND} done
--
-- SectionGetText $R0 $R2
-- ;Strip the trailing ':'
-- StrLen $R3 $R2
-- IntOp $R3 $R3 - 1
-- StrCpy $R2 $R2 $R3
--
-- ClearErrors
-- ReadRegStr $R3 HKCR "$R2" ""
-- IfErrors default_on ;there is no current handler
--
-- Push $R2
-- Call CheckIfPidginIsCurrentURIHandler
-- Pop $R3
--
-- ; If Pidgin isn't the current handler, we don't steal it automatically
-- IntCmp $R3 0 end_loop
--
-- ;We default the URI handler checkbox on
-- default_on:
-- IntOp $R1 $R1 | ${SF_SELECTED} ; Select
-- SectionSetFlags $R0 $R1
--
-- end_loop:
-- IntOp $R0 $R0 + 1 ;Advance to the next section
-- Goto start
--
-- done:
-- Pop $R3
-- Pop $R2
-- Pop $R1
-- Pop $R0
--FunctionEnd ;SelectURIHandlerSections
--
--; Check if Pidgin is the current handler
--; Returns a boolean on the stack
--!macro CheckIfPidginIsCurrentURIHandlerMacro UN
--Function ${UN}CheckIfPidginIsCurrentURIHandler
-- Exch $R0
-- ClearErrors
--
-- ReadRegStr $R0 HKCR "$R0\shell\Open\command" ""
-- IfErrors 0 +3
-- IntOp $R0 0 + 0
-- Goto done
--
-- !ifdef __UNINSTALL__
-- ${un.WordFind} "$R0" "pidgin.exe" "E+1{" $R0
-- !else
-- ${WordFind} "$R0" "pidgin.exe" "E+1{" $R0
-- !endif
-- IntOp $R0 0 + 1
-- IfErrors 0 +2
-- IntOp $R0 0 + 0
--
-- done:
-- Exch $R0
--FunctionEnd
--!macroend
--!insertmacro CheckIfPidginIsCurrentURIHandlerMacro ""
--!insertmacro CheckIfPidginIsCurrentURIHandlerMacro "un."
--
--; If Pidgin is the current URI handler for the specified protocol, remove it.
--Function un.UnregisterURIHandler
-- Exch $R0
-- Push $R1
--
-- Push $R0
-- Call un.CheckIfPidginIsCurrentURIHandler
-- Pop $R1
--
-- ; If Pidgin isn't the current handler, leave it as-is
-- IntCmp $R1 0 done
--
-- ;Unregister the URI handler
-- DetailPrint "Unregistering $R0 URI Handler"
-- DeleteRegKey HKCR "$R0"
--
-- done:
-- Pop $R1
-- Pop $R0
--FunctionEnd
--
--Function RegisterURIHandler
-- Exch $R0
-- DetailPrint "Registering $R0 URI Handler"
-- DeleteRegKey HKCR "$R0"
-- WriteRegStr HKCR "$R0" "" "URL:$R0"
-- WriteRegStr HKCR "$R0" "URL Protocol" ""
-- WriteRegStr HKCR "$R0\DefaultIcon" "" "$INSTDIR\pidgin.exe"
-- WriteRegStr HKCR "$R0\shell" "" ""
-- WriteRegStr HKCR "$R0\shell\Open" "" ""
-- WriteRegStr HKCR "$R0\shell\Open\command" "" "$INSTDIR\pidgin.exe --protocolhandler=%1"
-- Pop $R0
--FunctionEnd
--
--
--!macro CheckUserInstallRightsMacro UN
--Function ${UN}CheckUserInstallRights
-- Push $0
-- Push $1
-- ClearErrors
-- UserInfo::GetName
-- IfErrors Win9x
-- Pop $0
-- UserInfo::GetAccountType
-- Pop $1
--
-- StrCmp $1 "Admin" 0 +3
-- StrCpy $1 "HKLM"
-- Goto done
-- StrCmp $1 "Power" 0 +3
-- StrCpy $1 "HKLM"
-- Goto done
-- StrCmp $1 "User" 0 +3
-- StrCpy $1 "HKCU"
-- Goto done
-- StrCmp $1 "Guest" 0 +3
-- StrCpy $1 "NONE"
-- Goto done
-- ; Unknown error
-- StrCpy $1 "NONE"
-- Goto done
--
-- Win9x:
-- StrCpy $1 "HKLM"
--
-- done:
-- Exch $1
-- Exch
-- Pop $0
--FunctionEnd
--!macroend
--!insertmacro CheckUserInstallRightsMacro ""
--!insertmacro CheckUserInstallRightsMacro "un."
--
--;
--; Usage:
--; Push $0 ; Path string
--; Call VerifyDir
--; Pop $0 ; 0 - Bad path 1 - Good path
--;
--Function VerifyDir
-- Exch $0
-- Push $1
-- Push $2
-- Loop:
-- IfFileExists $0 dir_exists
-- StrCpy $1 $0 ; save last
-- ${GetParent} $0 $0
-- StrLen $2 $0
-- ; IfFileExists "C:" on xp returns true and on win2k returns false
-- ; So we're done in such a case..
-- IntCmp $2 2 loop_done
-- ; GetParent of "C:" returns ""
-- IntCmp $2 0 loop_done
-- Goto Loop
--
-- loop_done:
-- StrCpy $1 "$0\GaImFooB"
-- ; Check if we can create dir on this drive..
-- ClearErrors
-- CreateDirectory $1
-- IfErrors DirBad DirGood
--
-- dir_exists:
-- ClearErrors
-- FileOpen $1 "$0\pidginfoo.bar" w
-- IfErrors PathBad PathGood
--
-- DirGood:
-- RMDir $1
-- Goto PathGood1
--
-- DirBad:
-- RMDir $1
-- Goto PathBad1
--
-- PathBad:
-- FileClose $1
-- Delete "$0\pidginfoo.bar"
-- PathBad1:
-- StrCpy $0 "0"
-- Push $0
-- Goto done
--
-- PathGood:
-- FileClose $1
-- Delete "$0\pidginfoo.bar"
-- PathGood1:
-- StrCpy $0 "1"
-- Push $0
--
-- done:
-- Exch 3 ; The top of the stack contains the output variable
-- Pop $0
-- Pop $2
-- Pop $1
--FunctionEnd
--
--Function .onVerifyInstDir
-- Push $0
-- Push $INSTDIR
-- Call VerifyDir
-- Pop $0
-- StrCmp $0 "0" 0 dir_good
-- Pop $0
-- Abort
--
-- dir_good:
-- Pop $0
--FunctionEnd
--
--;
--; Usage:
--; Call DoWeNeedGtk
--; First Pop:
--; 0 - We have the correct version
--; 1 - We have an old version that should work, prompt user for optional upgrade
--; 2 - We have an old version that needs to be upgraded
--; 3 - We don't have Gtk+ at all
--;
--Function DoWeNeedGtk
-- Push $0
-- Push $1
--
-- IfFileExists "$INSTDIR\Gtk\CONTENTS" +3
-- Push "3"
-- Goto done
--
-- ClearErrors
-- ${ConfigRead} "$INSTDIR\Gtk\CONTENTS" "Bundle Version " $0
-- IfErrors 0 +3
-- Push "3"
-- Goto done
--
-- ${VersionCompare} ${GTK_INSTALL_VERSION} $0 $1
-- IntCmp $1 1 +3
-- Push "0" ; Have a good version
-- Goto done
--
-- ${VersionCompare} ${GTK_MIN_VERSION} $0 $1
-- IntCmp $1 1 +3
-- Push "1" ; Optional Upgrade
-- Goto done
-- Push "2" ; Mandatory Upgrade
-- Goto done
--
-- done:
-- ; The item on the stack is what we want to return
-- Exch
-- Pop $1
-- Exch
-- Pop $0
--FunctionEnd
--
--
--!macro RunCheckMacro UN
--Function ${UN}RunCheck
-- Push $R0
-- Push $R1
--
-- IntOp $R1 0 + 0
-- retry_runcheck:
-- ; Close the Handle (needed if we're retrying)
-- IntCmp $R1 0 +2
-- System::Call 'kernel32::CloseHandle(i $R1) i .R1'
-- System::Call 'kernel32::CreateMutexA(i 0, i 0, t "pidgin_is_running") i .R1 ?e'
-- Pop $R0
-- IntCmp $R0 0 +3 ;This could check for ERROR_ALREADY_EXISTS(183), but lets just assume
-- MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION $(PIDGINISRUNNING) /SD IDCANCEL IDRETRY retry_runcheck
-- Abort
--
-- ; Close the Handle (If we don't do this, the uninstaller called from within will fail)
-- ; This is not optimal because there is a (small) window of time when a new process could start
-- System::Call 'kernel32::CloseHandle(i $R1) i .R1'
--
-- Pop $R1
-- Pop $R0
--FunctionEnd
--!macroend
--!insertmacro RunCheckMacro ""
--!insertmacro RunCheckMacro "un."
--
--Function .onInit
-- Push $R0
-- Push $R1
-- Push $R2
-- Push $R3 ; This is only used for the Parameters throughout the function
--
-- ${GetParameters} $R3
--
-- IntOp $R1 0 + 0
-- retry_runcheck:
-- ; Close the Handle (needed if we're retrying)
-- IntCmp $R1 0 +2
-- System::Call 'kernel32::CloseHandle(i $R1) i .R1'
-- System::Call 'kernel32::CreateMutexA(i 0, i 0, t "pidgin_installer_running") i .R1 ?e'
-- Pop $R0
-- IntCmp $R0 0 +3 ;This could check for ERROR_ALREADY_EXISTS(183), but lets just assume
-- MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION $(INSTALLERISRUNNING) /SD IDCANCEL IDRETRY retry_runcheck
-- Abort
--
-- ; Allow installer to run even if pidgin is running via "/NOPIDGINRUNCHECK=1"
-- ; This is useful for testing
-- ClearErrors
-- ${GetOptions} "$R3" "/NOPIDGINRUNCHECK=" $R1
-- IfErrors 0 +2
-- Call RunCheck
--
-- StrCpy $name "Pidgin ${PIDGIN_VERSION}"
--
-- ;Try to copy the old Gaim installer Lang Reg. key
-- ;(remove it after we're done to prevent this being done more than once)
-- ClearErrors
-- ReadRegStr $R0 HKCU "${PIDGIN_REG_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}"
-- IfErrors 0 +5
-- ClearErrors
-- ReadRegStr $R0 HKCU "${OLD_GAIM_REG_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}"
-- IfErrors +3
-- DeleteRegValue HKCU "${OLD_GAIM_REG_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}"
-- WriteRegStr HKCU "${PIDGIN_REG_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}" "$R0"
--
-- ${MementoSectionRestore}
--
-- ;Preselect the URI handlers as appropriate
-- Call SelectURIHandlerSelections
--
-- ;Preselect the "shortcuts" checkboxes according to the previous installation
-- ClearErrors
-- ;Make sure that there was a previous installation
-- ReadRegStr $R0 HKCU "${PIDGIN_REG_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}"
-- IfErrors done_preselecting_shortcuts
-- ;Does the Desktop shortcut exist?
-- GetFileTime "$DESKTOP\Pidgin.lnk" $R0 $R0
-- IfErrors +1 +5
-- ClearErrors
-- SetShellVarContext "all"
-- GetFileTime "$DESKTOP\Pidgin.lnk" $R0 $R0
-- IfErrors preselect_startmenu_shortcut ;Desktop Shortcut if off by default
-- !insertmacro SelectSection ${SecDesktopShortcut}
-- preselect_startmenu_shortcut:
-- ;Reset ShellVarContext because we may have changed it
-- SetShellVarContext "current"
-- ClearErrors
-- ;Does the StartMenu shortcut exist?
-- GetFileTime "$SMPROGRAMS\Pidgin.lnk" $R0 $R0
-- IfErrors +1 done_preselecting_shortcuts ;StartMenu Shortcut is on by default
-- ClearErrors
-- SetShellVarContext "all"
-- GetFileTime "$SMPROGRAMS\Pidgin.lnk" $R0 $R0
-- IfErrors +1 done_preselecting_shortcuts ;StartMenu Shortcut is on by default
-- !insertmacro UnselectSection ${SecStartMenuShortcut}
-- done_preselecting_shortcuts:
-- ;Reset ShellVarContext because we may have changed it
-- SetShellVarContext "current"
--
-- ClearErrors
-- ${GetOptions} "$R3" "/L=" $R1
-- IfErrors +3
-- StrCpy $LANGUAGE $R1
-- Goto skip_lang
--
-- ; Select Language
-- ; Display Language selection dialog
-- !define MUI_LANGDLL_ALWAYSSHOW
-- !insertmacro MUI_LANGDLL_DISPLAY
-- skip_lang:
--
-- ClearErrors
-- ${GetOptions} "$R3" "/DS=" $R1
-- IfErrors +8
-- SectionGetFlags ${SecDesktopShortcut} $R2
-- StrCmp "1" $R1 0 +2
-- IntOp $R2 $R2 | ${SF_SELECTED}
-- StrCmp "0" $R1 0 +3
-- IntOp $R1 ${SF_SELECTED} ~
-- IntOp $R2 $R2 & $R1
-- SectionSetFlags ${SecDesktopShortcut} $R2
--
-- ClearErrors
-- ${GetOptions} "$R3" "/SMS=" $R1
-- IfErrors +8
-- SectionGetFlags ${SecStartMenuShortcut} $R2
-- StrCmp "1" $R1 0 +2
-- IntOp $R2 $R2 | ${SF_SELECTED}
-- StrCmp "0" $R1 0 +3
-- IntOp $R1 ${SF_SELECTED} ~
-- IntOp $R2 $R2 & $R1
-- SectionSetFlags ${SecStartMenuShortcut} $R2
--
-- ; If install path was set on the command, use it.
-- StrCmp $INSTDIR "" 0 instdir_done
--
-- ; If pidgin or gaim is currently installed, we should default to where it is currently installed
-- ClearErrors
-- ReadRegStr $INSTDIR HKCU "${PIDGIN_REG_KEY}" ""
-- IfErrors +2
-- StrCmp $INSTDIR "" 0 instdir_done
-- ClearErrors
-- ReadRegStr $INSTDIR HKLM "${PIDGIN_REG_KEY}" ""
-- IfErrors +2
-- StrCmp $INSTDIR "" 0 instdir_done
--
-- Call CheckUserInstallRights
-- Pop $R0
--
-- StrCmp $R0 "HKLM" 0 user_dir
-- StrCpy $INSTDIR "$PROGRAMFILES\Pidgin"
-- Goto instdir_done
-- user_dir:
-- Push $SMPROGRAMS
-- ${GetParent} $SMPROGRAMS $R2
-- ${GetParent} $R2 $R2
-- StrCpy $INSTDIR "$R2\Pidgin"
--
-- instdir_done:
--;LogSet on
--
-- ; Try to select a translation and a dictionary for the currently selected Language
-- Call SelectTranslationForCurrentLanguage
--
-- ;Mark the dictionaries that are already installed as readonly
-- Call SelectAndDisableInstalledDictionaries
--
-- Pop $R3
-- Pop $R2
-- Pop $R1
-- Pop $R0
--FunctionEnd
--
--Function .onInstSuccess
--
-- ${MementoSectionSave}
--
--FunctionEnd
--
--
--Function un.onInit
--
-- Call un.RunCheck
-- StrCpy $name "Pidgin ${PIDGIN_VERSION}"
--;LogSet on
--
-- ; Get stored language preference
-- !insertmacro MUI_UNGETLANGUAGE
--
--FunctionEnd
--
--; Page enter and exit functions..
--
--Function preWelcomePage
-- Push $R0
-- Push $R1
--
--!ifdef OFFLINE_INSTALLER
-- !insertmacro SelectSection ${SecDebugSymbols}
--!endif
--
-- Call DoWeNeedGtk
-- Pop $CURRENT_GTK_STATE
-- StrCpy $WARNED_GTK_STATE "0"
-- IntCmp $CURRENT_GTK_STATE 1 done gtk_not_mandatory
-- ; Make the GTK+ Section RO if it is required. (it is required only if you have an existing version that is too old)
-- StrCmp $CURRENT_GTK_STATE "2" 0 done
-- !insertmacro SetSectionFlag ${SecGtk} ${SF_RO}
-- Goto done
-- gtk_not_mandatory:
-- ; Don't select the GTK+ section if we already have this version or newer installed
-- !insertmacro UnselectSection ${SecGtk}
--
-- done:
-- Pop $R1
-- Pop $R0
--FunctionEnd
--
--; If the GTK+ Section has been unselected and there isn't a compatible GTK+ already, confirm
--Function .onSelChange
-- Push $R0
--
-- SectionGetFlags ${SecGtk} $R0
-- IntOp $R0 $R0 & ${SF_SELECTED}
-- ; If the Gtk Section is currently selected, reset the "Warned" flag
-- StrCmp $R0 "${SF_SELECTED}" 0 +3
-- StrCpy $WARNED_GTK_STATE "0"
-- Goto done
--
-- ; If we've already warned the user, don't warn them again
-- StrCmp $WARNED_GTK_STATE "1" done
-- IntCmp $CURRENT_GTK_STATE 1 done done 0
-- StrCpy $WARNED_GTK_STATE "1"
-- MessageBox MB_YESNO $(PIDGINPROMPTFORCENOGTK) /SD IDNO IDYES done
-- !insertmacro SelectSection ${SecGtk}
--
-- done:
-- Pop $R0
--FunctionEnd
--
--Function SelectTranslationForCurrentLanguage
--!insertmacro SELECT_TRANSLATION_FUNCTION
--FunctionEnd
--
--; SpellChecker Related Functions
--;-------------------------------
--
--; Select and Disable any Sections that have currently installed dictionaries
--!macro CHECK_SPELLCHECK_SECTION lang
-- ;Advance to the next (correct) section index
-- IntOp $R0 $R0 + 1
-- IfFileExists "$INSTDIR\spellcheck\share\enchant\myspell\${lang}.dic" 0 done_${lang}
-- SectionGetFlags $R0 $R1
-- IntOp $R1 $R1 | ${SF_RO} ; Mark Readonly
-- IntOp $R1 $R1 | ${SF_SELECTED} ; Select
-- SectionSetFlags $R0 $R1
-- done_${lang}:
--!macroend
--Function SelectAndDisableInstalledDictionaries
-- Push $R0
-- Push $R1
--
-- !insertmacro SetSectionFlag ${SecSpellCheck} ${SF_RO}
-- !insertmacro UnselectSection ${SecSpellCheck}
--
-- IntOp $R0 ${SecSpellCheck} + 0
-- !include "pidgin-spellcheck-preselect.nsh"
--
-- Pop $R1
-- Pop $R0
--FunctionEnd
--
--Function InstallDict
-- Push $R0
-- Exch
-- Pop $R0 ;This is the language code
-- Push $R1
-- Exch 2
-- Pop $R1 ;This is the language file
-- Push $R2
-- Push $R3
-- Push $R4
--
-- ClearErrors
-- IfFileExists "$INSTDIR\spellcheck\share\enchant\myspell\$R0.dic" installed
--
-- InitPluginsDir
--
-- ; We need to download and install dictionary
-- StrCpy $R2 "$PLUGINSDIR\$R1"
-- StrCpy $R3 "${DOWNLOADER_URL}&dl_pkg=oo_dict&lang=$R1&lang_file=$R1"
-- DetailPrint "Downloading the $R0 Dictionary... ($R3)"
-- retry:
-- NSISdl::download /TIMEOUT=10000 "$R3" "$R2"
-- Pop $R4
-- StrCmp $R4 "cancel" done
-- StrCmp $R4 "success" +3
-- MessageBox MB_RETRYCANCEL "$(PIDGINSPELLCHECKERROR)" /SD IDCANCEL IDRETRY retry IDCANCEL done
-- Goto done
-- SetOutPath "$INSTDIR\spellcheck\share\enchant\myspell"
-- nsisunz::UnzipToLog "$R2" "$OUTDIR"
-- SetOutPath "$INSTDIR"
-- Pop $R3
-- StrCmp $R3 "success" installed
-- DetailPrint "$R3" ;print error message to log
-- Goto done
--
-- installed: ;The dictionary is currently installed, no error message
-- DetailPrint "$R0 Dictionary is installed"
--
-- done:
-- Pop $R4
-- Pop $R3
-- Pop $R2
-- Pop $R0
-- Exch $R1
--FunctionEnd
--
--!ifndef OFFLINE_INSTALLER
--; Input Stack: Filename, SHA1sum
--; Output Return Code: 0=Match; 1=FileSum error; 2=Mismatch
--Function CheckSHA1Sum
-- Push $R0
-- Exch
-- Pop $R0 ;Filename
-- Push $R2
-- Exch 2
-- Pop $R2 ;SHA1sum
-- Push $R1
--
-- SHA1Plugin::FileSum "$R0"
-- Pop $R1
-- Pop $R0
--
-- StrCmp "$R1" "0" +4
-- DetailPrint "SHA1Sum calculation error: $R0"
-- IntOp $R1 0 + 1
-- Goto done
--
-- ; Compare the SHA1Sums
-- StrCmp $R2 $R0 +4
-- DetailPrint "SHA1Sum mismatch... Expected $R2; got $R0"
-- IntOp $R1 0 + 2
-- Goto done
--
-- IntOp $R1 0 + 0
--
-- done:
-- Pop $R2
-- Pop $R0
-- Exch $R1 ;$R1 has the return code
--FunctionEnd
--!endif
--
-diff -Nur pidgin-2.10.7/pidgin/win32/nsis/pidgin-plugin.nsh pidgin-2.10.7-nonprism/pidgin/win32/nsis/pidgin-plugin.nsh
---- pidgin-2.10.7/pidgin/win32/nsis/pidgin-plugin.nsh 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/nsis/pidgin-plugin.nsh 1969-12-31 21:00:00.000000000 -0300
-@@ -1,181 +0,0 @@
--;;
--;; Windows Pidgin NSIS installer plugin helper utilities
--;; Copyright 2005, Daniel Atallah <daniel_atallah@yahoo.com>
--;;
--;; Include in plugin installer scripts using:
--;; !addincludedir "${PATH_TO_PIDGIN_SRC}\pidgin\win32\nsis"
--;; !include "pidgin-plugin.nsh"
--;;
--
--!define PIDGIN_REG_KEY "SOFTWARE\pidgin"
--
--!define PIDGIN_VERSION_OK 0
--!define PIDGIN_VERSION_INCOMPATIBLE 1
--!define PIDGIN_VERSION_UNDEFINED 2
--
--; Extract the Pidgin Version from the registry
--; This will set the Error flag if unable to determine the value
--; Pop the value of the stack after calling this to get the value (unless Error Flag is set)
--Function GetPidginVersion
-- Push $R0
--
-- ; Read the pidgin version
-- ClearErrors
-- ReadRegStr $R0 HKLM ${PIDGIN_REG_KEY} "Version"
-- IfErrors +1 GetPidginVersion_found
-- ; fall back to the HKCU registry key
-- ReadRegStr $R0 HKCU ${PIDGIN_REG_KEY} "Version"
-- IfErrors GetPidginVersion_done ; Keep the error flag set
--
-- GetPidginVersion_found:
-- Push $R0 ; Push the value onto the stack
-- Exch
--
-- GetPidginVersion_done:
-- ; restore $R0
-- Pop $R0
--FunctionEnd
--
--; Check that the currently installed Pidgin version is compatible
--; with the plugin version we are installing
--; Push the Plugin's Pidgin Version onto the Stack before calling
--; After calling, the top of the Stack will contain the result of the check:
--; PIDGIN_VERSION_OK - If the installed Pidgin version is compatible w/ the version specified
--; PIDGIN_VERSION_INCOMPATIBLE - If the installed Pidgin version isn't compatible w/ the version specified
--; PIDGIN_VERSION_UNDEFINED - If the installed Pidgin version can't be determined
--Function CheckPidginVersion
-- ; Save the Variable values that we will use in the stack
-- Push $R4
-- Exch
-- Pop $R4 ; Get the plugin's Pidgin Version
-- Push $R0
-- Push $R1
-- Push $R2
--
-- ; Read the pidgin version
-- Call GetPidginVersion
-- IfErrors checkPidginVersion_noPidginInstallFound
-- Pop $R0
--
-- ;If they are exactly the same, we don't need to look at anything else
-- StrCmp $R0 $R4 checkPidginVersion_VersionOK
--
-- ; Versions are in the form of X.Y.Z
-- ; If X is different or plugin's Y > pidgin's Y, then we shouldn't install
--
-- ;Check the Major Version
-- Push $R0
-- Push 0
-- Call GetVersionComponent
-- IfErrors checkPidginVersion_noPidginInstallFound ;We couldn't extract 'X' from the installed pidgin version
-- Pop $R2
-- Push $R4
-- Push 0
-- Call GetVersionComponent
-- IfErrors checkPidginVersion_BadVersion ; this isn't a valid version, so don't bother even checking
-- Pop $R1
-- ;Check that both versions' X is the same
-- StrCmp $R1 $R2 +1 checkPidginVersion_BadVersion
--
-- ;Check the Minor Version
-- Push $R0
-- Push 1
-- Call GetVersionComponent
-- IfErrors checkPidginVersion_noPidginInstallFound ;We couldn't extract 'Y' from the installed pidgin version
-- Pop $R2
-- Push $R4
-- Push 1
-- Call GetVersionComponent
-- IfErrors checkPidginVersion_BadVersion ; this isn't a valid version, so don't bother even checking
-- Pop $R1
-- ;Check that plugin's Y <= pidgin's Y
-- IntCmp $R1 $R2 checkPidginVersion_VersionOK checkPidginVersion_VersionOK checkPidginVersion_BadVersion
--
-- checkPidginVersion_BadVersion:
-- Push ${PIDGIN_VERSION_INCOMPATIBLE}
-- goto checkPidginVersion_done
-- checkPidginVersion_noPidginInstallFound:
-- Push ${PIDGIN_VERSION_UNDEFINED}
-- goto checkPidginVersion_done
-- checkPidginVersion_VersionOK:
-- Push ${PIDGIN_VERSION_OK}
--
-- checkPidginVersion_done:
-- ; Restore the Variables that we used
-- Exch
-- Pop $R2
-- Exch
-- Pop $R1
-- Exch
-- Pop $R0
-- Exch
-- Pop $R4
--FunctionEnd
--
--; Extract the part of a string prior to "." (or the whole string if there is no ".")
--; If no "." was found, the ErrorFlag will be set
--; Before this is called, Push ${VERSION_STRING} must be called, and then Push 0 for Major, 1 for Minor, etc
--; Pop should be called after to retrieve the new value
--Function GetVersionComponent
-- ClearErrors
--
-- ; Save the Variable values that we will use in the stack
-- Push $1
-- Exch
-- Pop $1 ;The version component which we want to extract (0, 1, 2)
-- Exch
-- Push $0
-- Exch
-- Pop $0 ;The string from which to extract the version component
--
-- Push $2
-- Push $3
-- Push $4
-- Push $5
-- Push $6
-- Push $7
--
-- StrCpy $2 "0" ;Initialize our string index counter
-- StrCpy $7 "0" ;Index of last "."
-- StrCpy $3 "0" ;Initialize our version index counter
--
-- startGetVersionComponentLoop:
-- ;avoid infinite loop (if we have gotten the whole initial string, exit the loop and set the error flag)
-- StrCmp $6 $0 GetVersionComponentSetErrorFlag
-- IntOp $2 $2 + 1
-- StrCpy $6 $0 $2 ;Update the infinite loop preventing string
-- ;Determine the correct substring (only the current index component)
-- IntOp $5 $2 - $7
-- StrCpy $4 $0 $5 $7 ;Append the current character in $0 to $4
-- StrCpy $5 $0 1 $2 ;store the next character in $5
--
-- ;if the next character is ".", $4 will contain the version component prior to "."
-- StrCmp $5 "." +1 startGetVersionComponentLoop
-- StrCmp $3 $1 doneGetVersionComponent ;If it is the version component we're looking for, stop
-- IntOp $3 $3 + 1 ;Increment the version index counter
-- IntOp $2 $2 + 1 ;Increment the version string index to "." (so it will be skipped)
-- StrCpy $7 $2 ;Keep track of the index of the last "."
-- StrCpy $6 $0 $2 ;Update the infinite loop preventing string
-- goto startGetVersionComponentLoop
--
-- GetVersionComponentSetErrorFlag:
-- SetErrors
--
-- doneGetVersionComponent:
-- ; Restore the Variables that we used
-- Pop $7
-- Pop $6
-- Pop $5
-- Push $4 ;This is the value we're returning
-- Exch
-- Pop $4
-- Exch
-- Pop $3
-- Exch
-- Pop $2
-- Exch
-- Pop $0
-- Exch
-- Pop $1
--FunctionEnd
--
-Binary files pidgin-2.10.7/pidgin/win32/nsis/pixmaps/pidgin-header.bmp and pidgin-2.10.7-nonprism/pidgin/win32/nsis/pixmaps/pidgin-header.bmp differ
-Binary files pidgin-2.10.7/pidgin/win32/nsis/pixmaps/pidgin-install.ico and pidgin-2.10.7-nonprism/pidgin/win32/nsis/pixmaps/pidgin-install.ico differ
-Binary files pidgin-2.10.7/pidgin/win32/nsis/pixmaps/pidgin-intro.bmp and pidgin-2.10.7-nonprism/pidgin/win32/nsis/pixmaps/pidgin-intro.bmp differ
-diff -Nur pidgin-2.10.7/pidgin/win32/nsis/rpm2zip.sh pidgin-2.10.7-nonprism/pidgin/win32/nsis/rpm2zip.sh
---- pidgin-2.10.7/pidgin/win32/nsis/rpm2zip.sh 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/nsis/rpm2zip.sh 1969-12-31 21:00:00.000000000 -0300
-@@ -1,65 +0,0 @@
--#!/bin/sh
--
--here=`pwd`
--for F in $*; do
-- case $F in
-- mingw32-*.noarch.rpm|mingw64-*.noarch.rpm|*/mingw32-*.noarch.rpm|*/mingw64-*.noarch.rpm)
-- package=`rpm -qp $F 2>/dev/null`
-- case $package in
-- mingw32-*|mingw64-*)
-- case $package in
-- mingw32-*)
-- cpu=i686
-- bits=32
-- ;;
-- mingw64-*)
-- cpu=x86_64
-- bits=64
-- ;;
-- esac
-- origname=`rpm -qp --queryformat='%{NAME}' $F 2>/dev/null`
-- name=$origname
-- case $name in
-- *-devel)
-- name=${name%el}
-- ;;
-- esac
-- shortpackage="$name"_`rpm -qp --queryformat='%{VERSION}-%{RELEASE}'_win${bits} $F 2>/dev/null`
-- shortpackage=${shortpackage#mingw32-}
-- shortpackage=${shortpackage#mingw64-}
-- shortname=$name
-- shortname=${shortname#mingw32-}
-- shortname=${shortname#mingw64-}
-- tmp=`mktemp -d`
-- #rpm2cpio $F | lzcat | (cd $tmp && cpio --quiet -id)
-- rpm2cpio $F | (cd $tmp && cpio --quiet -id)
-- (
-- cd $tmp
-- zipfile="$here/$shortpackage.zip"
-- rm -f $zipfile
-- (cd usr/${cpu}-pc-mingw32/sys-root/mingw && zip -q -r -D $zipfile .)
-- if [ -d usr/share/doc/packages/$origname ] ; then
-- mv usr/share/doc/packages/$origname usr/share/doc/packages/$shortname
-- (cd usr && zip -q -r -D $zipfile share/doc/packages/$shortname)
-- fi
-- mkdir -p manifest
-- unzip -l $zipfile >manifest/$shortpackage.mft
-- zip -q $zipfile manifest/$shortpackage.mft
-- N=`unzip -l $zipfile | wc -l | sed -e 's/^ *\([0-9]*\).*/\1/'`
-- Nm1=`expr $N - 1`
-- unzip -l $zipfile | sed -e "1,3 d" -e "$Nm1,$N d" | awk '{print $4}' | grep -v -E '/$' >manifest/$shortpackage.mft
-- zip -q $zipfile manifest/$shortpackage.mft
-- echo $zipfile
-- )
-- rm -rf $tmp
-- ;;
-- *)
-- echo $F is not a mingw32/64 RPM package >&2
-- ;;
-- esac
-- ;;
-- *)
-- echo $F is not a mingw32/64 RPM package >&2
-- ;;
-- esac
--done
-diff -Nur pidgin-2.10.7/pidgin/win32/pidgin_dll_rc.rc.in pidgin-2.10.7-nonprism/pidgin/win32/pidgin_dll_rc.rc.in
---- pidgin-2.10.7/pidgin/win32/pidgin_dll_rc.rc.in 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/pidgin_dll_rc.rc.in 1969-12-31 21:00:00.000000000 -0300
-@@ -1,41 +0,0 @@
--#include <winver.h>
--#include "version.h"
--#include "resource.h"
--
--VS_VERSION_INFO VERSIONINFO
-- FILEVERSION PURPLE_MAJOR_VERSION,PURPLE_MINOR_VERSION,PURPLE_MICRO_VERSION,0
-- PRODUCTVERSION PURPLE_MAJOR_VERSION,PURPLE_MINOR_VERSION,PURPLE_MICRO_VERSION,0
-- FILEFLAGSMASK 0
-- FILEFLAGS 0
-- FILEOS VOS__WINDOWS32
-- FILETYPE VFT_DLL
-- FILESUBTYPE VFT2_UNKNOWN
-- BEGIN
-- BLOCK "StringFileInfo"
-- BEGIN
-- BLOCK "040904B0"
-- BEGIN
-- VALUE "CompanyName", "The Pidgin developer community"
-- VALUE "FileDescription", "GTK+ Pidgin Library"
-- VALUE "FileVersion", "@PIDGIN_VERSION@"
-- VALUE "InternalName", "libpidgin"
-- VALUE "LegalCopyright", "Copyright (C) 1998-2010 The Pidgin developer community (See the COPYRIGHT file in the source distribution)."
-- VALUE "OriginalFilename", "pidgin.dll"
-- VALUE "ProductName", "Pidgin"
-- VALUE "ProductVersion", "@PIDGIN_VERSION@"
-- END
-- END
-- BLOCK "VarFileInfo"
-- BEGIN
-- VALUE "Translation", 0x409, 1200
-- END
-- END
--
--PIDGIN_TRAY_AVAILABLE_4BIT ICON "pixmaps/tray/16/available_4bit.ico"
--PIDGIN_TRAY_AWAY_4BIT ICON "pixmaps/tray/16/away_4bit.ico"
--PIDGIN_TRAY_BUSY_4BIT ICON "pixmaps/tray/16/busy_4bit.ico"
--PIDGIN_TRAY_XA_4BIT ICON "pixmaps/tray/16/extended-away_4bit.ico"
--PIDGIN_TRAY_OFFLINE_4BIT ICON "pixmaps/tray/16/offline_4bit.ico"
--PIDGIN_TRAY_CONNECTING_4BIT ICON "pixmaps/tray/16/connecting_4bit.ico"
--PIDGIN_TRAY_PENDING_4BIT ICON "pixmaps/tray/16/message_4bit.ico"
--PIDGIN_TRAY_INVISIBLE_4BIT ICON "pixmaps/tray/16/invisible_4bit.ico"
-diff -Nur pidgin-2.10.7/pidgin/win32/pidgin_exe_rc.rc.in pidgin-2.10.7-nonprism/pidgin/win32/pidgin_exe_rc.rc.in
---- pidgin-2.10.7/pidgin/win32/pidgin_exe_rc.rc.in 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/pidgin_exe_rc.rc.in 1969-12-31 21:00:00.000000000 -0300
-@@ -1,34 +0,0 @@
--#include <winver.h>
--#include "resource.h"
--#include "version.h"
--
--VS_VERSION_INFO VERSIONINFO
-- FILEVERSION PURPLE_MAJOR_VERSION,PURPLE_MINOR_VERSION,PURPLE_MICRO_VERSION,0
-- PRODUCTVERSION PURPLE_MAJOR_VERSION,PURPLE_MINOR_VERSION,PURPLE_MICRO_VERSION,0
-- FILEFLAGSMASK 0
-- FILEFLAGS 0
-- FILEOS VOS__WINDOWS32
-- FILETYPE VFT_APP
-- FILESUBTYPE VFT2_UNKNOWN
-- BEGIN
-- BLOCK "StringFileInfo"
-- BEGIN
-- BLOCK "040904B0"
-- BEGIN
-- VALUE "CompanyName", "The Pidgin developer community"
-- VALUE "FileDescription", "Pidgin"
-- VALUE "FileVersion", "@PIDGIN_VERSION@"
-- VALUE "InternalName", "pidgin"
-- VALUE "LegalCopyright", "Copyright (C) 1998-2010 The Pidgin developer community (See the COPYRIGHT file in the source distribution)."
-- VALUE "OriginalFilename", "@ORIGINAL_FILENAME@"
-- VALUE "ProductName", "Pidgin"
-- VALUE "ProductVersion", "@PIDGIN_VERSION@"
-- END
-- END
-- BLOCK "VarFileInfo"
-- BEGIN
-- VALUE "Translation", 0x409, 1200
-- END
-- END
--
--PIDGIN_ICON ICON "pixmaps/pidgin.ico"
-diff -Nur pidgin-2.10.7/pidgin/win32/resource.h pidgin-2.10.7-nonprism/pidgin/win32/resource.h
---- pidgin-2.10.7/pidgin/win32/resource.h 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/resource.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,9 +0,0 @@
--#define PIDGIN_ICON 104
--#define PIDGIN_TRAY_AVAILABLE_4BIT 105
--#define PIDGIN_TRAY_AWAY_4BIT 106
--#define PIDGIN_TRAY_BUSY_4BIT 107
--#define PIDGIN_TRAY_XA_4BIT 108
--#define PIDGIN_TRAY_OFFLINE_4BIT 109
--#define PIDGIN_TRAY_CONNECTING_4BIT 110
--#define PIDGIN_TRAY_PENDING_4BIT 111
--#define PIDGIN_TRAY_INVISIBLE_4BIT 112
-diff -Nur pidgin-2.10.7/pidgin/win32/untar.c pidgin-2.10.7-nonprism/pidgin/win32/untar.c
---- pidgin-2.10.7/pidgin/win32/untar.c 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/untar.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,633 +0,0 @@
--/* untar.c */
--
--/*#define VERSION "1.4"*/
--
--/* DESCRIPTION:
-- * Untar extracts files from an uncompressed tar archive, or one which
-- * has been compressed with gzip. Usually such archives will have file
-- * names that end with ".tar" or ".tgz" respectively, although untar
-- * doesn't depend on any naming conventions. For a summary of the
-- * command-line options, run untar with no arguments.
-- *
-- * HOW TO COMPILE:
-- * Untar doesn't require any special libraries or compile-time flags.
-- * A simple "cc untar.c -o untar" (or the local equivalent) is
-- * sufficient. Even "make untar" works, without needing a Makefile.
-- * For Microsoft Visual C++, the command is "cl /D_WEAK_POSIX untar.c"
-- * (for 32 bit compilers) or "cl /F 1400 untar.c" (for 16-bit).
-- *
-- * IF YOU SEE COMPILER WARNINGS, THAT'S NORMAL; you can ignore them.
-- * Most of the warnings could be eliminated by adding #include <string.h>
-- * but that isn't portable -- some systems require <strings.h> and
-- * <malloc.h>, for example. Because <string.h> isn't quite portable,
-- * and isn't really necessary in the context of this program, it isn't
-- * included.
-- *
-- * PORTABILITY:
-- * Untar only requires the <stdio.h> header. It uses old-style function
-- * definitions. It opens all files in binary mode. Taken together,
-- * this means that untar should compile & run on just about anything.
-- *
-- * If your system supports the POSIX chmod(2), utime(2), link(2), and
-- * symlink(2) calls, then you may wish to compile with -D_POSIX_SOURCE,
-- * which will enable untar to use those system calls to restore the
-- * timestamp and permissions of the extracted files, and restore links.
-- * (For Linux, _POSIX_SOURCE is always defined.)
-- *
-- * For systems which support some POSIX features but not enough to support
-- * -D_POSIX_SOURCE, you might be able to use -D_WEAK_POSIX. This allows
-- * untar to restore time stamps and file permissions, but not links.
-- * This should work for Microsoft systems, and hopefully others as well.
-- *
-- * AUTHOR & COPYRIGHT INFO:
-- * Written by Steve Kirkendall, kirkenda@cs.pdx.edu
-- * Placed in public domain, 6 October 1995
-- *
-- * Portions derived from inflate.c -- Not copyrighted 1992 by Mark Adler
-- * version c10p1, 10 January 1993
-- *
-- * Altered by Herman Bloggs <hermanator12002@yahoo.com>
-- * April 4, 2003
-- * Changes: Stripped out gz compression code, added better interface for
-- * untar.
-- */
--#include <windows.h>
--#include <stdio.h>
--#include <io.h>
--#include <string.h>
--#include <stdlib.h>
--#ifndef SEEK_SET
--# define SEEK_SET 0
--#endif
--
--#ifdef _WEAK_POSIX
--# ifndef _POSIX_SOURCE
--# define _POSIX_SOURCE
--# endif
--#endif
--
--#ifdef _POSIX_SOURCE
--# include <sys/types.h>
--# include <sys/stat.h>
--# include <sys/utime.h>
--# ifdef _WEAK_POSIX
--# define mode_t int
--# else
--# include <unistd.h>
--# endif
--#endif
--#include "debug.h"
--#include "untar.h"
--#include <glib.h>
--
--#include <glib/gstdio.h>
--
--#define untar_error( error, args... ) purple_debug(PURPLE_DEBUG_ERROR, "untar", error, ## args )
--#define untar_warning( warning, args... ) purple_debug(PURPLE_DEBUG_WARNING, "untar", warning, ## args )
--#define untar_verbose( args... ) purple_debug(PURPLE_DEBUG_INFO, "untar", ## args )
--
--#define WSIZE 32768 /* size of decompression buffer */
--#define TSIZE 512 /* size of a "tape" block */
--#define CR 13 /* carriage-return character */
--#define LF 10 /* line-feed character */
--
--typedef unsigned char Uchar_t;
--typedef unsigned short Ushort_t;
--typedef unsigned long Ulong_t;
--
--typedef struct
--{
-- char filename[100]; /* 0 name of next file */
-- char mode[8]; /* 100 Permissions and type (octal digits) */
-- char owner[8]; /* 108 Owner ID (ignored) */
-- char group[8]; /* 116 Group ID (ignored) */
-- char size[12]; /* 124 Bytes in file (octal digits) */
-- char mtime[12]; /* 136 Modification time stamp (octal digits)*/
-- char checksum[8]; /* 148 Header checksum (ignored) */
-- char type; /* 156 File type (see below) */
-- char linkto[100]; /* 157 Linked-to name */
-- char brand[8]; /* 257 Identifies tar version (ignored) */
-- char ownername[32]; /* 265 Name of owner (ignored) */
-- char groupname[32]; /* 297 Name of group (ignored) */
-- char devmajor[8]; /* 329 Device major number (ignored) */
-- char defminor[8]; /* 337 Device minor number (ignored) */
-- char prefix[155]; /* 345 Prefix of name (optional) */
-- char RESERVED[12]; /* 500 Pad header size to 512 bytes */
--} tar_t;
--#define ISREGULAR(hdr) ((hdr).type < '1' || (hdr).type > '6')
--
--Uchar_t slide[WSIZE];
--
--static const char *inname = NULL; /* name of input archive */
--static FILE *infp = NULL; /* input byte stream */
--static FILE *outfp = NULL; /* output stream, for file currently being extracted */
--static Ulong_t outsize = 0; /* number of bytes remainin in file currently being extracted */
--static char **only = NULL; /* array of filenames to extract/list */
--static int nonlys = 0; /* number of filenames in "only" array; 0=extract all */
--static int didabs = 0; /* were any filenames affected by the absence of -p? */
--
--static untar_opt untarops = 0; /* Untar options */
--
--/* Options checked during untar process */
--#define LISTING (untarops & UNTAR_LISTING) /* 1 if listing, 0 if extracting */
--#define QUIET (untarops & UNTAR_QUIET) /* 1 to write nothing to stdout, 0 for normal chatter */
--#define VERBOSE (untarops & UNTAR_VERBOSE) /* 1 to write extra information to stdout */
--#define FORCE (untarops & UNTAR_FORCE) /* 1 to overwrite existing files, 0 to skip them */
--#define ABSPATH (untarops & UNTAR_ABSPATH) /* 1 to allow leading '/', 0 to strip leading '/' */
--#define CONVERT (untarops & UNTAR_CONVERT) /* 1 to convert newlines, 0 to leave unchanged */
--
--/*----------------------------------------------------------------------------*/
--
--/* create a file for writing. If necessary, create the directories leading up
-- * to that file as well.
-- */
--static FILE *createpath(name)
-- char *name; /* pathname of file to create */
--{
-- FILE *fp;
-- int i;
--
-- /* if we aren't allowed to overwrite and this file exists, return NULL */
-- if (!FORCE && access(name, 0) == 0)
-- {
-- untar_warning("%s: exists, will not overwrite without \"FORCE option\"\n", name);
-- return NULL;
-- }
--
-- /* first try creating it the easy way */
-- fp = g_fopen(name, CONVERT ? "w" : "wb");
-- if (fp)
-- return fp;
--
-- /* Else try making all of its directories, and then try creating
-- * the file again.
-- */
-- for (i = 0; name[i]; i++)
-- {
-- /* If this is a slash, then temporarily replace the '/'
-- * with a '\0' and do a mkdir() on the resulting string.
-- * Ignore errors for now.
-- */
-- if (name[i] == '/')
-- {
-- name[i] = '\0';
-- (void)g_mkdir(name, 0777);
-- name[i] = '/';
-- }
-- }
-- fp = g_fopen(name, CONVERT ? "w" : "wb");
-- if (!fp)
-- untar_error("Error opening: %s\n", name);
-- return fp;
--}
--
--/* Create a link, or copy a file. If the file is copied (not linked) then
-- * give a warning.
-- */
--static void linkorcopy(src, dst, sym)
-- char *src; /* name of existing source file */
-- char *dst; /* name of new destination file */
-- int sym; /* use symlink instead of link */
--{
-- FILE *fpsrc;
-- FILE *fpdst;
-- int c;
--
-- /* Open the source file. We do this first to make sure it exists */
-- fpsrc = g_fopen(src, "rb");
-- if (!fpsrc)
-- {
-- untar_error("Error opening: %s\n", src);
-- return;
-- }
--
-- /* Create the destination file. On POSIX systems, this is just to
-- * make sure the directory path exists.
-- */
-- fpdst = createpath(dst);
-- if (!fpdst) {
-- /* error message already given */
-- fclose(fpsrc);
-- return;
-- }
--
--#ifdef _POSIX_SOURCE
--# ifndef _WEAK_POSIX
-- /* first try to link it over, instead of copying */
-- fclose(fpdst);
-- g_unlink(dst);
-- if (sym)
-- {
-- if (symlink(src, dst))
-- {
-- perror(dst);
-- }
-- fclose(fpsrc);
-- return;
-- }
-- if (!link(src, dst))
-- {
-- /* This story had a happy ending */
-- fclose(fpsrc);
-- return;
-- }
--
-- /* Dang. Reopen the destination again */
-- fpdst = g_fopen(dst, "wb");
-- /* This *can't* fail */
--
--# endif /* _WEAK_POSIX */
--#endif /* _POSIX_SOURCE */
--
-- /* Copy characters */
-- while ((c = getc(fpsrc)) != EOF)
-- putc(c, fpdst);
--
-- /* Close the files */
-- fclose(fpsrc);
-- fclose(fpdst);
--
-- /* Give a warning */
-- untar_warning("%s: copy instead of link\n", dst);
--}
--
--/* This calls fwrite(), possibly after converting CR-LF to LF */
--static void cvtwrite(blk, size, fp)
-- Uchar_t *blk; /* the block to be written */
-- Ulong_t size; /* number of characters to be written */
-- FILE *fp; /* file to write to */
--{
-- int i, j;
-- static Uchar_t mod[TSIZE];
--
-- if (CONVERT)
-- {
-- for (i = j = 0; i < size; i++)
-- {
-- /* convert LF to local newline convention */
-- if (blk[i] == LF)
-- mod[j++] = '\n';
-- /* If CR-LF pair, then delete the CR */
-- else if (blk[i] == CR && (i+1 >= size || blk[i+1] == LF))
-- ;
-- /* other characters copied literally */
-- else
-- mod[j++] = blk[i];
-- }
-- size = j;
-- blk = mod;
-- }
--
-- fwrite(blk, (size_t)size, sizeof(Uchar_t), fp);
--}
--
--
--/* Compute the checksum of a tar header block, and return it as a long int.
-- * The checksum can be computed using either POSIX rules (unsigned bytes)
-- * or Sun rules (signed bytes).
-- */
--static long checksum(tblk, sunny)
-- tar_t *tblk; /* buffer containing the tar header block */
-- int sunny; /* Boolean: Sun-style checksums? (else POSIX) */
--{
-- long sum;
-- char *scan;
--
-- /* compute the sum of the first 148 bytes -- everything up to but not
-- * including the checksum field itself.
-- */
-- sum = 0L;
-- for (scan = (char *)tblk; scan < tblk->checksum; scan++)
-- {
-- sum += (*scan) & 0xff;
-- if (sunny && (*scan & 0x80) != 0)
-- sum -= 256;
-- }
--
-- /* for the 8 bytes of the checksum field, add blanks to the sum */
-- sum += ' ' * sizeof tblk->checksum;
-- scan += sizeof tblk->checksum;
--
-- /* finish counting the sum of the rest of the block */
-- for (; scan < (char *)tblk + sizeof *tblk; scan++)
-- {
-- sum += (*scan) & 0xff;
-- if (sunny && (*scan & 0x80) != 0)
-- sum -= 256;
-- }
--
-- return sum;
--}
--
--
--
--/* list files in an archive, and optionally extract them as well */
--static int untar_block(Uchar_t *blk) {
-- static char nbuf[256];/* storage space for prefix+name, combined */
-- static char *name,*n2;/* prefix and name, combined */
-- static int first = 1;/* Boolean: first block of archive? */
-- long sum; /* checksum for this block */
-- int i;
-- tar_t tblk[1];
--
--#ifdef _POSIX_SOURCE
-- static mode_t mode; /* file permissions */
-- static struct utimbuf timestamp; /* file timestamp */
--#endif
--
-- /* make a local copy of the block, and treat it as a tar header */
-- tblk[0] = *(tar_t *)blk;
--
-- /* process each type of tape block differently */
-- if (outsize > TSIZE)
-- {
-- /* data block, but not the last one */
-- if (outfp)
-- cvtwrite(blk, (Ulong_t)TSIZE, outfp);
-- outsize -= TSIZE;
-- }
-- else if (outsize > 0)
-- {
-- /* last data block of current file */
-- if (outfp)
-- {
-- cvtwrite(blk, outsize, outfp);
-- fclose(outfp);
-- outfp = NULL;
--#ifdef _POSIX_SOURCE
-- utime(nbuf, &timestamp);
-- chmod(nbuf, mode);
--#endif
-- }
-- outsize = 0;
-- }
-- else if ((tblk)->filename[0] == '\0')
-- {
-- /* end-of-archive marker */
-- if (didabs)
-- untar_warning("Removed leading slashes because \"ABSPATH option\" wasn't given.\n");
-- return 1;
-- }
-- else
-- {
-- /* file header */
--
-- /* half-assed verification -- does it look like header? */
-- if ((tblk)->filename[99] != '\0'
-- || ((tblk)->size[0] < '0'
-- && (tblk)->size[0] != ' ')
-- || (tblk)->size[0] > '9')
-- {
-- if (first)
-- {
-- untar_error("%s: not a valid tar file\n", inname);
-- return 0;
-- }
-- else
-- {
-- untar_error("Garbage detected; preceding file may be damaged\n");
-- return 0;
-- }
-- }
--
-- /* combine prefix and filename */
-- memset(nbuf, 0, sizeof nbuf);
-- name = nbuf;
-- if ((tblk)->prefix[0])
-- {
-- strncpy(name, (tblk)->prefix, sizeof (tblk)->prefix);
-- strcat(name, "/");
-- strncat(name + strlen(name), (tblk)->filename,
-- sizeof (tblk)->filename);
-- }
-- else
-- {
-- strncpy(name, (tblk)->filename,
-- sizeof (tblk)->filename);
-- }
--
-- /* Convert any backslashes to forward slashes, and guard
-- * against doubled-up slashes. (Some DOS versions of "tar"
-- * get this wrong.) Also strip off leading slashes.
-- */
-- if (!ABSPATH && (*name == '/' || *name == '\\'))
-- didabs = 1;
-- for (n2 = nbuf; *name; name++)
-- {
-- if (*name == '\\')
-- *name = '/';
-- if (*name != '/'
-- || (ABSPATH && n2 == nbuf)
-- || (n2 != nbuf && n2[-1] != '/'))
-- *n2++ = *name;
-- }
-- if (n2 == nbuf)
-- *n2++ = '/';
-- *n2 = '\0';
--
-- /* verify the checksum */
-- for (sum = 0L, i = 0; i < sizeof((tblk)->checksum); i++)
-- {
-- if ((tblk)->checksum[i] >= '0'
-- && (tblk)->checksum[i] <= '7')
-- sum = sum * 8 + (tblk)->checksum[i] - '0';
-- }
-- if (sum != checksum(tblk, 0) && sum != checksum(tblk, 1))
-- {
-- if (!first)
-- untar_error("Garbage detected; preceding file may be damaged\n");
-- untar_error("%s: header has bad checksum for %s\n", inname, nbuf);
-- return 0;
-- }
--
-- /* From this point on, we don't care whether this is the first
-- * block or not. Might as well reset the "first" flag now.
-- */
-- first = 0;
--
-- /* if last character of name is '/' then assume directory */
-- if (*nbuf && nbuf[strlen(nbuf) - 1] == '/')
-- (tblk)->type = '5';
--
-- /* convert file size */
-- for (outsize = 0L, i = 0; i < sizeof((tblk)->size); i++)
-- {
-- if ((tblk)->size[i] >= '0' && (tblk)->size[i] <= '7')
-- outsize = outsize * 8 + (tblk)->size[i] - '0';
-- }
--
--#ifdef _POSIX_SOURCE
-- /* convert file timestamp */
-- for (timestamp.modtime=0L, i=0; i < sizeof((tblk)->mtime); i++)
-- {
-- if ((tblk)->mtime[i] >= '0' && (tblk)->mtime[i] <= '7')
-- timestamp.modtime = timestamp.modtime * 8
-- + (tblk)->mtime[i] - '0';
-- }
-- timestamp.actime = timestamp.modtime;
--
-- /* convert file permissions */
-- for (mode = i = 0; i < sizeof((tblk)->mode); i++)
-- {
-- if ((tblk)->mode[i] >= '0' && (tblk)->mode[i] <= '7')
-- mode = mode * 8 + (tblk)->mode[i] - '0';
-- }
--#endif
--
-- /* If we have an "only" list, and this file isn't in it,
-- * then skip it.
-- */
-- if (nonlys > 0)
-- {
-- for (i = 0;
-- i < nonlys
-- && strcmp(only[i], nbuf)
-- && (strncmp(only[i], nbuf, strlen(only[i]))
-- || nbuf[strlen(only[i])] != '/');
-- i++)
-- {
-- }
-- if (i >= nonlys)
-- {
-- outfp = NULL;
-- return 1;
-- }
-- }
--
-- /* list the file */
-- if (VERBOSE)
-- untar_verbose("%c %s",
-- ISREGULAR(*tblk) ? '-' : ("hlcbdp"[(tblk)->type - '1']),
-- nbuf);
-- else if (!QUIET)
-- untar_verbose("%s\n", nbuf);
--
-- /* if link, then do the link-or-copy thing */
-- if (tblk->type == '1' || tblk->type == '2')
-- {
-- if (VERBOSE)
-- untar_verbose(" -> %s\n", tblk->linkto);
-- if (!LISTING)
-- linkorcopy(tblk->linkto, nbuf, tblk->type == '2');
-- outsize = 0L;
-- return 1;
-- }
--
-- /* If directory, then make a weak attempt to create it.
-- * Ideally we would do the "create path" thing, but that
-- * seems like more trouble than it's worth since traditional
-- * tar archives don't contain directories anyway.
-- */
-- if (tblk->type == '5')
-- {
-- if (LISTING)
-- n2 = " directory";
--#ifdef _POSIX_SOURCE
-- else if (mkdir(nbuf, mode) == 0)
--#else
-- else if (g_mkdir(nbuf, 0755) == 0)
--#endif
-- n2 = " created";
-- else
-- n2 = " ignored";
-- if (VERBOSE)
-- untar_verbose("%s\n", n2);
-- return 1;
-- }
--
-- /* if not a regular file, then skip it */
-- if (!ISREGULAR(*tblk))
-- {
-- if (VERBOSE)
-- untar_verbose(" ignored\n");
-- outsize = 0L;
-- return 1;
-- }
--
-- /* print file statistics */
-- if (VERBOSE)
-- {
-- untar_verbose(" (%ld byte%s, %ld tape block%s)\n",
-- outsize,
-- outsize == 1 ? "" : "s",
-- (outsize + TSIZE - 1) / TSIZE,
-- (outsize > 0 && outsize <= TSIZE) ? "" : "s");
-- }
--
-- /* if extracting, then try to create the file */
-- if (!LISTING)
-- outfp = createpath(nbuf);
-- else
-- outfp = NULL;
--
-- /* if file is 0 bytes long, then we're done already! */
-- if (outsize == 0 && outfp)
-- {
-- fclose(outfp);
--#ifdef _POSIX_SOURCE
-- utime(nbuf, &timestamp);
-- chmod(nbuf, mode);
--#endif
-- }
-- }
-- return 1;
--}
--
--/* Process an archive file. This involves reading the blocks one at a time
-- * and passing them to a untar() function.
-- */
--int untar(const char *filename, const char* destdir, untar_opt options) {
-- int ret=1;
-- wchar_t curdir[_MAX_PATH];
-- wchar_t *w_destdir;
-- untarops = options;
-- /* open the archive */
-- inname = filename;
-- infp = g_fopen(filename, "rb");
-- if (!infp)
-- {
-- untar_error("Error opening: %s\n", filename);
-- return 0;
-- }
--
-- w_destdir = g_utf8_to_utf16(destdir, -1, NULL, NULL, NULL);
--
-- /* Set current directory */
-- if(!GetCurrentDirectoryW(_MAX_PATH, curdir)) {
-- untar_error("Could not get current directory (error %lu).\n", GetLastError());
-- fclose(infp);
-- return 0;
-- }
-- if(!SetCurrentDirectoryW(w_destdir)) {
-- untar_error("Could not set current directory to (error %lu): %s\n", GetLastError(), destdir);
-- fclose(infp);
-- return 0;
-- } else {
-- /* UNCOMPRESSED */
-- /* send each block to the untar_block() function */
-- while (fread(slide, 1, TSIZE, infp) == TSIZE) {
-- if(!untar_block(slide)) {
-- untar_error("untar failure: %s\n", filename);
-- fclose(infp);
-- ret=0;
-- }
-- }
-- if (outsize > 0 && ret) {
-- untar_warning("Last file might be truncated!\n");
-- fclose(outfp);
-- outfp = NULL;
-- }
-- if(!SetCurrentDirectoryW(curdir)) {
-- untar_error("Could not set current dir back to original (error %lu).\n", GetLastError());
-- ret=0;
-- }
-- }
--
-- g_free(w_destdir);
--
-- /* close the archive file. */
-- fclose(infp);
--
-- return ret;
--}
--
-diff -Nur pidgin-2.10.7/pidgin/win32/untar.h pidgin-2.10.7-nonprism/pidgin/win32/untar.h
---- pidgin-2.10.7/pidgin/win32/untar.h 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/untar.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,30 +0,0 @@
--/*
-- * untar.h
-- *
-- * Author: Herman Bloggs <hermanator12002@yahoo.com>
-- * Date: April, 2003
-- * Description: untar.c header
-- */
--#ifndef _UNTAR_H_
--#define _UNTAR_H_
--
--#ifdef __cplusplus
--extern "C" {
--#endif /* __cplusplus */
--
--typedef enum _untar_opt {
-- UNTAR_LISTING = (1 << 0),
-- UNTAR_QUIET = (1 << 1),
-- UNTAR_VERBOSE = (1 << 2),
-- UNTAR_FORCE = (1 << 3),
-- UNTAR_ABSPATH = (1 << 4),
-- UNTAR_CONVERT = (1 << 5)
--} untar_opt;
--
--int untar(const char *filename, const char *destdir, untar_opt options);
--
--#ifdef __cplusplus
--}
--#endif /* __cplusplus */
--
--#endif
-diff -Nur pidgin-2.10.7/pidgin/win32/winpidgin.c pidgin-2.10.7-nonprism/pidgin/win32/winpidgin.c
---- pidgin-2.10.7/pidgin/win32/winpidgin.c 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/winpidgin.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,834 +0,0 @@
--/*
-- * winpidgin.c
-- *
-- * Date: June, 2002
-- * Description: Entry point for win32 pidgin, and various win32 dependant
-- * routines.
-- *
-- * Pidgin is the legal property of its developers, whose names are too numerous
-- * to list here. Please refer to the COPYRIGHT file distributed with this
-- * source distribution.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--/* This is for ATTACH_PARENT_PROCESS */
--#ifndef _WIN32_WINNT
--#define _WIN32_WINNT 0x501
--#endif
--#include <windows.h>
--#include <fcntl.h>
--#include <stdlib.h>
--#include <string.h>
--#include <stdio.h>
--#include <sys/types.h>
--#include <sys/stat.h>
--#include "config.h"
--
--typedef int (__cdecl* LPFNPIDGINMAIN)(HINSTANCE, int, char**);
--typedef void (WINAPI* LPFNSETDLLDIRECTORY)(LPCWSTR);
--typedef BOOL (WINAPI* LPFNATTACHCONSOLE)(DWORD);
--typedef BOOL (WINAPI* LPFNSETPROCESSDEPPOLICY)(DWORD);
--
--static BOOL portable_mode = FALSE;
--
--/*
-- * PROTOTYPES
-- */
--static LPFNPIDGINMAIN pidgin_main = NULL;
--static LPFNSETDLLDIRECTORY MySetDllDirectory = NULL;
--
--static const wchar_t *get_win32_error_message(DWORD err) {
-- static wchar_t err_msg[512];
--
-- FormatMessageW(
-- FORMAT_MESSAGE_FROM_SYSTEM,
-- NULL, err,
-- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-- (LPWSTR) &err_msg, sizeof(err_msg) / sizeof(wchar_t), NULL);
--
-- return err_msg;
--}
--
--static BOOL read_reg_string(HKEY key, wchar_t *sub_key, wchar_t *val_name, LPBYTE data, LPDWORD data_len) {
-- HKEY hkey;
-- BOOL ret = FALSE;
-- LONG retv;
--
-- if (ERROR_SUCCESS == (retv = RegOpenKeyExW(key, sub_key, 0,
-- KEY_QUERY_VALUE, &hkey))) {
-- if (ERROR_SUCCESS == (retv = RegQueryValueExW(hkey, val_name,
-- NULL, NULL, data, data_len)))
-- ret = TRUE;
-- else {
-- const wchar_t *err_msg = get_win32_error_message(retv);
--
-- wprintf(L"Could not read reg key '%s' subkey '%s' value: '%s'.\nMessage: (%ld) %s\n",
-- (key == HKEY_LOCAL_MACHINE) ? L"HKLM"
-- : ((key == HKEY_CURRENT_USER) ? L"HKCU" : L"???"),
-- sub_key, val_name, retv, err_msg);
-- }
-- RegCloseKey(hkey);
-- }
-- else {
-- wchar_t szBuf[80];
--
-- FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, retv, 0,
-- (LPWSTR) &szBuf, sizeof(szBuf) / sizeof(wchar_t), NULL);
-- wprintf(L"Could not open reg subkey: %s\nError: (%ld) %s\n",
-- sub_key, retv, szBuf);
-- }
--
-- return ret;
--}
--
--static BOOL common_dll_prep(const wchar_t *path) {
-- HMODULE hmod;
-- HKEY hkey;
-- struct _stat stat_buf;
-- wchar_t test_path[MAX_PATH + 1];
--
-- _snwprintf(test_path, sizeof(test_path) / sizeof(wchar_t),
-- L"%s\\libgtk-win32-2.0-0.dll", path);
-- test_path[sizeof(test_path) / sizeof(wchar_t) - 1] = L'\0';
--
-- if (_wstat(test_path, &stat_buf) != 0) {
-- printf("Unable to determine GTK+ path. \n"
-- "Assuming GTK+ is in the PATH.\n");
-- return FALSE;
-- }
--
--
-- wprintf(L"GTK+ path found: %s\n", path);
--
-- if ((hmod = GetModuleHandleW(L"kernel32.dll"))) {
-- MySetDllDirectory = (LPFNSETDLLDIRECTORY) GetProcAddress(
-- hmod, "SetDllDirectoryW");
-- if (!MySetDllDirectory)
-- printf("SetDllDirectory not supported\n");
-- } else
-- printf("Error getting kernel32.dll module handle\n");
--
-- /* For Windows XP SP1+ / Server 2003 we use SetDllDirectory to avoid dll hell */
-- if (MySetDllDirectory) {
-- printf("Using SetDllDirectory\n");
-- MySetDllDirectory(path);
-- }
--
-- /* For the rest, we set the current directory and make sure
-- * SafeDllSearch is set to 0 where needed. */
-- else {
-- OSVERSIONINFOW osinfo;
--
-- printf("Setting current directory to GTK+ dll directory\n");
-- SetCurrentDirectoryW(path);
-- /* For Windows 2000 (SP3+) / WinXP (No SP):
-- * If SafeDllSearchMode is set to 1, Windows system directories are
-- * searched for dlls before the current directory. Therefore we set it
-- * to 0.
-- */
-- osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
-- GetVersionExW(&osinfo);
-- if ((osinfo.dwMajorVersion == 5
-- && osinfo.dwMinorVersion == 0
-- && wcscmp(osinfo.szCSDVersion, L"Service Pack 3") >= 0)
-- ||
-- (osinfo.dwMajorVersion == 5
-- && osinfo.dwMinorVersion == 1
-- && wcscmp(osinfo.szCSDVersion, L"") >= 0)
-- ) {
-- DWORD regval = 1;
-- DWORD reglen = sizeof(DWORD);
--
-- printf("Using Win2k (SP3+) / WinXP (No SP)... Checking SafeDllSearch\n");
-- read_reg_string(HKEY_LOCAL_MACHINE,
-- L"System\\CurrentControlSet\\Control\\Session Manager",
-- L"SafeDllSearchMode",
-- (LPBYTE) &regval,
-- &reglen);
--
-- if (regval != 0) {
-- printf("Trying to set SafeDllSearchMode to 0\n");
-- regval = 0;
-- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
-- L"System\\CurrentControlSet\\Control\\Session Manager",
-- 0, KEY_SET_VALUE, &hkey
-- ) == ERROR_SUCCESS) {
-- if (RegSetValueExW(hkey,
-- L"SafeDllSearchMode", 0,
-- REG_DWORD, (LPBYTE) &regval,
-- sizeof(DWORD)
-- ) != ERROR_SUCCESS)
-- printf("Error writing SafeDllSearchMode. Error: %u\n",
-- (UINT) GetLastError());
-- RegCloseKey(hkey);
-- } else
-- printf("Error opening Session Manager key for writing. Error: %u\n",
-- (UINT) GetLastError());
-- } else
-- printf("SafeDllSearchMode is set to 0\n");
-- }/*end else*/
-- }
--
-- return TRUE;
--}
--
--static BOOL dll_prep(const wchar_t *pidgin_dir) {
-- wchar_t path[MAX_PATH + 1];
-- path[0] = L'\0';
--
-- if (*pidgin_dir) {
-- _snwprintf(path, sizeof(path) / sizeof(wchar_t), L"%s\\Gtk\\bin", pidgin_dir);
-- path[sizeof(path) / sizeof(wchar_t) - 1] = L'\0';
-- }
--
-- return common_dll_prep(path);
--}
--
--static void portable_mode_dll_prep(const wchar_t *pidgin_dir) {
-- /* need to be able to fit MAX_PATH + "PURPLEHOME=" in path2 */
-- wchar_t path[MAX_PATH + 1];
-- wchar_t path2[MAX_PATH + 12];
-- const wchar_t *prev = NULL;
--
-- /* We assume that GTK+ is installed under \\path\to\Pidgin\..\GTK
-- * First we find \\path\to
-- */
-- if (*pidgin_dir)
-- /* pidgin_dir points to \\path\to\Pidgin */
-- prev = wcsrchr(pidgin_dir, L'\\');
--
-- if (prev) {
-- int cnt = (prev - pidgin_dir);
-- wcsncpy(path, pidgin_dir, cnt);
-- path[cnt] = L'\0';
-- } else {
-- printf("Unable to determine current executable path. \n"
-- "This will prevent the settings dir from being set.\n"
-- "Assuming GTK+ is in the PATH.\n");
-- return;
-- }
--
-- /* Set $HOME so that the GTK+ settings get stored in the right place */
-- _snwprintf(path2, sizeof(path2) / sizeof(wchar_t), L"HOME=%s", path);
-- _wputenv(path2);
--
-- /* Set up the settings dir base to be \\path\to
-- * The actual settings dir will be \\path\to\.purple */
-- _snwprintf(path2, sizeof(path2) / sizeof(wchar_t), L"PURPLEHOME=%s", path);
-- wprintf(L"Setting settings dir: %s\n", path2);
-- _wputenv(path2);
--
-- if (!dll_prep(pidgin_dir)) {
-- /* set the GTK+ path to be \\path\to\GTK\bin */
-- wcscat(path, L"\\GTK\\bin");
-- common_dll_prep(path);
-- }
--}
--
--static wchar_t* winpidgin_lcid_to_posix(LCID lcid) {
-- wchar_t *posix = NULL;
-- int lang_id = PRIMARYLANGID(lcid);
-- int sub_id = SUBLANGID(lcid);
--
-- switch (lang_id) {
-- case LANG_AFRIKAANS: posix = L"af"; break;
-- case LANG_ARABIC: posix = L"ar"; break;
-- case LANG_AZERI: posix = L"az"; break;
-- case LANG_BENGALI: posix = L"bn"; break;
-- case LANG_BULGARIAN: posix = L"bg"; break;
-- case LANG_CATALAN: posix = L"ca"; break;
-- case LANG_CZECH: posix = L"cs"; break;
-- case LANG_DANISH: posix = L"da"; break;
-- case LANG_ESTONIAN: posix = L"et"; break;
-- case LANG_PERSIAN: posix = L"fa"; break;
-- case LANG_GERMAN: posix = L"de"; break;
-- case LANG_GREEK: posix = L"el"; break;
-- case LANG_ENGLISH:
-- switch (sub_id) {
-- case SUBLANG_ENGLISH_UK:
-- posix = L"en_GB"; break;
-- case SUBLANG_ENGLISH_AUS:
-- posix = L"en_AU"; break;
-- case SUBLANG_ENGLISH_CAN:
-- posix = L"en_CA"; break;
-- default:
-- posix = L"en"; break;
-- }
-- break;
-- case LANG_SPANISH: posix = L"es"; break;
-- case LANG_BASQUE: posix = L"eu"; break;
-- case LANG_FINNISH: posix = L"fi"; break;
-- case LANG_FRENCH: posix = L"fr"; break;
-- case LANG_GALICIAN: posix = L"gl"; break;
-- case LANG_GUJARATI: posix = L"gu"; break;
-- case LANG_HEBREW: posix = L"he"; break;
-- case LANG_HINDI: posix = L"hi"; break;
-- case LANG_HUNGARIAN: posix = L"hu"; break;
-- case LANG_ICELANDIC: break;
-- case LANG_INDONESIAN: posix = L"id"; break;
-- case LANG_ITALIAN: posix = L"it"; break;
-- case LANG_JAPANESE: posix = L"ja"; break;
-- case LANG_GEORGIAN: posix = L"ka"; break;
-- case LANG_KANNADA: posix = L"kn"; break;
-- case LANG_KOREAN: posix = L"ko"; break;
-- case LANG_LITHUANIAN: posix = L"lt"; break;
-- case LANG_MACEDONIAN: posix = L"mk"; break;
-- case LANG_DUTCH: posix = L"nl"; break;
-- case LANG_NEPALI: posix = L"ne"; break;
-- case LANG_NORWEGIAN:
-- switch (sub_id) {
-- case SUBLANG_NORWEGIAN_BOKMAL:
-- posix = L"nb"; break;
-- case SUBLANG_NORWEGIAN_NYNORSK:
-- posix = L"nn"; break;
-- }
-- break;
-- case LANG_PUNJABI: posix = L"pa"; break;
-- case LANG_POLISH: posix = L"pl"; break;
-- case LANG_PASHTO: posix = L"ps"; break;
-- case LANG_PORTUGUESE:
-- switch (sub_id) {
-- case SUBLANG_PORTUGUESE_BRAZILIAN:
-- posix = L"pt_BR"; break;
-- default:
-- posix = L"pt"; break;
-- }
-- break;
-- case LANG_ROMANIAN: posix = L"ro"; break;
-- case LANG_RUSSIAN: posix = L"ru"; break;
-- case LANG_SLOVAK: posix = L"sk"; break;
-- case LANG_SLOVENIAN: posix = L"sl"; break;
-- case LANG_ALBANIAN: posix = L"sq"; break;
-- /* LANG_CROATIAN == LANG_SERBIAN == LANG_BOSNIAN */
-- case LANG_SERBIAN:
-- switch (sub_id) {
-- case SUBLANG_SERBIAN_LATIN:
-- posix = L"sr@Latn"; break;
-- case SUBLANG_SERBIAN_CYRILLIC:
-- posix = L"sr"; break;
-- case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC:
-- case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN:
-- posix = L"bs"; break;
-- case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN:
-- posix = L"hr"; break;
-- }
-- break;
-- case LANG_SWEDISH: posix = L"sv"; break;
-- case LANG_TAMIL: posix = L"ta"; break;
-- case LANG_TELUGU: posix = L"te"; break;
-- case LANG_THAI: posix = L"th"; break;
-- case LANG_TURKISH: posix = L"tr"; break;
-- case LANG_UKRAINIAN: posix = L"uk"; break;
-- case LANG_VIETNAMESE: posix = L"vi"; break;
-- case LANG_XHOSA: posix = L"xh"; break;
-- case LANG_CHINESE:
-- switch (sub_id) {
-- case SUBLANG_CHINESE_SIMPLIFIED:
-- posix = L"zh_CN"; break;
-- case SUBLANG_CHINESE_TRADITIONAL:
-- posix = L"zh_TW"; break;
-- default:
-- posix = L"zh"; break;
-- }
-- break;
-- case LANG_URDU: break;
-- case LANG_BELARUSIAN: break;
-- case LANG_LATVIAN: break;
-- case LANG_ARMENIAN: break;
-- case LANG_FAEROESE: break;
-- case LANG_MALAY: break;
-- case LANG_KAZAK: break;
-- case LANG_KYRGYZ: break;
-- case LANG_SWAHILI: break;
-- case LANG_UZBEK: break;
-- case LANG_TATAR: break;
-- case LANG_ORIYA: break;
-- case LANG_MALAYALAM: break;
-- case LANG_ASSAMESE: break;
-- case LANG_MARATHI: break;
-- case LANG_SANSKRIT: break;
-- case LANG_MONGOLIAN: break;
-- case LANG_KONKANI: break;
-- case LANG_MANIPURI: break;
-- case LANG_SINDHI: break;
-- case LANG_SYRIAC: break;
-- case LANG_KASHMIRI: break;
-- case LANG_DIVEHI: break;
-- }
--
-- /* Deal with exceptions */
-- if (posix == NULL) {
-- switch (lcid) {
-- case 0x0455: posix = L"my_MM"; break; /* Myanmar (Burmese) */
-- case 9999: posix = L"ku"; break; /* Kurdish (from NSIS) */
-- }
-- }
--
-- return posix;
--}
--
--/* Determine and set Pidgin locale as follows (in order of priority):
-- - Check PIDGINLANG env var
-- - Check NSIS Installer Language reg value
-- - Use default user locale
--*/
--static const wchar_t *winpidgin_get_locale() {
-- const wchar_t *locale = NULL;
-- LCID lcid;
-- wchar_t data[10];
-- DWORD datalen = sizeof(data) / sizeof(wchar_t);
--
-- /* Check if user set PIDGINLANG env var */
-- if ((locale = _wgetenv(L"PIDGINLANG")))
-- return locale;
--
-- if (!portable_mode && read_reg_string(HKEY_CURRENT_USER, L"SOFTWARE\\pidgin",
-- L"Installer Language", (LPBYTE) &data, &datalen)) {
-- if ((locale = winpidgin_lcid_to_posix(_wtoi(data))))
-- return locale;
-- }
--
-- lcid = GetUserDefaultLCID();
-- if ((locale = winpidgin_lcid_to_posix(lcid)))
-- return locale;
--
-- return L"en";
--}
--
--static void winpidgin_set_locale() {
-- const wchar_t *locale;
-- wchar_t envstr[25];
--
-- locale = winpidgin_get_locale();
--
-- _snwprintf(envstr, sizeof(envstr) / sizeof(wchar_t), L"LANG=%s", locale);
-- wprintf(L"Setting locale: %s\n", envstr);
-- _wputenv(envstr);
--}
--
--
--static void winpidgin_add_stuff_to_path() {
-- wchar_t perl_path[MAX_PATH + 1];
-- wchar_t *ppath = NULL;
-- wchar_t mit_kerberos_path[MAX_PATH + 1];
-- wchar_t *mpath = NULL;
-- DWORD plen;
--
-- printf("%s", "Looking for Perl... ");
--
-- plen = sizeof(perl_path) / sizeof(wchar_t);
-- if (read_reg_string(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Perl", L"",
-- (LPBYTE) &perl_path, &plen)) {
-- /* We *could* check for perl510.dll, but it seems unnecessary. */
-- wprintf(L"found in '%s'.\n", perl_path);
--
-- if (perl_path[wcslen(perl_path) - 1] != L'\\')
-- wcscat(perl_path, L"\\");
-- wcscat(perl_path, L"bin");
--
-- ppath = perl_path;
-- } else
-- printf("%s", "not found.\n");
--
-- printf("%s", "Looking for MIT Kerberos... ");
--
-- plen = sizeof(mit_kerberos_path) / sizeof(wchar_t);
-- if (read_reg_string(HKEY_LOCAL_MACHINE, L"SOFTWARE\\MIT\\Kerberos", L"InstallDir",
-- (LPBYTE) &mit_kerberos_path, &plen)) {
-- /* We *could* check for gssapi32.dll */
-- wprintf(L"found in '%s'.\n", mit_kerberos_path);
--
-- if (mit_kerberos_path[wcslen(mit_kerberos_path) - 1] != L'\\')
-- wcscat(mit_kerberos_path, L"\\");
-- wcscat(mit_kerberos_path, L"bin");
--
-- mpath = mit_kerberos_path;
-- } else
-- printf("%s", "not found.\n");
--
-- if (ppath != NULL || mpath != NULL) {
-- const wchar_t *path = _wgetenv(L"PATH");
-- BOOL add_ppath = ppath != NULL && (path == NULL || !wcsstr(path, ppath));
-- BOOL add_mpath = mpath != NULL && (path == NULL || !wcsstr(path, mpath));
-- wchar_t *newpath;
-- int newlen;
--
-- if (add_ppath || add_mpath) {
-- /* Enough to add "PATH=" + path + ";" + ppath + ";" + mpath + \0 */
-- newlen = 6 + (path ? wcslen(path) + 1 : 0);
-- if (add_ppath)
-- newlen += wcslen(ppath) + 1;
-- if (add_mpath)
-- newlen += wcslen(mpath) + 1;
-- newpath = malloc(newlen * sizeof(wchar_t));
--
-- _snwprintf(newpath, newlen, L"PATH=%s%s%s%s%s%s",
-- path ? path : L"",
-- path ? L";" : L"",
-- add_ppath ? ppath : L"",
-- add_ppath ? L";" : L"",
-- add_mpath ? mpath : L"",
-- add_mpath ? L";" : L"");
--
-- wprintf(L"New PATH: %s\n", newpath);
--
-- _wputenv(newpath);
-- free(newpath);
-- }
-- }
--}
--
--#define PIDGIN_WM_FOCUS_REQUEST (WM_APP + 13)
--#define PIDGIN_WM_PROTOCOL_HANDLE (WM_APP + 14)
--
--static BOOL winpidgin_set_running(BOOL fail_if_running) {
-- HANDLE h;
--
-- if ((h = CreateMutexW(NULL, FALSE, L"pidgin_is_running"))) {
-- DWORD err = GetLastError();
-- if (err == ERROR_ALREADY_EXISTS) {
-- if (fail_if_running) {
-- HWND msg_win;
--
-- printf("An instance of Pidgin is already running.\n");
--
-- if((msg_win = FindWindowExW(NULL, NULL, L"WinpidginMsgWinCls", NULL)))
-- if(SendMessage(msg_win, PIDGIN_WM_FOCUS_REQUEST, (WPARAM) NULL, (LPARAM) NULL))
-- return FALSE;
--
-- /* If we get here, the focus request wasn't successful */
--
-- MessageBoxW(NULL,
-- L"An instance of Pidgin is already running",
-- NULL, MB_OK | MB_TOPMOST);
--
-- return FALSE;
-- }
-- } else if (err != ERROR_SUCCESS)
-- printf("Error (%u) accessing \"pidgin_is_running\" mutex.\n", (UINT) err);
-- }
-- return TRUE;
--}
--
--#define PROTO_HANDLER_SWITCH L"--protocolhandler="
--
--static void handle_protocol(wchar_t *cmd) {
-- char *remote_msg, *utf8msg;
-- wchar_t *tmp1, *tmp2;
-- int len, wlen;
-- SIZE_T len_written;
-- HWND msg_win;
-- DWORD pid;
-- HANDLE process;
--
-- /* The start of the message */
-- tmp1 = cmd + wcslen(PROTO_HANDLER_SWITCH);
--
-- /* The end of the message */
-- if ((tmp2 = wcschr(tmp1, L' ')))
-- wlen = (tmp2 - tmp1);
-- else
-- wlen = wcslen(tmp1);
--
-- if (wlen == 0) {
-- printf("No protocol message specified.\n");
-- return;
-- }
--
-- if (!(msg_win = FindWindowExW(NULL, NULL, L"WinpidginMsgWinCls", NULL))) {
-- printf("Unable to find an instance of Pidgin to handle protocol message.\n");
-- return;
-- }
--
-- len = WideCharToMultiByte(CP_UTF8, 0, tmp1,
-- wlen, NULL, 0, NULL, NULL);
-- if (len) {
-- utf8msg = malloc(len);
-- len = WideCharToMultiByte(CP_UTF8, 0, tmp1,
-- wlen, utf8msg, len, NULL, NULL);
-- }
--
-- if (len == 0) {
-- printf("No protocol message specified.\n");
-- return;
-- }
--
-- GetWindowThreadProcessId(msg_win, &pid);
-- if (!(process = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, pid))) {
-- DWORD dw = GetLastError();
-- const wchar_t *err_msg = get_win32_error_message(dw);
-- wprintf(L"Unable to open Pidgin process. (%u) %s\n", (UINT) dw, err_msg);
-- return;
-- }
--
-- wprintf(L"Trying to handle protocol message:\n'%.*s'\n", wlen, tmp1);
--
-- /* MEM_COMMIT initializes the memory to zero
-- * so we don't need to worry that our section of utf8msg isn't nul-terminated */
-- if ((remote_msg = (char*) VirtualAllocEx(process, NULL, len + 1, MEM_COMMIT, PAGE_READWRITE))) {
-- if (WriteProcessMemory(process, remote_msg, utf8msg, len, &len_written)) {
-- if (!SendMessageA(msg_win, PIDGIN_WM_PROTOCOL_HANDLE, len_written, (LPARAM) remote_msg))
-- printf("Unable to send protocol message to Pidgin instance.\n");
-- } else {
-- DWORD dw = GetLastError();
-- const wchar_t *err_msg = get_win32_error_message(dw);
-- wprintf(L"Unable to write to remote memory. (%u) %s\n", (UINT) dw, err_msg);
-- }
--
-- VirtualFreeEx(process, remote_msg, 0, MEM_RELEASE);
-- } else {
-- DWORD dw = GetLastError();
-- const wchar_t *err_msg = get_win32_error_message(dw);
-- wprintf(L"Unable to allocate remote memory. (%u) %s\n", (UINT) dw, err_msg);
-- }
--
-- CloseHandle(process);
-- free(utf8msg);
--}
--
--
--int _stdcall
--WinMain (struct HINSTANCE__ *hInstance, struct HINSTANCE__ *hPrevInstance,
-- char *lpszCmdLine, int nCmdShow) {
-- wchar_t errbuf[512];
-- wchar_t pidgin_dir[MAX_PATH];
-- wchar_t *pidgin_dir_start = NULL;
-- wchar_t exe_name[MAX_PATH];
-- HMODULE hmod;
-- wchar_t *wtmp;
-- int pidgin_argc;
-- char **pidgin_argv; /* This is in utf-8 */
-- int i, j, k;
-- BOOL debug = FALSE, help = FALSE, version = FALSE, multiple = FALSE, success;
-- LPWSTR *szArglist;
-- LPWSTR cmdLine;
--
-- /* If debug or help or version flag used, create console for output */
-- for (i = 1; i < __argc; i++) {
-- if (strlen(__argv[i]) > 1 && __argv[i][0] == '-') {
-- /* check if we're looking at -- or - option */
-- if (__argv[i][1] == '-') {
-- if (strstr(__argv[i], "--debug") == __argv[i])
-- debug = TRUE;
-- else if (strstr(__argv[i], "--help") == __argv[i])
-- help = TRUE;
-- else if (strstr(__argv[i], "--version") == __argv[i])
-- version = TRUE;
-- else if (strstr(__argv[i], "--multiple") == __argv[i])
-- multiple = TRUE;
-- } else {
-- if (strchr(__argv[i], 'd'))
-- debug = TRUE;
-- if (strchr(__argv[i], 'h'))
-- help = TRUE;
-- if (strchr(__argv[i], 'v'))
-- version = TRUE;
-- if (strchr(__argv[i], 'm'))
-- multiple = TRUE;
-- }
-- }
-- }
--
-- /* Permanently enable DEP if the OS supports it */
-- if ((hmod = GetModuleHandleW(L"kernel32.dll"))) {
-- LPFNSETPROCESSDEPPOLICY MySetProcessDEPPolicy =
-- (LPFNSETPROCESSDEPPOLICY)
-- GetProcAddress(hmod, "SetProcessDEPPolicy");
-- if (MySetProcessDEPPolicy)
-- MySetProcessDEPPolicy(1); //PROCESS_DEP_ENABLE
-- }
--
-- if (debug || help || version) {
-- /* If stdout hasn't been redirected to a file, alloc a console
-- * (_istty() doesn't work for stuff using the GUI subsystem) */
-- if (_fileno(stdout) == -1 || _fileno(stdout) == -2) {
-- LPFNATTACHCONSOLE MyAttachConsole = NULL;
-- if (hmod)
-- MyAttachConsole =
-- (LPFNATTACHCONSOLE)
-- GetProcAddress(hmod, "AttachConsole");
-- if ((MyAttachConsole && MyAttachConsole(ATTACH_PARENT_PROCESS))
-- || AllocConsole()) {
-- freopen("CONOUT$", "w", stdout);
-- freopen("CONOUT$", "w", stderr);
-- }
-- }
-- }
--
-- cmdLine = GetCommandLineW();
--
-- /* If this is a protocol handler invocation, deal with it accordingly */
-- if ((wtmp = wcsstr(cmdLine, PROTO_HANDLER_SWITCH)) != NULL) {
-- handle_protocol(wtmp);
-- return 0;
-- }
--
-- /* Load exception handler if we have it */
-- if (GetModuleFileNameW(NULL, pidgin_dir, MAX_PATH) != 0) {
--
-- /* primitive dirname() */
-- pidgin_dir_start = wcsrchr(pidgin_dir, L'\\');
--
-- if (pidgin_dir_start) {
-- HMODULE hmod;
-- pidgin_dir_start[0] = L'\0';
--
-- /* tmp++ will now point to the executable file name */
-- wcscpy(exe_name, pidgin_dir_start + 1);
--
-- wcscat(pidgin_dir, L"\\exchndl.dll");
-- if ((hmod = LoadLibraryW(pidgin_dir))) {
-- typedef void (__cdecl* LPFNSETLOGFILE)(const LPCSTR);
-- LPFNSETLOGFILE MySetLogFile;
-- /* exchndl.dll is built without UNICODE */
-- char debug_dir[MAX_PATH];
-- printf("Loaded exchndl.dll\n");
-- /* Temporarily override exchndl.dll's logfile
-- * to something sane (Pidgin will override it
-- * again when it initializes) */
-- MySetLogFile = (LPFNSETLOGFILE) GetProcAddress(hmod, "SetLogFile");
-- if (MySetLogFile) {
-- if (GetTempPathA(sizeof(debug_dir), debug_dir) != 0) {
-- strcat(debug_dir, "pidgin.RPT");
-- printf(" Setting exchndl.dll LogFile to %s\n",
-- debug_dir);
-- MySetLogFile(debug_dir);
-- }
-- }
-- /* The function signature for SetDebugInfoDir is the same as SetLogFile,
-- * so we can reuse the variable */
-- MySetLogFile = (LPFNSETLOGFILE) GetProcAddress(hmod, "SetDebugInfoDir");
-- if (MySetLogFile) {
-- char *pidgin_dir_ansi = NULL;
-- /* Restore pidgin_dir to point to where the executable is */
-- pidgin_dir_start[0] = L'\0';
-- i = WideCharToMultiByte(CP_ACP, 0, pidgin_dir,
-- -1, NULL, 0, NULL, NULL);
-- if (i != 0) {
-- pidgin_dir_ansi = malloc(i);
-- i = WideCharToMultiByte(CP_ACP, 0, pidgin_dir,
-- -1, pidgin_dir_ansi, i, NULL, NULL);
-- if (i == 0) {
-- free(pidgin_dir_ansi);
-- pidgin_dir_ansi = NULL;
-- }
-- }
-- if (pidgin_dir_ansi != NULL) {
-- _snprintf(debug_dir, sizeof(debug_dir),
-- "%s\\pidgin-%s-dbgsym",
-- pidgin_dir_ansi, VERSION);
-- debug_dir[sizeof(debug_dir) - 1] = '\0';
-- printf(" Setting exchndl.dll DebugInfoDir to %s\n",
-- debug_dir);
-- MySetLogFile(debug_dir);
-- free(pidgin_dir_ansi);
-- }
-- }
--
-- }
--
-- /* Restore pidgin_dir to point to where the executable is */
-- pidgin_dir_start[0] = L'\0';
-- }
-- } else {
-- DWORD dw = GetLastError();
-- const wchar_t *err_msg = get_win32_error_message(dw);
-- _snwprintf(errbuf, 512,
-- L"Error getting module filename.\nError: (%u) %s",
-- (UINT) dw, err_msg);
-- wprintf(L"%s\n", errbuf);
-- MessageBoxW(NULL, errbuf, NULL, MB_OK | MB_TOPMOST);
-- pidgin_dir[0] = L'\0';
-- }
--
-- /* Determine if we're running in portable mode */
-- if (wcsstr(cmdLine, L"--portable-mode")
-- || (exe_name != NULL && wcsstr(exe_name, L"-portable.exe"))) {
-- printf("Running in PORTABLE mode.\n");
-- portable_mode = TRUE;
-- }
--
-- if (portable_mode)
-- portable_mode_dll_prep(pidgin_dir);
-- else if (!getenv("PIDGIN_NO_DLL_CHECK"))
-- dll_prep(pidgin_dir);
--
-- winpidgin_set_locale();
--
-- winpidgin_add_stuff_to_path();
--
-- /* If help, version or multiple flag used, do not check Mutex */
-- if (!help && !version)
-- if (!winpidgin_set_running(getenv("PIDGIN_MULTI_INST") == NULL && !multiple))
-- return 0;
--
-- /* Now we are ready for Pidgin .. */
-- wcscat(pidgin_dir, L"\\pidgin.dll");
-- if ((hmod = LoadLibraryW(pidgin_dir)))
-- pidgin_main = (LPFNPIDGINMAIN) GetProcAddress(hmod, "pidgin_main");
--
-- /* Restore pidgin_dir to point to where the executable is */
-- if (pidgin_dir_start)
-- pidgin_dir_start[0] = L'\0';
--
-- if (!pidgin_main) {
-- DWORD dw = GetLastError();
-- BOOL mod_not_found = (dw == ERROR_MOD_NOT_FOUND || dw == ERROR_DLL_NOT_FOUND);
-- const wchar_t *err_msg = get_win32_error_message(dw);
--
-- _snwprintf(errbuf, 512, L"Error loading pidgin.dll.\nError: (%u) %s%s%s",
-- (UINT) dw, err_msg,
-- mod_not_found ? L"\n" : L"",
-- mod_not_found ? L"This probably means that GTK+ can't be found." : L"");
-- wprintf(L"%s\n", errbuf);
-- MessageBoxW(NULL, errbuf, L"Error", MB_OK | MB_TOPMOST);
--
-- return 0;
-- }
--
-- /* Convert argv to utf-8*/
-- szArglist = CommandLineToArgvW(cmdLine, &j);
-- pidgin_argc = j;
-- pidgin_argv = malloc(pidgin_argc* sizeof(char*));
-- k = 0;
-- for (i = 0; i < j; i++) {
-- success = FALSE;
-- /* Remove the --portable-mode arg from the args passed to pidgin so it doesn't choke */
-- if (wcsstr(szArglist[i], L"--portable-mode") == NULL) {
-- int len = WideCharToMultiByte(CP_UTF8, 0, szArglist[i],
-- -1, NULL, 0, NULL, NULL);
-- if (len != 0) {
-- char *arg = malloc(len);
-- len = WideCharToMultiByte(CP_UTF8, 0, szArglist[i],
-- -1, arg, len, NULL, NULL);
-- if (len != 0) {
-- pidgin_argv[k++] = arg;
-- success = TRUE;
-- }
-- }
-- if (!success)
-- wprintf(L"Error converting argument '%s' to UTF-8\n",
-- szArglist[i]);
-- }
-- if (!success)
-- pidgin_argc--;
-- }
-- LocalFree(szArglist);
--
--
-- return pidgin_main(hInstance, pidgin_argc, pidgin_argv);
--}
-diff -Nur pidgin-2.10.7/pidgin/win32/wspell.c pidgin-2.10.7-nonprism/pidgin/win32/wspell.c
---- pidgin-2.10.7/pidgin/win32/wspell.c 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/wspell.c 1969-12-31 21:00:00.000000000 -0300
-@@ -1,110 +0,0 @@
--/*
-- * pidgin
-- *
-- * File: wspell.c
-- * Date: March, 2003
-- * Description: Windows Pidgin gtkspell interface.
-- *
-- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--
--#ifdef HAVE_CONFIG_H
--#include <config.h>
--#endif
--#ifdef USE_GTKSPELL
--#include <windows.h>
--#include <string.h>
--#include <stdlib.h>
--#include <glib.h>
--#include <gtk/gtk.h>
--#include <gtkspell/gtkspell.h>
--#include "debug.h"
--#include "win32dep.h"
--#include "wspell.h"
--
--/* Intermediate function so that we can eat Enchant error popups when it doesn't find a DLL
-- * This is fixed upstream, but not released */
--GtkSpell* (*wpidginspell_new_attach_proxy) (GtkTextView *,
-- const gchar *,
-- GError **) = NULL;
--
--/* GTKSPELL DUMMY FUNCS */
--static GtkSpell* wgtkspell_new_attach(GtkTextView *view, const gchar *lang, GError **error) {
-- GtkSpell *ret = NULL;
-- if (wpidginspell_new_attach_proxy) {
-- UINT old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
-- ret = wpidginspell_new_attach_proxy(view, lang, error);
-- SetErrorMode(old_error_mode);
-- }
-- return ret;
--}
--static GtkSpell* wgtkspell_get_from_text_view(GtkTextView *view) {return NULL;}
--static void wgtkspell_detach(GtkSpell *spell) {}
--static gboolean wgtkspell_set_language(GtkSpell *spell, const gchar *lang, GError **error) {return FALSE;}
--static void wgtkspell_recheck_all(GtkSpell *spell) {}
--
--/* GTKSPELL PROTOS */
--GtkSpell* (*wpidginspell_new_attach) (GtkTextView *,
-- const gchar *,
-- GError **) = wgtkspell_new_attach;
--
--GtkSpell* (*wpidginspell_get_from_text_view) (GtkTextView*) = wgtkspell_get_from_text_view;
--
--void (*wpidginspell_detach) (GtkSpell*) = wgtkspell_detach;
--
--gboolean (*wpidginspell_set_language) (GtkSpell*,
-- const gchar*,
-- GError**) = wgtkspell_set_language;
--
--void (*wpidginspell_recheck_all) (GtkSpell*) = wgtkspell_recheck_all;
--
--#define GTKSPELL_DLL "libgtkspell-0.dll"
--
--static void load_gtkspell() {
-- UINT old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
-- gchar *tmp, *tmp2;
--
-- const char *path = g_getenv("PATH");
-- tmp = g_build_filename(wpurple_install_dir(), "spellcheck", NULL);
-- tmp2 = g_strdup_printf("%s%s%s", tmp,
-- (path ? G_SEARCHPATH_SEPARATOR_S : ""),
-- (path ? path : ""));
-- g_free(tmp);
-- g_setenv("PATH", tmp2, TRUE);
-- g_free(tmp2);
--
-- tmp = g_build_filename(wpurple_install_dir(), "spellcheck", GTKSPELL_DLL, NULL);
-- /* Suppress error popups */
-- wpidginspell_new_attach_proxy = (void*) wpurple_find_and_loadproc(tmp, "gtkspell_new_attach" );
-- if (wpidginspell_new_attach_proxy) {
-- wpidginspell_get_from_text_view = (void*) wpurple_find_and_loadproc(tmp, "gtkspell_get_from_text_view");
-- wpidginspell_detach = (void*) wpurple_find_and_loadproc(tmp, "gtkspell_detach");
-- wpidginspell_set_language = (void*) wpurple_find_and_loadproc(tmp, "gtkspell_set_language");
-- wpidginspell_recheck_all = (void*) wpurple_find_and_loadproc(tmp, "gtkspell_recheck_all");
-- } else {
-- purple_debug_warning("wspell", "Couldn't load gtkspell (%s) \n", tmp);
-- /*wpidginspell_new_attach = wgtkspell_new_attach;*/
-- }
-- g_free(tmp);
-- SetErrorMode(old_error_mode);
--}
--
--void winpidgin_spell_init() {
-- load_gtkspell();
--}
--#endif
-diff -Nur pidgin-2.10.7/pidgin/win32/wspell.h pidgin-2.10.7-nonprism/pidgin/win32/wspell.h
---- pidgin-2.10.7/pidgin/win32/wspell.h 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/pidgin/win32/wspell.h 1969-12-31 21:00:00.000000000 -0300
-@@ -1,57 +0,0 @@
--/*
-- * pidgin
-- *
-- * File: wspell.h
-- *
-- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License as published by
-- * the Free Software Foundation; either version 2 of the License, or
-- * (at your option) any later version.
-- *
-- * This program is distributed in the hope that it will be useful,
-- * but WITHOUT ANY WARRANTY; without even the implied warranty of
-- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- * GNU General Public License for more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-- *
-- */
--#ifndef _WSPELL_H_
--#define _WSPELL_H_
--#include <gtkspell/gtkspell.h>
--
--#ifdef __cplusplus
--extern "C" {
--#endif /* __cplusplus */
--
--void winpidgin_spell_init(void);
--
--extern GtkSpell* (*wpidginspell_new_attach)(GtkTextView*, const gchar*, GError**);
--#define gtkspell_new_attach( view, lang, error ) \
--wpidginspell_new_attach( view, lang, error )
--
--extern GtkSpell* (*wpidginspell_get_from_text_view)(GtkTextView*);
--#define gtkspell_get_from_text_view( view ) \
--wpidginspell_get_from_text_view( view )
--
--extern void (*wpidginspell_detach)(GtkSpell*);
--#define gtkspell_detach( spell ) \
--wpidginspell_detach( spell )
--
--extern gboolean (*wpidginspell_set_language)(GtkSpell*, const gchar*, GError**);
--#define gtkspell_set_language( spell, lang, error ) \
--wpidginspell_set_language( spell, lang, error )
--
--extern void (*wpidginspell_recheck_all)(GtkSpell*);
--#define gtkspell_recheck_all( spell ) \
--wpidginspell_recheck_all( spell )
--
--#ifdef __cplusplus
--}
--#endif /* __cplusplus */
--
--#endif /* _WSPELL_H_ */
diff -Nur pidgin-2.10.7/pidgin.apspec.in pidgin-2.10.7-nonprism/pidgin.apspec.in
--- pidgin-2.10.7/pidgin.apspec.in 2013-02-11 07:16:53.000000000 -0200
+++ pidgin-2.10.7-nonprism/pidgin.apspec.in 2013-08-16 20:53:14.523862926 -0300
@@ -171338,170 +4928,3 @@ diff -Nur pidgin-2.10.7/pidgin.spec.in pidgin-2.10.7-nonprism/pidgin.spec.in
* Sun Oct 30 2005 Stu Tomlinson <stu@nosnilmot.com>
- Add separate gaim-bonjour package if built with --with-howl
- Add separate gaim-mono package if built with --with-mono
-diff -Nur pidgin-2.10.7/po/Makefile.mingw pidgin-2.10.7-nonprism/po/Makefile.mingw
---- pidgin-2.10.7/po/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
-+++ pidgin-2.10.7-nonprism/po/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,54 +0,0 @@
--# Makefile.mingw
--#
--# Description: Makefile to generate mo files
--#
--
--PIDGIN_TREE_TOP := ..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--PACKAGE = pidgin
--
--.SUFFIXES:
--.SUFFIXES: .po .gmo
--
--##
--## SOURCES, OBJECTS
--##
--
--CATALOGS = $(patsubst %.po,%.gmo,$(wildcard *.po))
--
--##
--## RULES
--##
--
--.po.gmo:
-- rm -f $@ && $(GMSGFMT) --statistics -o $@ $<
--
--##
--## TARGETS
--##
--
--.PHONY: all install clean
--
--all: $(CATALOGS)
--
--install: all
-- mkdir -p $(PURPLE_INSTALL_PO_DIR)
-- @catalogs='$(CATALOGS)'; \
-- for cat in $$catalogs; do \
-- cat=`basename $$cat`; \
-- lang=`echo $$cat | sed 's/\.gmo$$//'`; \
-- dir=$(PURPLE_INSTALL_PO_DIR)/$$lang/LC_MESSAGES; \
-- mkdir -p $$dir; \
-- if test -r $$cat; then \
-- cp $$cat $$dir/$(PACKAGE).mo; \
-- echo "installing $$cat as $$dir/$(PACKAGE).mo"; \
-- else \
-- cp $(PURPLE_PO_TOP)/$$cat $$dir/$(PACKAGE).mo; \
-- echo "installing $(PURPLE_PO_TOP)/$$cat as" \
-- "$$dir/$(PACKAGE).mo"; \
-- fi; \
-- done
--
--clean:
-- rm -f *.gmo
-diff -Nur pidgin-2.10.7/README pidgin-2.10.7-nonprism/README
---- pidgin-2.10.7/README 2013-02-11 07:16:50.000000000 -0200
-+++ pidgin-2.10.7-nonprism/README 2013-08-16 23:06:39.859153182 -0300
-@@ -4,7 +4,7 @@
-
- libpurple is a library intended to be used by programmers seeking
- to write an IM client that connects to many IM networks. It supports
--AIM, ICQ, XMPP, MSN and Yahoo!, among others.
-+XMPP, among others.
-
- Pidgin is a graphical IM client written in C which uses the GTK+
- toolkit.
-diff -Nur pidgin-2.10.7/share/ca-certs/Makefile.in pidgin-2.10.7-nonprism/share/ca-certs/Makefile.in
---- pidgin-2.10.7/share/ca-certs/Makefile.in 2013-02-11 07:17:24.000000000 -0200
-+++ pidgin-2.10.7-nonprism/share/ca-certs/Makefile.in 2013-08-17 00:03:38.308758187 -0300
-@@ -151,8 +151,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -214,8 +212,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/share/ca-certs/Makefile.mingw pidgin-2.10.7-nonprism/share/ca-certs/Makefile.mingw
---- pidgin-2.10.7/share/ca-certs/Makefile.mingw 2013-02-11 07:16:57.000000000 -0200
-+++ pidgin-2.10.7-nonprism/share/ca-certs/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,27 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of Pidgin ca-certs
--#
--
--PIDGIN_TREE_TOP := ../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--datadir := $(PIDGIN_INSTALL_DIR)
---include ./Makefile.am.mingw
--cacertsdir := $(PIDGIN_INSTALL_DIR)/ca-certs
--
--.PHONY: install clean
--
--install: ./Makefile.am.mingw
-- if test '$(cacerts_DATA)'; then \
-- mkdir -p $(cacertsdir); \
-- cp $(cacerts_DATA) $(cacertsdir); \
-- fi;
--
--clean:
-- rm -f ./Makefile.am.mingw
--
--./Makefile.am.mingw: ./Makefile.am
-- sed -e 's/^if\ INSTALL_SSL_CERTIFICATES/ifeq (\$$(INSTALL_SSL_CERTIFICATES), 1)/' ./Makefile.am > $@
--
-diff -Nur pidgin-2.10.7/share/sounds/Makefile.in pidgin-2.10.7-nonprism/share/sounds/Makefile.in
---- pidgin-2.10.7/share/sounds/Makefile.in 2013-02-11 07:17:24.000000000 -0200
-+++ pidgin-2.10.7-nonprism/share/sounds/Makefile.in 2013-08-17 00:04:04.366224904 -0300
-@@ -151,8 +151,6 @@
- FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
- FARSTREAM_LIBS = @FARSTREAM_LIBS@
- FGREP = @FGREP@
--GADU_CFLAGS = @GADU_CFLAGS@
--GADU_LIBS = @GADU_LIBS@
- GCONFTOOL = @GCONFTOOL@
- GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
- GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
-@@ -214,8 +212,6 @@
- LTLIBOBJS = @LTLIBOBJS@
- MAKEINFO = @MAKEINFO@
- MANIFEST_TOOL = @MANIFEST_TOOL@
--MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
--MEANWHILE_LIBS = @MEANWHILE_LIBS@
- MKDIR_P = @MKDIR_P@
- MKINSTALLDIRS = @MKINSTALLDIRS@
- MONO_CFLAGS = @MONO_CFLAGS@
-diff -Nur pidgin-2.10.7/share/sounds/Makefile.mingw pidgin-2.10.7-nonprism/share/sounds/Makefile.mingw
---- pidgin-2.10.7/share/sounds/Makefile.mingw 2013-02-11 07:16:57.000000000 -0200
-+++ pidgin-2.10.7-nonprism/share/sounds/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
-@@ -1,20 +0,0 @@
--#
--# Makefile.mingw
--#
--# Description: Makefile for win32 (mingw) version of Pidgin sounds
--#
--
--PIDGIN_TREE_TOP := ../..
--include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
--
--datadir := $(PIDGIN_INSTALL_DIR)
--include ./Makefile.am
--
--.PHONY: install
--
--install:
-- if test '$(sounds_DATA)'; then \
-- mkdir -p $(soundsdir); \
-- cp $(sounds_DATA) $(soundsdir); \
-- fi;
--