diff options
Diffstat (limited to 'nonprism/pidgin-nonprism/nonprism.patch')
-rw-r--r-- | nonprism/pidgin-nonprism/nonprism.patch | 166577 |
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, "&", 5); -- break; -- case '<': -- gg_append(dst, &len, "<", 4); -- break; -- case '>': -- gg_append(dst, &len, ">", 4); -- break; -- case '\'': -- gg_append(dst, &len, "'", 6); -- break; -- case '\"': -- gg_append(dst, &len, """, 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, "<", 4) == 0) -- dst[len++] = '<'; -- else if (strncmp(entity, ">", 4) == 0) -- dst[len++] = '>'; -- else if (strncmp(entity, """, 6) == 0) -- dst[len++] = '"'; -- else if (strncmp(entity, "'", 6) == 0) -- dst[len++] = '\''; -- else if (strncmp(entity, "&", 5) == 0) -- dst[len++] = '&'; -- else if (strncmp(entity, " ", 6) == 0) { -- dst[len++] = 0xc2; -- dst[len++] = 0xa0; -- } else -- dst[len++] = '?'; -- } else { -- if (strncmp(entity, " ", 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" — wskaźnik na zmiennÄ…, gdzie zostanie umieszczony deskryptor potoku -- * - \c "void **priv_data" — wskaźnik na zmiennÄ…, gdzie można umieÅ›cić wskaźnik do prywatnych danych na potrzeby rozwiÄ…zywania nazwy -- * - \c "const char *name" — nazwa serwera do rozwiÄ…zania -- * -- * Parametry funkcji zwalniajÄ…cej zasoby wyglÄ…dajÄ… nastÄ™pujÄ…co: -- * - \c "void **priv_data" — wskaźnik na zmiennÄ… przechowujÄ…cÄ… wskaźnik do prywatnych danych, należy go ustawić na \c NULL po zakoÅ„czeniu -- * - \c "int force" — 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(¶ms[next_index].value, G_TYPE_STRING); - g_value_set_string(¶ms[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 -- * and · -- */ -- while ((p = strstr(url_buffer, " ")) != NULL) -- { -- *p = ' '; /* Turn '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, "·")) != 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 ' for apostrophes...replace them */ -- while ((p = strstr(url_buffer, "'")) != 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://spaces.live.com/profile.aspx?cid=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, "<", 4)) -- { -- msg[retcount++] = '<'; -- c += 4; -- } -- else if (!g_ascii_strncasecmp(c, ">", 4)) -- { -- msg[retcount++] = '>'; -- c += 4; -- } -- else if (!g_ascii_strncasecmp(c, " ", 6)) -- { -- msg[retcount++] = ' '; -- c += 6; -- } -- else if (!g_ascii_strncasecmp(c, """, 6)) -- { -- msg[retcount++] = '"'; -- c += 6; -- } -- else if (!g_ascii_strncasecmp(c, "&", 5)) -- { -- msg[retcount++] = '&'; -- c += 5; -- } -- else if (!g_ascii_strncasecmp(c, "'", 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, "<" ); -- break; -- case '>' : -- g_string_append( mx->msg, ">" ); -- break; -- case '&' : -- g_string_append( mx->msg, "&" ); -- break; -- case '"' : -- g_string_append( mx->msg, """ ); -- 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: -- * & " < > -- */ -- -- /* 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, ¶ms); -- -- 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, "<title>"); -- if (tmp1 != NULL) { -- tmp1 += 13; -- tmp2 = strstr(tmp1, "</title>"); -- if (tmp2 != NULL) -- g_string_append_len(xstatus, tmp1, tmp2 - tmp1); -- } -- tmp1 = strstr(xml, "<desc>"); -- if (tmp1 != NULL) { -- tmp1 += 12; -- tmp2 = strstr(tmp1, "</desc>"); -- 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><Q><PluginID>srvMng</PluginID></Q></QUERY><NOTIFY><srv><id>cAwaySrv</id><req><id>AwayStat</id><trans>2</trans><senderId>%s</senderId></req></srv></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><ret event='OnRemoteNotification'><srv><id>cAwaySrv</id><val srv_id='cAwaySrv'><Root><CASXtraSetAwayMessage></CASXtraSetAwayMessage>&l t;uin>%s</uin><index>1</index><title>%s</title><desc>%s</desc></Root></val></srv><srv><id>cRandomizerSrv</id><val srv_id='cRandomizerSrv'>undefined</val></srv></ret></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 <room>: 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 <room>: 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(¤t_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 ", NULL }, -- { DE, "Letzter Update ", NULL }, -- { EL, "Last Updated:", "http://gr.profiles.yahoo.com" }, -- { EN_GB, "Last Update ", "Favourite Quote" }, -- { EN, "Last Update:", NULL }, -- { EN, "Last Update ", NULL }, -- { ES_AR, "\332ltima actualizaci\363n ", NULL }, -- { ES_ES, "Actualizada el ", "http://es.profiles.yahoo.com" }, -- { ES_MX, "Actualizada el ", "http://mx.profiles.yahoo.com" }, -- { ES_US, "Actualizada el ", 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 ", NULL }, -- { NO, "Sist oppdatert ", NULL }, -- { PT, "\332ltima atualiza\347\343o ", NULL }, -- { PT_BR, "\332ltima atualiza\347\343o:", NULL }, -- { SV, "Senast uppdaterad ", 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; '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, " ")) != NULL) { -- *p = ' '; /* Turn '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 -- * and · -- */ -- yahoo_remove_nonbreaking_spaces(url_buffer); --#if 1 -- while ((p = strstr(url_buffer, "·")) != 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 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 <peanut>", -- yahoo_codes_to_html("plain <peanut>")); -- assert_string_equal_free("plain <peanut", -- yahoo_codes_to_html("plain <peanut")); -- assert_string_equal_free("plain> peanut", -- yahoo_codes_to_html("plain> peanut")); -- assert_string_equal_free("<font face='inva>lid'>test</font>", -- yahoo_codes_to_html("<font face='inva>lid'>test")); -- assert_string_equal_free("<font face='inva>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(":<", -- 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 <peanut>")); -- assert_string_equal_free("plain <peanut", -- yahoo_html_to_codes("plain <peanut")); -- assert_string_equal_free("plain> peanut", -- yahoo_html_to_codes("plain> peanut")); -- assert_string_equal_free("plain >", -- yahoo_html_to_codes("plain >")); -- assert_string_equal_free("plain > ", -- yahoo_html_to_codes("plain > ")); -- assert_string_equal_free("plain <", -- yahoo_html_to_codes("plain <")); -- assert_string_equal_free("plain < ", -- yahoo_html_to_codes("plain < ")); -- assert_string_equal_free("plain <", -- yahoo_html_to_codes("plain <")); -- assert_string_equal_free("plain &", -- yahoo_html_to_codes("plain &")); -- -- /* 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, ®_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, ®_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", >kwin32_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>k_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}>k_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, ×tamp); -- 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, ×tamp); -- 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) ®val, -- ®len); -- -- 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) ®val, -- 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; -- |